1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00
psalm/docs/running_psalm/issues.md
2020-03-16 09:51:45 -04:00

2758 lines
46 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Issue types
### AbstractInstantiation
Emitted when an attempt is made to instantiate an abstract class:
```php
abstract class A {}
new A();
```
### AbstractMethodCall
Emitted when an attempt is made to call an abstract static method directly
```php
abstract class Base {
abstract static function bar() : void;
}
Base::bar();
```
### ArgumentTypeCoercion
Emitted when calling a function with an argument which has a less specific type than the function expects
```php
class A {}
class B extends A {}
function takesA(A $a) : void {
takesB($a);
}
function takesB(B $b) : void {}
```
#### How to fix
You could add a typecheck before the call to `takesB`:
```php
function takesA(A $a) : void {
if ($a instanceof B) {
takesB($a);
}
}
```
Or, if you have control over the function signature of `takesA` you can change it to expect `B`:
```php
function takesA(B $a) : void {
takesB($a);
}
```
### AssignmentToVoid
Emitted when assigning from a function that returns `void`:
```php
function foo() : void {}
$a = foo();
```
#### How to fix
You should just be able to remove the assignment:
```php
function foo() : void {}
foo();
```
### CircularReference
Emitted when a class references itself as one of its parents
```php
class A extends B {}
class B extends A {}
```
### ConflictingReferenceConstraint
Emitted when a by-ref variable is set in two different branches of an if to different types.
```php
class A {
/** @var int */
private $foo;
public function __construct(int &$foo) {
$this->foo = &$foo;
}
}
class B {
/** @var string */
private $bar;
public function __construct(string &$bar) {
$this->bar = &$bar;
}
}
if (rand(0, 1)) {
$v = 5;
$c = (new A($v)); // $v is constrained to an int
} else {
$v = "hello";
$c = (new B($v)); // $v is constrained to a string
}
$v = 8;
```
### ContinueOutsideLoop
Emitted when encountering a `continue` statement outside a loop context.
```php
$a = 5;
continue;
```
### DeprecatedClass
Emitted when referring to a deprecated class:
```php
/** @deprecated */
class A {}
new A();
```
### DeprecatedConstant
Emitted when referring to a deprecated constant:
```php
class A {
/** @deprecated */
const FOO = 'foo';
}
echo A::FOO;
```
### DeprecatedFunction
Emitted when calling a deprecated function:
```php
/** @deprecated */
function foo() : void {}
foo();
```
### DeprecatedInterface
Emitted when referring to a deprecated interface
```php
/** @deprecated */
interface I {}
class A implements I {}
```
### DeprecatedMethod
Emitted when calling a deprecated method on a given class:
```php
class A {
/** @deprecated */
public function foo() : void {}
}
(new A())->foo();
```
### DeprecatedProperty
Emitted when getting/setting a deprecated property of a given class
```php
class A {
/**
* @deprecated
* @var ?string
*/
public $foo;
}
(new A())->foo = 5;
```
### DeprecatedTrait
Emitted when referring to a deprecated trait:
```php
/** @deprecated */
trait T {}
class A {
use T;
}
```
### DocblockTypeContradiction
Emitted when conditional doesn't make sense given the docblock types supplied.
```php
/**
* @param string $s
*
* @return void
*/
function foo($s) {
if ($s === 5) { }
}
```
### DuplicateArrayKey
Emitted when an array has a key more than once
```php
$arr = [
'a' => 1,
'b' => 2,
'c' => 3,
'c' => 4,
];
```
### DuplicateClass
Emitted when a class is defined twice
```php
class A {}
class A {}
```
### DuplicateFunction
Emitted when a function is defined twice
```php
function foo() : void {}
function bar() : void {}
function foo() : void {}
```
### DuplicateMethod
Emitted when a method is defined twice
```php
class A {
public function foo() {}
public function foo() {}
}
```
### DuplicateParam
Emitted when a function has a param defined twice
```php
function foo(int $b, string $b) {}
```
### EmptyArrayAccess
Emitted when attempting to access a value on an empty array
```php
$a = [];
$b = $a[0];
```
### FalsableReturnStatement
Emitted if a return statement contains a false value, but the function return type does not allow false
```php
function foo() : string {
if (rand(0, 1)) {
return "foo";
}
return false; // emitted here
}
```
### FalseOperand
Emitted when using `false` as part of an operation (e.g. `+`, `.`, `^` etc.)
```php
echo false . 'hello';
```
### ForbiddenCode
Emitted when Psalm encounters a var_dump, exec or similar expression that may make your code more vulnerable
```php
var_dump("bah");
```
### ForbiddenEcho
Emitted when Psalm encounters an echo statement and the `forbidEcho` flag in your config is set to `true`
```php
echo("bah");
```
### ImplementedParamTypeMismatch
Emitted when a class that inherits another, or implements an interface, has docblock param type that's entirely different to the parent. Subclasses of the parent return type are permitted, in docblocks.
```php
class D {
/** @param string $a */
public function foo($a): void {}
}
class E extends D {
/** @param int $a */
public function foo($a): void {}
}
```
### ImplementedReturnTypeMismatch
Emitted when a class that inherits another, or implements an interface, has docblock return type that's entirely different to the parent. Subclasses of the parent return type are permitted, in docblocks.
```php
class A {
/** @return bool */
public function foo() {
return true;
}
}
class B extends A {
/** @return string */
public function foo() {
return "hello";
}
}
```
### ImplicitToStringCast
Emitted when implicitly converting an object with a `__toString` method to a string
```php
class A {
public function __toString() {
return "foo";
}
}
function takesString(string $s) : void {}
takesString(new A);
```
### ImpureByReferenceAssignment
Emitted when assigning a passed-by-reference variable inside a function or method marked as mutation-free.
```php
/**
* @psalm-pure
*/
function foo(string &$a): string {
$a = "B";
return $a;
}
```
### ImpureFunctionCall
Emitted when calling an impure function from a function or method marked as pure.
```php
function impure(array $a) : array {
/** @var int */
static $i = 0;
++$i;
$a[$i] = 1;
return $a;
}
/** @psalm-pure */
function filterOdd(array $a) : void {
impure($a);
}
```
### ImpureMethodCall
Emitted when calling an impure method from a function or method marked as pure.
```php
class A {
public int $a = 5;
public function foo() : void {
$this->a++;
}
}
/** @psalm-pure */
function filterOdd(int $i, A $a) : ?int {
$a->foo();
if ($i % 2 === 0 || $a->a === 2) {
return $i;
}
return null;
}
```
### ImpurePropertyAssignment
Emitted when updating a property value from a function or method marked as pure.
```php
class A {
public int $a = 5;
}
/** @psalm-pure */
function filterOdd(int $i, A $a) : ?int {
$a->a++;
if ($i % 2 === 0 || $a->a === 2) {
return $i;
}
return null;
}
```
### ImpureStaticVariable
Emitted when attempting to use a static variable from a function or method marked as pure
```php
/** @psalm-pure */
function addCumulative(int $left) : int {
/** @var int */
static $i = 0;
$i += $left;
return $left;
}
```
### ImpureStaticProperty
Emitted when attempting to use a static property from a function or method marked as pure
```php
class ValueHolder {
public static ?string $value = null;
/**
* @psalm-pure
*/
public static function get(): ?string {
return self::$value;
}
}
```
### InaccessibleClassConstant
Emitted when a public/private class constant is not accessible from the calling context
```php
class A {
protected const FOO = 'FOO';
}
echo A::FOO;
```
### InaccessibleMethod
Emitted when attempting to access a protected/private method from outside its available scope
```php
class A {
protected function foo() : void {}
}
echo (new A)->foo();
```
### InterfaceInstantiation
Emitted when an attempt is made to instantiate an interface:
```php
interface I {}
new I();
```
### InaccessibleProperty
Emitted when attempting to access a protected/private property from outside its available scope
```php
class A {
/** @return string */
protected $foo;
}
echo (new A)->foo;
```
### InternalClass
Emitted when attempting to access a class marked as internal an unrelated namespace or class, or attempting
to access a class marked as psalm-internal to a different namespace.
```php
namespace A {
/**
* @internal
*/
class Foo { }
}
namespace B {
class Bat {
public function batBat() {
$a = new \A\Foo();
}
}
}
```
### InternalMethod
Emitted when attempting to access a method marked as internal an unrelated namespace or class, or attempting
to access a method marked as psalm-internal to a different namespace.
```php
namespace A {
class Foo {
/**
* @internal
*/
public static function barBar(): void {
}
}
}
namespace B {
class Bat {
public function batBat() {
\A\Foo::barBar();
}
}
}
```
### InternalProperty
Emitted when attempting to access a property marked as internal from an unrelated namespace or class, or attempting
to access a property marked as psalm-internal to a different namespace.
```php
namespace A {
class Foo {
/**
* @internal
* @var ?int
*/
public $foo;
}
}
namespace B {
class Bat {
public function batBat() : void {
echo (new \A\Foo)->foo;
}
}
}
```
### InvalidArgument
Emitted when a supplied function/method argument is incompatible with the method signature or docblock one.
```php
class A {}
function foo(A $a) : void {}
foo("hello");
```
### InvalidArrayAccess
Emitted when attempting to access an array offset on a value that does not permit it
```php
$arr = 5;
echo $arr[0];
```
### InvalidArrayAssignment
Emitted when attempting to assign a value on a non-array
```php
$arr = 5;
$arr[0] = 3;
```
### InvalidArrayOffset
Emitted when attempting to access an array using a value that's not a valid offset for that array
```php
$a = [5, 20, 18];
echo $a["hello"];
```
### InvalidCast
Emitted when attempting to cast a value that's not castable
```php
class A {}
$a = new A();
$b = (string)$a;
```
### InvalidCatch
Emitted when trying to catch a class/interface that doesn't extend `Exception` or implement `Throwable`
```php
class A {}
try {
$worked = true;
}
catch (A $e) {}
```
### InvalidClass
Emitted when referencing a class with the wrong casing
```php
class Foo {}
(new foo());
```
### InvalidStringClass
Emitted when you have `allowStringToStandInForClass="false"` in your config and youre passing a string instead of calling a class directly
```php
class Foo {}
$a = "Foo";
new $a();
```
### InvalidClone
Emitted when trying to clone a value that's not cloneable
```php
$a = "hello";
$b = clone $a;
```
### InvalidDocblock
Emitted when there's an error in a docblock type
```php
/** @var array() */
$a = [];
```
### InvalidDocblockParamName
Emitted when a docblock param name doesnt match up with a named param in the function, if the param doesnt have a type or its type is `array`.
```php
/**
* @param string[] $bar
*/
function foo(array $barb): void {
//
}
```
### InvalidFalsableReturnType
Emitted when a function can return a nullable value, but its given return type says otherwise
```php
function foo() : string {
if (rand(0, 1)) {
return "foo";
}
return false;
}
```
### InvalidFunctionCall
Emitted when calling a function on a non-callable variable
```php
$a = 5;
$b = $a();
```
### InvalidGlobal
Emitted when there's a reference to the global keyword where it's not expected
```php
global $e;
```
### InvalidIterator
Emitted when trying to iterate over a value that's not iterable
```php
$a = 5;
foreach ($a as $b) {}
```
### InvalidMethodCall
Emitted when attempting to call a method on a non-object
```php
$a = 5;
$a->foo();
```
### InvalidNullableReturnType
Emitted when a function can return a nullable value, but its given return type says otherwise
```php
function foo() : string {
if (rand(0, 1)) {
return "foo";
}
return null;
}
```
### InvalidOperand
Emitted when using something as an operand that is unexpected
```php
class A {}
echo (new A) . ' ';
```
### InvalidParamDefault
Emitted when a function parameter default clashes with the type Psalm expects the param to be
```php
function foo(int $i = false) : void {}
```
### InvalidParent
Emitted when a function return type is `parent`, but there's no parent class
```php
class Foo {
public function f(): parent {}
}
```
### InvalidPassByReference
Emitted when passing a non-variable to a function that expects a by-ref variable
```php
function foo(array &$arr) : void {}
foo([0, 1, 2]);
```
### InvalidPropertyAssignment
Emitted when attempting to assign a property to a non-object
```php
$a = "foo";
$a->bar = "bar";
```
### InvalidPropertyAssignmentValue
Emitted when attempting to assign a value to a property that cannot contain that type.
```php
class A {
/** @var string|null */
public $foo;
}
$a = new A();
$a->foo = new stdClass();
```
### InvalidPropertyFetch
Emitted when attempting to get a property from a non-object
```php
$a = "foo";
echo $a->bar;
```
### InvalidReturnStatement
Emitted when a function return statement is incorrect
```php
function foo() : string {
return 5; // emitted here
}
```
### InvalidReturnType
Emitted when a functions signature return type is incorrect (often emitted with `InvalidReturnStatement`)
```php
function foo() : int {
if (rand(0, 1)) {
return "hello";
}
return 5;
}
```
### InvalidScalarArgument
Emitted when a scalar value is passed to a method that expected another scalar type
```php
function foo(int $i) : void {}
function bar(string $s) : void {
if (is_numeric($s)) {
foo($s);
}
}
```
### InvalidScope
Emitted when referring to `$this` outside a class
```php
echo $this;
```
### InvalidStaticInvocation
Emitted when trying to call an instance function statically
```php
class A {
/** @var ?string */
public $foo;
public function bar() : void {
echo $this->foo;
}
}
A::bar();
```
### InvalidTemplateParam
Emitted when using the `@extends`/`@implements` annotation to extend a class that has a template type constraint, where that extended value does not satisfy the parent class/interface's constraints.
```php
/**
* @template T as object
*/
class Base {}
/** @template-extends Base<int> */
class SpecializedByInheritance extends Base {}
```
### InvalidThrow
Emitted when trying to throw a class that doesn't extend `Exception` or implement `Throwable`
```php
class A {}
throw new A();
```
### InvalidToString
Emitted when a `__toString` method does not always return a `string`
```php
class A {
public function __toString() {
return true;
}
}
```
### LessSpecificImplementedReturnType
Emitted when a class implements an interface method but its return type is less specific than the interface method return type
```php
class A {}
class B extends A {}
interface I {
/** @return B[] */
public function foo();
}
class D implements I {
/** @return A[] */
public function foo() {
return [new A, new A];
}
}
```
### LessSpecificReturnStatement
Emitted when a return statement is more general than the return type given for the function
```php
class A {}
class B extends A {}
function foo() : B {
return new A(); // emitted here
}
```
### LessSpecificReturnType
Emitted when a return type covers more possibilities than the function itself
```php
function foo() : ?int {
return 5;
}
```
### LoopInvalidation
Emitted when logic inside a loop invalidates one of the conditionals of the loop
```php
for ($i = 0; $i < 10; $i++) {
$i = 5;
}
```
### MethodSignatureMismatch
Emitted when a method parameter differs from a parent method parameter, or if there are fewer parameters than the parent method
```php
class A {
public function foo(int $i) : void {}
}
class B extends A {
public function foo(string $s) : void {}
}
```
### MethodSignatureMustOmitReturnType
Emitted when a `__clone`, `__construct`, or `__destruct` method is defined with a return type.
```php
class A {
public function __clone() : void {}
}
```
### MismatchingDocblockParamType
Emitted when an `@param` entry in a functions docblock doesnt match the param typehint,
```php
class A {}
class B {}
/**
* @param B $b // emitted here
*/
function foo(A $b) : void {}
```
This, however, is fine:
```php
class A {}
class B extends A {}
/**
* @param B
*/
function foo(A $b) : void {}
```
### MismatchingDocblockReturnType
Emitted when an `@return` entry in a functions docblock doesnt match the function return typehint
```php
class A {}
class B {}
/**
* @return B // emitted here
*/
function foo() : A {
return new A();
}
```
This, however, is fine:
```php
class A {}
class B extends A {}
/**
* @return B // emitted here
*/
function foo() : A {
return new B();
}
```
### MismatchingDocblockParamType
Emitted when an `@param` entry in a functions docblock doesnt match the param typehint
```php
/**
* @param int $b
*/
function foo(string $b) : void {}
```
### MissingClosureParamType
Emitted when a closure parameter has no type information associated with it
```php
$a = function($a): string {
return "foo";
};
```
### MissingClosureReturnType
Emitted when a closure lacks a return type
```php
$a = function() {
return "foo";
};
```
### MissingConstructor
Emitted when non-null properties without default values are defined in a class without a `__construct` method
```php
class A {
/** @var string */
public $foo;
}
```
### MissingDependency
Emitted when referencing a class that doesnt exist
```php
/**
* @psalm-suppress UndefinedClass
*/
class A extends B {}
$a = new A();
```
### MissingDocblockType
Emitted when a docblock is present, but the type is missing or badly formatted
```php
/** @var $a */
$a = [];
```
### MissingFile
Emitted when using `include` or `require` on a file that does not exist
```php
require("nonexistent.php");
```
### MissingImmutableAnnotation
Emitted when a class inheriting from an immutable interface or class does not also have a `@psalm-immutable` declaration
```php
/** @psalm-immutable */
interface SomethingImmutable {
public function someInteger() : int;
}
class MutableImplementation implements SomethingImmutable {
private int $counter = 0;
public function someInteger() : int {
return ++$this->counter;
}
}
```
### MissingParamType
Emitted when a function parameter has no type information associated with it
```php
function foo($a) : void {}
```
### MissingPropertyType
Emitted when a property is defined on a class without a type
```php
class A {
public $foo = 5;
}
```
### MissingReturnType
Emitted when a function doesn't have a return type defined
```php
function foo() {
return "foo";
}
```
### MissingTemplateParam
Emitted when using the `@extends`/`@implements` annotation to extend a class without
extending all its template params.
```php
/**
* @template-implements ArrayAccess<int>
*/
class SomeIterator implements ArrayAccess
{
public function offsetSet($offset, $value) {
}
public function offsetExists($offset) {
return false;
}
public function offsetUnset($offset) {
}
public function offsetGet($offset) {
return null;
}
}
```
### MissingThrowsDocblock
Emitted when a function doesn't have a return type defined
```php
function foo(int $x, int $y) : int {
if ($y === 0) {
throw new \InvalidArgumentException('Cannot divide by zero');
}
return intdiv($x, $y);
}
```
### MixedArgument
Emitted when Psalm cannot determine the type of an argument
```php
function takesInt(int $i) : void {}
takesInt($_GET['foo']);
```
### MixedArgumentTypeCoercion
Emitted when Psalm cannot be sure that part of an array/iterabble argument's type constraints can be fulfilled
```php
function foo(array $a) : void {
takesStringArray($a);
}
/** @param string[] $a */
function takesStringArray(array $a) : void {}
```
### MixedArrayAccess
Emitted when trying to access an array offset on a value whose type Psalm cannot determine
```php
echo $_GET['foo'][0];
```
### MixedArrayAssignment
Emitted when trying to assign a value to an array offset on a value whose type Psalm cannot determine
```php
$_GET['foo'][0] = "5";
```
### MixedArrayOffset
Emitted when attempting to access an array offset where Psalm cannot determine the offset type
```php
echo [1, 2, 3][$_GET['foo']];
```
### MixedArrayTypeCoercion
Emitted when trying to access an array with a less specific offset than is expected
```php
/**
* @param array<array-key, int> $a
* @param array<int, string> $b
*/
function foo(array $a, array $b) : void {
foreach ($a as $j => $k) {
echo $b[$j];
}
}
```
### MixedAssignment
Emitted when assigning an unannotated variable to a value for which Psalm
cannot infer a type more specific than `mixed`.
```php
$a = $_GET['foo'];
```
#### How to fix
The above example can be fixed in a few ways by adding an `assert` call:
```php
$a = $_GET['foo'];
assert(is_string($a));
```
or by adding an explicit cast:
```php
$a = (string) $_GET['foo'];
```
or by adding a docblock
```php
/** @var string */
$a = $_GET['foo'];
```
### MixedFunctionCall
Emitted when calling a function on a value whose type Psalm cannot infer.
```php
/** @var mixed */
$a = $_GET['foo'];
$a();
```
### MixedInferredReturnType
Emitted when Psalm cannot determine a function's return type
```php
function foo() : int {
return $_GET['foo'];
}
```
### MixedMethodCall
Emitted when calling a method on a value that Psalm cannot infer a type for
```php
/** @param mixed $a */
function foo($a) : void {
$a->foo();
}
```
### MixedOperand
Emitted when Psalm cannot infer a type for an operand in any calculated expression
```php
echo $_GET['foo'] + "hello";
```
### MixedPropertyAssignment
Emitted when assigning a property to a value for which Psalm cannot infer a type
```php
/** @param mixed $a */
function foo($a) : void {
$a->foo = "bar";
}
```
### MixedPropertyFetch
Emitted when retrieving a property on a value for which Psalm cannot infer a type
```php
/** @param mixed $a */
function foo($a) : void {
echo $a->foo;
}
```
### MixedPropertyTypeCoercion
Emitted when Psalm cannot be sure that part of an array/iterabble argument's type constraints can be fulfilled
```php
class A {
/** @var string[] */
public $takesStringArray = [];
}
function foo(A $a, array $arr) : void {
$a->takesStringArray = $arr;
}
```
### MixedReturnStatement
Emitted when Psalm cannot determine the type of a given return statement
```php
function foo() : int {
return $_GET['foo']; // emitted here
}
```
### MixedReturnTypeCoercion
Emitted when Psalm cannot be sure that part of an array/iterabble return type's constraints can be fulfilled
```php
/**
* @return string[]
*/
function foo(array $a) : array {
return $a;
}
```
### MixedStringOffsetAssignment
Emitted when assigning a value on a string using a value for which Psalm cannot infer a type
```php
"hello"[0] = $_GET['foo'];
```
### MoreSpecificImplementedParamType
Emitted when a class implements an interface method but a param type is less specific than the interface method param type
```php
class A {}
class B extends A {
public function bar(): void {}
}
class C extends A {
public function bar(): void {}
}
class D {
public function foo(A $a): void {}
}
class E extends D {
/** @param B|C $a */
public function foo(A $a): void {
$a->bar();
}
}
```
### MoreSpecificReturnType
Emitted when the declared return type for a method is more specific than the inferred one (emitted in the same methods that `LessSpecificReturnStatement` is)
```php
class A {}
class B extends A {}
function foo() : B {
/** @psalm-suppress LessSpecificReturnStatement */
return new A();
}
```
### MutableDependency
Emitted when an immutable class inherits from a class or trait not marked immutable
```php
class MutableParent {
public int $i = 0;
public function increment() : void {
$this->i++;
}
}
/**
* @psalm-immutable
*/
final class NotReallyImmutableClass extends MutableParent {}
```
### NoValue
Emitted when using the result of a function that never returns.
```php
/**
* @return never-returns
*/
function foo() : void {
exit();
}
$a = foo();
```
### NoInterfaceProperties
Emitted when trying to fetch a property on an interface as interfaces, by definition, do not have definitions for properties.
```php
interface I {}
class A implements I {
/** @var ?string */
public $foo;
}
function bar(I $i) : void {
if ($i->foo) {}
}
```
### NonStaticSelfCall
Emitted when calling a non-static function statically
```php
class A {
public function foo(): void {}
public static function bar(): void {
self::foo();
}
}
```
### NullableReturnStatement
Emitted if a return statement contains a null value, but the function return type is not nullable
```php
function foo() : string {
if (rand(0, 1)) {
return "foo";
}
return null; // emitted here
}
```
### NullArgument
Emitted when calling a function with a null value argument when the function does not expect it
```php
function foo(string $s) : void {}
foo(null);
```
### NullArrayAccess
Emitted when trying to access an array value on `null`
```php
$arr = null;
echo $arr[0];
```
### NullArrayOffset
Emitted when trying to access an array offset with `null`
```php
$arr = ['' => 5, 'foo' => 1];
echo $arr[null];
```
### NullFunctionCall
Emitted when trying to use `null` as a `callable`
```php
$arr = null;
echo $arr();
```
### NullIterator
Emitted when iterating over `null`
```php
foreach (null as $a) {}
```
### NullOperand
Emitted when using `null` as part of an operation (e.g. `+`, `.`, `^` etc.)
```php
echo null . 'hello';
```
### NullPropertyAssignment
Emitted when trying to set a property on `null`
```php
$a = null;
$a->foo = "bar";
```
### NullPropertyFetch
Emitted when trying to fetch a property on a `null` value
```php
$a = null;
echo $a->foo;
```
### NullReference
Emitted when attempting to call a method on `null`
```php
$a = null;
$a->foo();
```
### OverriddenMethodAccess
Emitted when a method is less accessible than its parent
```php
class A {
public function foo() : void {}
}
class B extends A {
protected function foo() : void {}
}
```
### OverriddenPropertyAccess
Emitted when a property is less accessible than the same-named property in its parent class
```php
class A {
/** @var string|null */
public $foo;
}
class B extends A {
/** @var string|null */
protected $foo;
}
```
### ParadoxicalCondition
Emitted when a paradox is encountered in your programs logic that could not be caught by `RedundantCondition`
```php
function foo($a) : void {
if ($a) return;
if ($a) echo "cannot happen";
}
```
### ParentNotFound
Emitted when using `parent::` in a class without a parent class.
```php
class A {
public function foo() : void {
parent::foo();
}
}
```
### ParseError
Emitted when the PHP Parser encounters an error.
```php
class A {
public function foo() : void {
echo "foo"
}
}
```
### PluginIssue
Can be emitted by plugins.
### PossibleRawObjectIteration
Emitted when possibly iterating over an objects properties, the comparison to [RawObjectIteration](#rawobjectiteration).
```php
class A {
/** @var string|null */
public $foo;
/** @var string|null */
public $bar;
}
function takesA(A $a) {
if (rand(0, 1)) {
$a = [1, 2, 3];
}
foreach ($a as $property) {}
}
```
### PossiblyFalseArgument
Emitted when a function argument is possibly `false`, but the function doesnt expect `false`. This is distinct from a function argument is possibly `bool`, which results in `PossiblyInvalidArgument`.
```php
function foo(string $s) : void {
$a_pos = strpos($s, "a");
echo substr($s, $a_pos);
}
```
### PossiblyFalseIterator
Emitted when trying to iterate over a value that may be `false`
```php
$arr = rand(0, 1) ? [1, 2, 3] : false;
foreach ($arr as $a) {}
```
### PossiblyFalseOperand
Emitted when using a possibly `false` value as part of an operation (e.g. `+`, `.`, `^` etc).
```php
function foo(string $a) : void {
echo strpos($a, ":") + 5;
}
```
### PossiblyFalsePropertyAssignmentValue
Emitted when trying to assign a value that may be false to a property that only takes non-false values.
```php
class A {
/** @var int */
public $foo = 0;
}
function assignToA(string $s) {
$a = new A();
$a->foo = strpos("haystack", $s);
}
```
### PossiblyFalseReference
Emitted when making a method call on a value than might be `false`
```php
class A {
public function bar() : void {}
}
/** @return A|false */
function foo() {
return rand(0, 1) ? new A : false;
}
foo()->bar();
```
### PossiblyInvalidArgument
Emitted when
```php
/** @return int|stdClass */
function foo() {
return rand(0, 1) ? 5 : new stdClass;
}
function bar(int $i) : void {}
bar(foo());
```
### PossiblyInvalidArrayAccess
Emitted when attempting to access an array offset on a value that may not be an array
```php
$arr = rand(0, 1) ? 5 : [4, 3, 2, 1];
echo $arr[0];
```
### PossiblyInvalidArrayAssignment
Emitted when attempting to assign an array offset on a value that may not be an array
```php
$arr = rand(0, 1) ? 5 : [4, 3, 2, 1];
$arr[0] = "hello";
```
### PossiblyInvalidCast
Emitted when attempting to cast a value that may not be castable
```php
class A {}
class B {
public function __toString() {
return 'hello';
}
}
$c = (string) (rand(0, 1) ? new A() : new B());
```
### PossiblyInvalidArrayOffset
Emitted when its possible that the array offset is not applicable to the value youre trying to access.
```php
$arr = rand(0, 1) ? ["a" => 5] : "hello";
echo $arr[0];
```
### PossiblyInvalidFunctionCall
Emitted when trying to call a function on a value that may not be callable
```php
$a = rand(0, 1) ? 5 : function() : int { return 5; };
$b = $a();
```
### PossiblyInvalidIterator
Emitted when trying to iterate over a value that may be invalid
```php
$arr = rand(0, 1) ? [1, 2, 3] : "hello";
foreach ($arr as $a) {}
```
### PossiblyInvalidMethodCall
Emitted when trying to call a method on a value that may not be an object
```php
class A {
public function bar() : void {}
}
/** @return A|int */
function foo() {
return rand(0, 1) ? new A : 5;
}
foo()->bar();
```
### PossiblyInvalidOperand
Emitted when using a possibly invalid value as part of an operation (e.g. `+`, `.`, `^` etc.
```php
function foo() : void {
$b = rand(0, 1) ? [] : 4;
echo $b + 5;
}
```
### PossiblyInvalidPropertyAssignment
Emitted when trying to assign a property on a value that may not be an object or may be an object that doesnt have the desired property.
```php
class A {
/** @var ?string */
public $bar;
}
/** @return A|int */
function foo() {
return rand(0, 1) ? new A : 5;
}
$a = foo();
$a->bar = "5";
```
### PossiblyInvalidPropertyAssignmentValue
Emitted when trying to assign a possibly invalid value to a typed property.
```php
class A {
/** @var int[] */
public $bb = [];
}
class B {
/** @var string[] */
public $bb;
}
$c = rand(0, 1) ? new A : new B;
$c->bb = ["hello", "world"];
```
### PossiblyInvalidPropertyFetch
Emitted when trying to fetch a property on a value that may not be an object or may be an object that doesnt have the desired property.
```php
class A {
/** @var ?string */
public $bar;
}
/** @return A|int */
function foo() {
return rand(0, 1) ? new A : 5;
}
$a = foo();
echo $a->bar;
```
### PossiblyNullArgument
Emitted when calling a function with a value thats possibly null when the function does not expect it
```php
function foo(string $s) : void {}
foo(rand(0, 1) ? "hello" : null);
```
### PossiblyNullArrayAccess
Emitted when trying to access an array offset on a possibly null value
```php
function foo(?array $a) : void {
echo $a[0];
}
```
### PossiblyNullArrayAssignment
Emitted when trying to set a value on a possibly null array
```php
$a = null;
$a[0][] = 1;
```
### PossiblyNullArrayOffset
Emitted when trying to access a value on an array using a possibly null offset
```php
function foo(?int $a) : void {
echo [1, 2, 3, 4][$a];
}
```
### PossiblyNullFunctionCall
Emitted when trying to call a function on a value that may be null
```php
function foo(?callable $a) : void {
$a();
}
```
### PossiblyNullIterator
Emitted when trying to iterate over a value that may be null
```php
function foo(?array $arr) : void {
foreach ($arr as $a) {}
}
```
### PossiblyNullOperand
Emitted when using a possibly `null` value as part of an operation (e.g. `+`, `.`, `^` etc.)
```php
function foo(?int $a) : void {
echo $a + 5;
}
```
### PossiblyNullPropertyAssignment
Emitted when trying to assign a property to a possibly null object
```php
class A {
/** @var ?string */
public $foo;
}
function foo(?A $a) : void {
$a->foo = "bar";
}
```
### PossiblyNullPropertyAssignmentValue
Emitted when trying to assign a value that may be null to a property that only takes non-null values.
```php
class A {
/** @var string */
public $foo = "bar";
}
function assignToA(?string $s) {
$a = new A();
$a->foo = $s;
}
```
### PossiblyNullPropertyFetch
Emitted when trying to fetch a property on a possibly null object
```php
class A {
/** @var ?string */
public $foo;
}
function foo(?A $a) : void {
echo $a->foo;
}
```
### PossiblyNullReference
Emitted when trying to call a method on a possibly null value
```php
class A {
public function bar() : void {}
}
function foo(?A $a) : void {
$a->bar();
}
```
### PossiblyUndefinedArrayOffset
Emitted when trying to access a possibly undefined array offset
```php
if (rand(0, 1)) {
$arr = ["a" => 1, "b" => 2];
} else {
$arr = ["a" => 3];
}
echo $arr["b"];
```
### PossiblyUndefinedIntArrayOffset
Emitted when the config flag `ensureArrayIntOffsetsExist` is set to `true` and an integer-keyed offset is not checked for existence
```php
/**
* @param array<int, string> $arr
*/
function foo(array $arr) : void {
echo $arr[0];
}
```
### PossiblyUndefinedStringArrayOffset
Emitted when the config flag `ensureArrayStringOffsetsExist` is set to `true` and an integer-keyed offset is not checked for existence
```php
/**
* @param array<string, string> $arr
*/
function foo(array $arr) : void {
echo $arr["hello"];
}
```
### PossiblyUndefinedGlobalVariable
Emitted when trying to access a variable in the global scope that may not be defined
```php
if (rand(0, 1)) {
$a = 5;
}
echo $a;
```
### PossiblyUndefinedMethod
Emitted when trying to access a method that may not be defined on the object
```php
class A {
public function bar() : void {}
}
class B {}
$a = rand(0, 1) ? new A : new B;
$a->bar();
```
### PossiblyUndefinedVariable
Emitted when trying to access a variable in function scope that may not be defined
```php
function foo() : void {
if (rand(0, 1)) {
$a = 5;
}
echo $a;
}
```
### PossiblyUnusedMethod
Emitted when `--find-dead-code` is turned on and Psalm cannot find any calls to a given class method
```php
class A {
public function foo() : void {}
public function bar() : void {}
}
(new A)->foo();
```
### PossiblyUnusedParam
Emitted when `--find-dead-code` is turned on and Psalm cannot find any uses of a particular parameter in a public/protected method
```php
class A {
public function foo(int $a, int $b) : int {
return $a + 4;
}
}
$a = new A();
$a->foo(1, 2);
```
### PossiblyUnusedProperty
Emitted when `--find-dead-code` is turned on and Psalm cannot find any uses of a particular public/protected property
```php
class A {
/** @var string|null */
public $foo;
/** @var int|null */
public $bar;
}
$a = new A();
echo $a->foo;
```
### PropertyNotSetInConstructor
Emitted when a non-null property without a default value is declared but not set in the classs constructor
```php
class A {
/** @var string */
public $foo;
public function __construct() {}
}
```
### PropertyTypeCoercion
Emitted when setting a property with an value which has a less specific type than the property expects
```php
class A {}
class B extends A {}
function takesA(C $c, A $a) : void {
$c->b = $a;
}
class C {
/** @var ?B */
public $b;
}
```
### RawObjectIteration
Emitted when iterating over an objects properties. This issue exists because it may be undesired behaviour (e.g. you may have meant to iterate over an array)
```php
class A {
/** @var string|null */
public $foo;
/** @var string|null */
public $bar;
}
function takesA(A $a) {
foreach ($a as $property) {}
}
```
### RedundantCondition
Emitted when conditional is redundant given previous assertions
```php
class A {}
function foo(A $a) : ?A {
if ($a) return $a;
return null;
}
```
### RedundantConditionGivenDocblockType
Emitted when conditional is redundant given information supplied in one or more docblocks.
This may be desired (e.g. when checking user input) so is distinct from RedundantCondition, which only applies to non-docblock types.
```php
/**
* @param string $s
*
* @return void
*/
function foo($s) {
if (is_string($s)) {};
}
```
### ReferenceConstraintViolation
Emitted when changing the type of a pass-by-reference variable
```php
function foo(string &$a) {
$a = 5;
}
```
### ReservedWord
Emitted when using a reserved word as a class name
```php
function foo(resource $res) : void {}
```
### StringIncrement
Emitted when attempting to increment a string - this works in PHP, but is unexpected behaviour for most people.
```php
$a = "hello";
$a++;
```
### TaintedInput
Emitted when tainted input detection is turned on
### TraitMethodSignatureMismatch
Emitted when a method's signature or return type differs from corresponding trait-defined method
```php
trait T {
abstract public function foo(int $i);
}
class A {
use T;
public function foo(string $s) : void {}
}
```
### TooFewArguments
Emitted when calling a function with fewer arguments than the function has parameters
```php
function foo(string $a) : void {}
foo();
```
### TooManyArguments
Emitted when calling a function with more arguments than the function has parameters
```php
function foo(string $a) : void {}
foo("hello", 4);
```
### TooManyTemplateParams
Emitted when using the `@extends`/`@implements` annotation to extend a class and adds too
many types.
```php
/**
* @template-implements IteratorAggregate<int, string, int>
*/
class SomeIterator implements IteratorAggregate
{
public function getIterator() {
yield 5;
}
}
```
### TypeDoesNotContainNull
Emitted when checking a non-nullable type for `null`
```php
$a = "hello";
if ($a === null) {}
```
### TypeDoesNotContainType
Emitted checking whether one value has a type or value that is impossible given its currently-known type
```php
$a = "hello";
if ($a === 5) {}
```
### UncaughtThrowInGlobalScope
Emitted when a possible exception isn't caught in global scope
```php
/**
* @throws \Exception
*/
function foo() : int {
return random_int(0, 1);
}
foo();
```
### UndefinedClass
Emitted when referencing a class that doesnt exist
```php
$a = new A();
```
### UndefinedConstant
Emitted when referencing a constant that doesnt exist
```php
echo FOO_BAR;
```
### UndefinedDocblockClass
Emitted when referencing a class that doesnt exist from a docblock
```php
/**
* @param DoesNotExist $a
*/
function foo($a) : void {}
```
### UndefinedFunction
Emitted when referencing a function that doesn't exist
```php
foo();
```
### UndefinedGlobalVariable
Emitted when referencing a variable that doesn't exist
```php
echo $a;
```
### UndefinedInterface
Emitted when referencing an interface that doesnt exist but does have an identically-named class.
```php
class C {}
interface I extends C {}
```
### UndefinedMagicMethod
Emitted when calling a magic method that doesnt exist
```php
/**
* @method bar():string
*/
class A {
public function __call(string $name, array $args) {
return "cool";
}
}
(new A)->foo();
```
### UndefinedMagicPropertyAssignment
Emitted when assigning a property on an object that doesnt have that magic property defined
```php
/**
* @property string $bar
*/
class A {
/** @param mixed $value */
public function __set(string $name, $value) {}
}
$a = new A();
$a->foo = "bar";
```
### UndefinedMagicPropertyFetch
Emitted when getting a property on an object that doesnt have that magic property defined
```php
/**
* @property string $bar
*/
class A {
public function __get(string $name) {
return "cool";
}
}
$a = new A();
echo $a->foo;
```
### UndefinedMethod
Emitted when calling a method that doesnt exist
```php
class A {}
A::foo();
```
### UndefinedInterfaceMethod
Emitted when calling a method that doesnt exist on an interface
```php
interface I {}
function foo(I $i) {
$i->bar();
}
```
### UndefinedPropertyAssignment
Emitted when assigning a property on an object that doesnt have that property defined
```php
class A {}
$a = new A();
$a->foo = "bar";
```
### UndefinedPropertyFetch
Emitted when getting a property on an object that doesnt have that property defined
```php
class A {}
$a = new A();
echo $a->foo;
```
### UndefinedThisPropertyAssignment
Emitted when assigning a property on an object in one of that objects methods when no such property exists
```php
class A {
function foo() {
$this->foo = "bar";
}
}
```
### UndefinedThisPropertyFetch
Emitted when getting a property for an object in one of that objects methods when no such property exists
```php
class A {
function foo() {
echo $this->foo;
}
}
```
### UndefinedTrait
Emitted when referencing a trait that doesnt exist
```php
class A {
use T;
}
```
### UndefinedVariable
Emitted when referencing a variable that doesn't exist in a given functions scope
```php
function foo() {
echo $a;
}
```
### UnevaluatedCode
Emitted when `--find-dead-code` is turned on and Psalm encounters code that will not be evaluated
```php
function foo() : void {
return;
$a = "foo";
}
```
### UnimplementedAbstractMethod
Emitted when a class extends another, but does not implement all of its abstract methods
```php
abstract class A {
abstract public function foo() : void;
}
class B extends A {}
```
### UnimplementedInterfaceMethod
Emitted when a class `implements` an interface but does not implement all of its methods
```php
interface I {
public function foo() : void;
}
class A implements I {}
```
### UninitializedProperty
Emitted when a property is used in a constructor before it is initialized
```php
class A {
/** @var string */
public $foo;
public function __construct() {
echo strlen($this->foo);
$this->foo = "foo";
}
}
```
### UnnecessaryVarAnnotation
Emitted when `--find-dead-code` is turned on and you're using a `@var` annotation on an assignment that Psalm has already identified a type for.
```php
function foo() : string {
return "hello";
}
/** @var string */
$a = foo();
```
### UnrecognizedExpression
Emitted when Psalm encounters an expression that it doesn't know how to handle. This should never happen.
### UnrecognizedStatement
Emitted when Psalm encounters a code construct that it doesn't know how to handle. This should never happen.
### UnresolvableInclude
Emitted when Psalm cannot figure out what specific file is being included/required by PHP.
```php
function requireFile(string $s) : void {
require_once($s);
}
```
### UnusedClass
Emitted when `--find-dead-code` is turned on and Psalm cannot find any uses of a given class
```php
class A {}
class B {}
$a = new A();
```
### UnusedMethod
Emitted when `--find-dead-code` is turned on and Psalm cannot find any uses of a given private method or function
```php
class A {
public function __construct() {
$this->foo();
}
private function foo() : void {}
private function bar() : void {}
}
$a = new A();
```
### UnusedClosureParam
Emitted when `--find-dead-code` is turned on and Psalm cannot find any uses of a particular parameter in a closure.
```php
$a = function (int $a, int $b) : int {
return $a + 4;
};
/**
* @param callable(int,int):int $c
*/
function foo(callable $c) : int {
return $c(2, 4);
}
```
### UnusedFunctionCall
Emitted when `--find-dead-code` is turned on and Psalm finds a function call whose return value is not used anywhere
```php
$a = strlen("hello");
strlen("goodbye"); // unused
echo $a;
```
### UnusedMethodCall
Emitted when `--find-dead-code` is turned on and Psalm finds a method call whose return value is not used anywhere
```php
class A {
private string $foo;
public function __construct(string $foo) {
$this->foo = $foo;
}
public function getFoo() : string {
return $this->foo;
}
}
$a = new A("hello");
$a->getFoo();
```
### UnusedParam
Emitted when `--find-dead-code` is turned on and Psalm cannot find any uses of a particular parameter in a private method or function
```php
function foo(int $a, int $b) : int {
return $a + 4;
}
```
### UnusedProperty
Emitted when `--find-dead-code` is turned on and Psalm cannot find any uses of a private property
```php
class A {
/** @var string|null */
private $foo;
/** @var int|null */
private $bar;
public function getFoo(): ?string {
return $this->foo;
}
}
$a = new A();
echo $a->getFoo();
```
### UnusedPsalmSuppress
Emitted when `--find-unused-psalm-suppress` is turned on and Psalm cannot find any uses of a given `@psalm-suppress` annotation
```php
/** @psalm-suppress InvalidArgument */
echo strpos("hello", "e");
```
### UnusedVariable
Emitted when `--find-dead-code` is turned on and Psalm cannot find any references to a variable, once instantiated
```php
function foo() : void {
$a = 5;
$b = 4;
echo $b;
}
```