1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00
psalm/docs/running_psalm/issues.md
2019-06-15 12:09:15 -04:00

39 KiB
Raw Blame History

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;

DeprecatedFunction

Emitted when calling a deprecated function:

/** @deprecated */
function foo() : void {}
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 youre 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 doesnt 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 functions 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 functions docblock doesnt 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 functions docblock doesnt 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 functions docblock doesnt match the param typehint

/**
 * @param int $b
 */
function foo(string $b) : 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 doesnt 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 doesnt 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 its possible that the array offset is not applicable to the value youre 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 doesnt 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 doesnt 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 thats 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 classs 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 objects 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 doesnt exist

$a = new A();

UndefinedConstant

Emitted when referencing a constant that doesnt exist

echo FOO_BAR;

UndefinedDocblockClass

Emitted when referencing a class that doesnt 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 doesnt exist but does have an identically-named class.

class C {}

interface I extends C {}

UndefinedMethod

Emitted when calling a method that doesnt exist

class A {}
A::foo();

UndefinedInterfaceMethod

Emitted when calling a method that doesnt exist on an interface

interface I {}

function foo(I $i) {
    $i->bar();
}

UndefinedPropertyAssignment

Emitted when assigning a property on an object that doesnt have that property defined

class A {}
$a = new A();
$a->foo = "bar";

UndefinedPropertyFetch

Emitted when getting a property on an object that doesnt 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 objects 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 objects methods when no such property exists

class A {
    function foo() {
        echo $this->foo;
    }
}

UndefinedTrait

Emitted when referencing a trait that doesnt exist

class A {
    use T;
}

UndefinedVariable

Emitted when referencing a variable that doesn't exist in a given functions 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;
}