39 KiB
Issue types
AbstractInstantiation
Emitted when an attempt is made to instantiate an abstract class:
abstract class A {}
new A();
ArgumentTypeCoercion
Emitted when calling a function with an argument which has a less specific type than the function expects
class A {}
class B extends A {}
function takesA(A $a) : void {
takesB($a);
}
function takesB(B $b) : void {}
AssignmentToVoid
Emitted when assigning from a function that returns void
:
function foo() : void {}
$a = foo();
CircularReference
Emitted when a class references itself as one of its parents
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.
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.
$a = 5;
continue;
DeprecatedClass
Emitted when referring to a deprecated class:
/** @deprecated */
class A {}
new A();
DeprecatedConstant
Emitted when referring to a deprecated constant:
class A {
/** @deprecated */
const FOO = 'foo';
}
echo A::FOO;
DeprecatedInterface
Emitted when referring to a deprecated interface
/** @deprecated */
interface I {}
class A implements I {}
DeprecatedMethod
Emitted when calling a deprecated method on a given class:
class A {
/** @deprecated */
public function foo() : void {}
}
(new A())->foo();
DeprecatedProperty
Emitted when getting/setting a deprecated property of a given class
class A {
/**
* @deprecated
* @var ?string
*/
public $foo;
}
(new A())->foo = 5;
DeprecatedTrait
Emitted when referring to a deprecated trait:
/** @deprecated */
trait T {}
class A {
use T;
}
DocblockTypeContradiction
Emitted when conditional doesn't make sense given the docblock types supplied.
/**
* @param string $s
*
* @return void
*/
function foo($s) {
if ($s === 5) { }
}
DuplicateArrayKey
Emitted when an array has a key more than once
$arr = [
'a' => 1,
'b' => 2,
'c' => 3,
'c' => 4,
];
DuplicateClass
Emitted when a class is defined twice
class A {}
class A {}
DuplicateFunction
Emitted when a function is defined twice
function foo() : void {}
function bar() : void {}
function foo() : void {}
DuplicateMethod
Emitted when a method is defined twice
class A {
public function foo() {}
public function foo() {}
}
DuplicateParam
Emitted when a function has a param defined twice
function foo(int $b, string $b) {}
EmptyArrayAccess
Emitted when attempting to access a value on an empty array
$a = [];
$b = $a[0];
FalsableReturnStatement
Emitted if a return statement contains a false value, but the function return type does not allow false
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.)
echo false . 'hello';
ForbiddenCode
Emitted when Psalm encounters a var_dump, exec or similar expression that may make your code more vulnerable
var_dump("bah");
ForbiddenEcho
Emitted when Psalm encounters an echo statement and the forbidEcho
flag in your config is set to true
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.
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.
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
class A {
public function __toString() {
return "foo";
}
}
function takesString(string $s) : void {}
takesString(new A);
InaccessibleClassConstant
Emitted when a public/private class constant is not accessible from the calling context
class A {
protected const FOO = 'FOO';
}
echo A::FOO;
InaccessibleMethod
Emitted when attempting to access a protected/private method from outside its available scope
class A {
protected function foo() : void {}
}
echo (new A)->foo();
InterfaceInstantiation
Emitted when an attempt is made to instantiate an interface:
interface I {}
new I();
InaccessibleProperty
Emitted when attempting to access a protected/private property from outside its available scope
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.
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.
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.
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.
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
$arr = 5;
echo $arr[0];
InvalidArrayAssignment
Emitted when attempting to assign a value on a non-array
$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
$a = [5, 20, 18];
echo $a["hello"];
InvalidCast
Emitted when attempting to cast a value that's not castable
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
class A {}
try {
$worked = true;
}
catch (A $e) {}
InvalidClass
Emitted when referencing a class with the wrong casing
class Foo {}
(new foo());
InvalidStringClass
Emitted when you have allowStringToStandInForClass="false"
in your config and you’re passing a string instead of calling a class directly
class Foo {}
$a = "Foo";
new $a();
InvalidClone
Emitted when trying to clone a value that's not cloneable
$a = "hello";
$b = clone $a;
InvalidDocblock
Emitted when there's an error in a docblock type
/** @var array() */
$a = [];
InvalidDocblockParamName
Emitted when a docblock param name doesn’t match up with a named param in the function.
/**
* @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
function foo() : string {
if (rand(0, 1)) {
return "foo";
}
return false;
}
InvalidFunctionCall
Emitted when calling a function on a non-callable variable
$a = 5;
$b = $a();
InvalidGlobal
Emitted when there's a reference to the global keyword where it's not expected
global $e;
InvalidIterator
Emitted when trying to iterate over a value that's not iterable
$a = 5;
foreach ($a as $b) {}
InvalidMethodCall
Emitted when attempting to call a method on a non-object
$a = 5;
$a->foo();
InvalidNullableReturnType
Emitted when a function can return a nullable value, but its given return type says otherwise
function foo() : string {
if (rand(0, 1)) {
return "foo";
}
return null;
}
InvalidOperand
Emitted when using something as an operand that is unexpected
class A {}
echo (new A) . ' ';
InvalidParamDefault
Emitted when a function parameter default clashes with the type Psalm expects the param to be
function foo(int $i = false) : void {}
InvalidPassByReference
Emitted when passing a non-variable to a function that expects a by-ref variable
function foo(array &$arr) : void {}
foo([0, 1, 2]);
InvalidPropertyAssignment
Emitted when attempting to assign a property to a non-object
$a = "foo";
$a->bar = "bar";
InvalidPropertyAssignmentValue
Emitted when attempting to assign a value to a property that cannot contain that type.
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
$a = "foo";
echo $a->bar;
InvalidReturnStatement
Emitted when a function return statement is incorrect
function foo() : string {
return 5; // emitted here
}
InvalidReturnType
Emitted when a function’s signature return type is incorrect (often emitted with `InvalidReturnStatement`)
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
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
echo $this;
InvalidStaticInvocation
Emitted when trying to call an instance function statically
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.
/**
* @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
class A {}
throw new A();
InvalidToString
Emitted when a __toString
method does not always return a string
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
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
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
function foo() : ?int {
return 5;
}
LoopInvalidation
Emitted when logic inside a loop invalidates one of the conditionals of the loop
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
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.
class A {
public function __clone() : void {}
}
MismatchingDocblockParamType
Emitted when an @param
entry in a function’s docblock doesn’t match the param typehint,
class A {}
class B {}
/**
* @param B $b // emitted here
*/
function foo(A $b) : void {}
This, however, is fine:
class A {}
class B extends A {}
/**
* @param B
*/
function foo(A $b) : void {}
MismatchingDocblockReturnType
Emitted when an @return
entry in a function’s docblock doesn’t match the function return typehint
class A {}
class B {}
/**
* @return B // emitted here
*/
function foo() : A {
return new A();
}
This, however, is fine:
class A {}
class B extends A {}
/**
* @return B // emitted here
*/
function foo() : A {
return new B();
}
MismatchingDocblockParamType
Emitted when an @param
entry in a function’s docblock doesn’t match the param typehint
/**
* @param int $b
*/
function foo(string $b) : void {}
MisplacedRequiredParam
Emitted when a required param is before a param that is not required. Included in Psalm because it is an E_WARNING in PHP
function foo(int $i = 5, string $j) : void {}
MissingClosureParamType
Emitted when a closure parameter has no type information associated with it
$a = function($a): string {
return "foo";
};
MissingClosureReturnType
Emitted when a closure lacks a return type
$a = function() {
return "foo";
};
MissingConstructor
Emitted when non-null properties without default values are defined in a class without a __construct
method
class A {
/** @var string */
public $foo;
}
MissingDependency
Emitted when referencing a class that doesn’t exist
/**
* @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
/** @var $a */
$a = [];
MissingFile
Emitted when using include
or require
on a file that does not exist
require("nonexistent.php");
MissingParamType
Emitted when a function parameter has no type information associated with it
function foo($a) : void {}
MissingPropertyType
Emitted when a property is defined on a class without a type
class A {
public $foo;
}
MissingReturnType
Emitted when a function doesn't have a return type defined
function foo() {
return "foo";
}
MissingTemplateParam
Emitted when using the @extends
/@implements
annotation to extend a class without
extending all its template params.
/**
* @template-implements IteratorAggregate<int>
*/
class SomeIterator implements IteratorAggregate
{
public function getIterator() {
yield 5;
}
}
MissingThrowsDocblock
Emitted when a function doesn't have a return type defined
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
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
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
echo $_GET['foo'][0];
MixedArrayAssignment
Emitted when trying to assign a value to an array offset on a value whose type Psalm cannot determine
$_GET['foo'][0] = "5";
MixedArrayOffset
Emitted when attempting to access an array offset where Psalm cannot determine the offset type
echo [1, 2, 3][$_GET['foo']];
MixedArrayTypeCoercion
Emitted when trying to access an array with a less specific offset than is expected
/**
* @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 a variable to a value for which Psalm cannot infer a type
$a = $_GET['foo'];
MixedFunctionCall
Emitted when calling a function on a value whose type Psalm cannot infer.
/** @psalm-suppress MixedAssignment */
$a = $_GET['foo'];
$a();
MixedInferredReturnType
Emitted when Psalm cannot determine a function's return type
function foo() : int {
return $_GET['foo'];
}
MixedMethodCall
Emitted when calling a method on a value that Psalm cannot infer a type for
/** @param mixed $a */
function foo($a) : void {
$a->foo();
}
MixedOperand
Emitted when Psalm cannot infer a type for an operand in any calculated expression
echo $_GET['foo'] + "hello";
MixedPropertyAssignment
Emitted when assigning a property to a value for which Psalm cannot infer a type
/** @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
/** @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
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
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
/**
* @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
"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
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)
class A {}
class B extends A {}
function foo() : B {
/** @psalm-suppress LessSpecificReturnStatement */
return new A();
}
NoValue
Emitted when using the result of a function that never returns.
/**
* @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.
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
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
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
function foo(string $s) : void {}
foo(null);
NullArrayAccess
Emitted when trying to access an array value on null
$arr = null;
echo $arr[0];
NullArrayOffset
Emitted when trying to access an array offset with null
$arr = ['' => 5, 'foo' => 1];
echo $arr[null];
NullFunctionCall
Emitted when trying to use null
as a callable
$arr = null;
echo $arr();
NullIterator
Emitted when iterating over null
foreach (null as $a) {}
NullOperand
Emitted when using null
as part of an operation (e.g. +
, .
, ^
etc.)
echo null . 'hello';
NullPropertyAssignment
Emitted when trying to set a property on null
$a = null;
$a->foo = "bar";
NullPropertyFetch
Emitted when trying to fetch a property on a null
value
$a = null;
echo $a->foo;
NullReference
Emitted when attempting to call a method on null
$a = null;
$a->foo();
OverriddenMethodAccess
Emitted when a method is less accessible than its parent
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
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
function foo($a) : void {
if ($a) return;
if ($a) echo "cannot happen";
}
ParentNotFound
Emitted when using parent::
in a class without a parent class.
class A {
public function foo() : void {
parent::foo();
}
}
ParseError
Emitted when the PHP Parser encounters an error.
class A {
public function foo() : void {
echo "foo"
}
}
PluginIssue
Can be emitted by plugins.
PossiblyFalseArgument
Emitted when a function argument is possibly false
, but the function doesn’t expect false
. This is distinct from a function argument is possibly bool
, which results in PossiblyInvalidArgument
.
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
$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).
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.
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
class A {
public function bar() : void {}
}
/** @return A|false */
function foo() {
return rand(0, 1) ? new A : false;
}
foo()->bar();
PossiblyInvalidArgument
Emitted when
/** @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
$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
$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
class A {}
class B {
public function __toString() {
return 'hello';
}
}
$c = (string) (rand(0, 1) ? new A() : new B());
PossiblyInvalidArrayOffset
Emitted when it’s possible that the array offset is not applicable to the value you’re trying to access.
$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
$a = rand(0, 1) ? 5 : function() : int { return 5; };
$b = $a();
PossiblyInvalidIterator
Emitted when trying to iterate over a value that may be invalid
$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
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.
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 doesn’t have the desired property.
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.
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 doesn’t have the desired property.
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 that’s possibly null when the function does not expect it
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
function foo(?array $a) : void {
echo $a[0];
}
PossiblyNullArrayAssignment
Emitted when trying to set a value on a possibly null array
$a = null;
$a[0][] = 1;
PossiblyNullArrayOffset
Emitted when trying to access a value on an array using a possibly null offset
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
function foo(?callable $a) : void {
$a();
}
PossiblyNullIterator
Emitted when trying to iterate over a value that may be null
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.)
function foo(?int $a) : void {
echo $a + 5;
}
PossiblyNullPropertyAssignment
Emitted when trying to assign a property to a possibly null object
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.
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
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
class A {
public function bar() : void {}
}
function foo(?A $a) : void {
$a->bar();
}
PossiblyUndefinedArrayOffset
Emitted when trying to access a possibly undefined array offset
if (rand(0, 1)) {
$arr = ["a" => 1, "b" => 2];
} else {
$arr = ["a" => 3];
}
echo $arr["b"];
PossiblyUndefinedGlobalVariable
Emitted when trying to access a variable in the global scope that may not be defined
if (rand(0, 1)) {
$a = 5;
}
echo $a;
PossiblyUndefinedMethod
Emitted when trying to access a method that may not be defined on the object
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
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
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
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
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 class’s constructor
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
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 object’s properties. This issue exists because it may be undesired behaviour (e.g. you may have meant to iterate over an array)
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
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.
/**
* @param string $s
*
* @return void
*/
function foo($s) {
if (is_string($s)) {};
}
ReferenceConstraintViolation
Emitted when changing the type of a pass-by-reference variable
function foo(string &$a) {
$a = 5;
}
ReservedWord
Emitted when using a reserved word as a class name
function foo(resource $res) : void {}
TraitMethodSignatureMismatch
Emitted when a method's signature or return type differs from corresponding trait-defined method
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
function foo(string $a) : void {}
foo();
TooManyArguments
Emitted when calling a function with more arguments than the function has parameters
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.
/**
* @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
$a = "hello";
if ($a === null) {}
TypeDoesNotContainType
Emitted checking whether one value has a type or value that is impossible given its currently-known type
$a = "hello";
if ($a === 5) {}
UncaughtThrowInGlobalScope
Emitted when a possible exception isn't caught in global scope
/**
* @throws \Exception
*/
function foo() : int {
return random_int(0, 1);
}
foo();
UndefinedClass
Emitted when referencing a class that doesn’t exist
$a = new A();
UndefinedConstant
Emitted when referencing a constant that doesn’t exist
echo FOO_BAR;
UndefinedDocblockClass
Emitted when referencing a class that doesn’t exist from a docblock
/**
* @param DoesNotExist $a
*/
function foo($a) : void {}
UndefinedFunction
Emitted when referencing a function that doesn't exist
foo();
UndefinedGlobalVariable
Emitted when referencing a variable that doesn't exist
echo $a;
UndefinedInterface
Emitted when referencing an interface that doesn’t exist but does have an identically-named class.
class C {}
interface I extends C {}
UndefinedMethod
Emitted when calling a method that doesn’t exist
class A {}
A::foo();
UndefinedInterfaceMethod
Emitted when calling a method that doesn’t exist on an interface
interface I {}
function foo(I $i) {
$i->bar();
}
UndefinedPropertyAssignment
Emitted when assigning a property on an object that doesn’t have that property defined
class A {}
$a = new A();
$a->foo = "bar";
UndefinedPropertyFetch
Emitted when getting a property on an object that doesn’t have that property defined
class A {}
$a = new A();
echo $a->foo;
UndefinedThisPropertyAssignment
Emitted when assigning a property on an object in one of that object’s methods when no such property exists
class A {
function foo() {
$this->foo = "bar";
}
}
UndefinedThisPropertyFetch
Emitted when getting a property for an object in one of that object’s methods when no such property exists
class A {
function foo() {
echo $this->foo;
}
}
UndefinedTrait
Emitted when referencing a trait that doesn’t exist
class A {
use T;
}
UndefinedVariable
Emitted when referencing a variable that doesn't exist in a given function’s scope
function foo() {
echo $a;
}
UnevaluatedCode
Emitted when --find-dead-code
is turned on and Psalm encounters code that will not be evaluated
function foo() : void {
return;
$a = "foo";
}
UnimplementedAbstractMethod
Emitted when a class extends another, but does not implement all of its abstract methods
abstract class A {
abstract public function foo();
}
class B extends A {}
UnimplementedInterfaceMethod
Emitted when a class implements
an interface but does not implement all of its methods
interface I {
public function foo();
}
class A implements I {}
UninitializedProperty
Emitted when a property is used in a constructor before it is initialized
class A {
/** @var string */
public $foo;
public function __construct() {
echo strlen($this->foo);
$this->foo = "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.
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
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
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.
$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);
}
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
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
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();
UnusedVariable
Emitted when --find-dead-code
is turned on and Psalm cannot find any references to a variable, once instantiated
function foo() : void {
$a = 5;
$b = 4;
echo $b;
}