[ 'code' => ' 123]; /** @var array{test: ?int} */ $a = ["test" => null]; if ($a["test"] === null) { $a = $dummy; } $var = $a["test"];', 'assertions' => [ '$var' => 'int', ], ], 'intIsMixed' => [ 'code' => ' [ 'code' => ' [], 'ignored_issues' => ['RedundantConditionGivenDocblockType'], ], 'arrayTypeResolutionFromDocblock' => [ 'code' => ' [], 'ignored_issues' => ['RedundantConditionGivenDocblockType'], ], 'typeResolutionFromDocblockInside' => [ 'code' => ' [], 'ignored_issues' => ['DocblockTypeContradiction', 'TypeDoesNotContainType'], ], 'notInstanceof' => [ 'code' => ' [ '$out' => 'A|null', ], ], 'notInstanceOfProperty' => [ 'code' => 'foo = new B(); } } $a = new A(); $out = null; if ($a->foo instanceof C) { // do something } else { $out = $a->foo; }', 'assertions' => [ '$out' => 'B|null', ], 'ignored_issues' => [], ], 'notInstanceOfPropertyElseif' => [ 'code' => 'foo)) { } elseif ($a->foo instanceof C) { // do something } else { $out = $a->foo; }', 'assertions' => [ '$out' => 'B|null', ], 'ignored_issues' => [], ], 'typeRefinementWithIsNumericOnIntOrFalse' => [ 'code' => ' [ 'code' => ' [ 'code' => ' 4 ? "hello" : 5; if (is_numeric($a)) { exit; }', 'assertions' => [ '$a' => 'string', ], ], 'typeRefinementonWithNegatedIsNumeric' => [ 'code' => ' [ 'code' => ' 4 ? "hello" : true; if (is_bool($a)) { exit; }', 'assertions' => [ '$a' => 'string', ], ], 'updateMultipleIssetVars' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [], 'ignored_issues' => ['RedundantConditionGivenDocblockType'], ], 'ignoreNullCheckAndMaintainNullValue' => [ 'code' => ' [ '$b' => 'null', ], 'ignored_issues' => ['TypeDoesNotContainType', 'RedundantCondition'], ], 'ignoreNullCheckAndMaintainNullableValue' => [ 'code' => ' [ '$b' => 'int|null', ], ], 'ternaryByRefVar' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'bar(); $this->bat(); takesA($this); takesI($this); takesAandI($this); takesIandA($this); } return null; } protected function bar(): void {} } class B extends A implements I { public function bat(): void {} }', ], 'createIntersectionOfInterfaceAndClass' => [ 'code' => 'bat(); $i->baz(); } } function bar(A $a) : void { if ($a instanceof I) { $a->bat(); $a->baz(); } } class B extends A implements I { public function baz() : void {} } foo(new B); bar(new B);', ], 'unionOfArrayOrTraversable' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' 2) { $a = "hello"; } else { $a = false; } } return $a; }', ], 'nullableIntReplacement' => [ 'code' => ' [ '$a' => 'int|null', ], ], 'eraseNullAfterInequalityCheck' => [ 'code' => ' 0) { echo $a + 3; } if (0 < $a) { echo $a + 3; }', ], 'twoWrongsDontMakeARight' => [ 'code' => ' [ '$a' => 'false', ], ], 'instanceofStatic' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'foo(); }', ], 'isArrayOnArrayKeyOffset' => [ 'code' => '|string>} */ $doc = []; if (!is_array($doc["s"]["t"])) { $doc["s"]["t"] = [$doc["s"]["t"]]; }', 'assertions' => [ '$doc[\'s\'][\'t\']' => 'array', ], ], 'removeTrue' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ '$a' => 'null', ], ], 'removeNullWithIsScalar' => [ 'code' => ' [ '$a' => 'string', ], ], 'scalarToNumeric' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => '|null $foo */ function d(?iterable $foo): void { if (is_iterable($foo)) { foreach ($foo as $f) {} } if (!is_iterable($foo)) { } else { foreach ($foo as $f) {} } }', ], 'isStringSessionVar' => [ 'code' => ' [ 'code' => ' [ 'code' => 'b())) {} }', ], 'reconcileFloatToEmpty' => [ 'code' => ' [ 'code' => ' [ '$s' => 'scalar', ], ], 'scalarToString' => [ 'code' => ' [ '$s' => 'scalar', ], ], 'scalarToInt' => [ 'code' => ' [ '$s' => 'scalar', ], ], 'scalarToFloat' => [ 'code' => ' [ '$s' => 'scalar', ], ], 'removeFromArray' => [ 'code' => ' $v */ function foo(array $v) : void { if (!isset($v[0])) { return; } if ($v[0] === " ") { array_shift($v); } if (!isset($v[0])) {} }', ], 'arrayEquality' => [ 'code' => '> $haystack * @param array $needle */ function foo(array $haystack, array $needle) : void { foreach ($haystack as $arr) { if ($arr === $needle) {} } }', ], 'classResolvesBackToSelfAfterComparison' => [ 'code' => ' [ '$a' => 'A', ], ], 'isNumericCanBeScalar' => [ 'code' => ' [ 'code' => '|null $val */ function foo(?string $val) : void { if (!$val) {} if ($val) {} }', ], 'allowStringToObjectReconciliation' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'foo(); } function baz(A $a) : void { if (($a instanceof B || $a instanceof C) === false) { return; } $a->foo(); }', ], 'selfInstanceofStatic' => [ 'code' => ' [ 'code' => ' [ 'code' => 'foo) { $this->foo = []; } } public function iffer() : bool { return $this->foo || $this->bar; } }', ], 'noLeakyForeachType' => [ 'code' => '_array_value = $this->getArrayValue(); if ($this->_array_value !== null && !count($this->_array_value)) { return; } switch ($var) { case "a": foreach ($this->_array_value ?: [] as $v) {} break; case "b": foreach ($this->_array_value ?: [] as $v) {} break; } } }', 'assertions' => [], 'ignored_issues' => ['MixedAssignment'], ], 'nonEmptyThing' => [ 'code' => ' [], 'ignored_issues' => ['MixedArgument', 'MixedArrayAccess', 'MixedAssignment', 'MixedArrayOffset'], ], 'allowNonEmptyArrayComparison' => [ 'code' => ' $b */ function foo(array $a, array $b) : void { if ($a === $b) {} }', ], 'preventCombinatorialExpansion' => [ 'code' => ' [ 'code' => ' $x */ function takesArray (array $x): void {} /** @var iterable */ $x = null; assert(is_array($x)); takesArray($x); /** * @param Traversable $x */ function takesTraversable (Traversable $x): void {} /** @var iterable */ $x = null; assert($x instanceof Traversable); takesTraversable($x);', ], 'dontReconcileArrayOffset' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => '|false|string */ function foo() { return filter_input(INPUT_POST, "some_var") ?? []; }', ], 'noCrashOnWeirdArrayKeys' => [ 'code' => 'id])) {} }', ], 'assertArrayReturnTypeNarrowed' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' $arr */ function uriToPath(array $arr) : string { if (!isset($arr["a"]) || $arr["b"] !== "foo") { throw new \InvalidArgumentException("bad"); } return (string) $arr["c"]; }', ], 'combineAfterLoopAssert' => [ 'code' => ' $array */ function foo(array $array) : void { $c = 0; if ($array["a"] === "a") { foreach ([rand(0, 1), rand(0, 1)] as $i) { if ($array["b"] === "c") {} $c++; } } }', ], 'assertOnArrayTwice' => [ 'code' => ' $array */ function f(array $array) : void { if ($array["bar"] === "a") {} if ($array["bar"] === "b") {} }', ], 'assertOnArrayThrice' => [ 'code' => ' $array */ function f(array $array) : void { if ($array["foo"] === "ok") { if ($array["bar"] === "a") {} if ($array["bar"] === "b") {} } }', ], 'assertOnBacktrace' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' 0; }', ], 'assertHasArrayAccessSimple' => [ 'code' => ' [ 'code' => '> $array * @return array */ function getBar(array $array) : array { if (isset($array[\'foo\'][\'bar\'])) { return $array[\'foo\']; } return []; }', ], 'assertHasArrayAccessOnSimpleXMLElement' => [ 'code' => 'bar)) {} }', ], 'assertArrayOffsetToTraversable' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' $arr * @return non-empty-array */ function foo(array $arr) : array { if (isset($arr["a"])) { return $arr; } return ["b" => 1]; }', ], 'setArrayConstantOffset' => [ 'code' => ' [ 'code' => ' $arr */ function foo(A $a, array $arr): void { if (!isset($arr[$a->id])) { $arr[$a->id] = new B(); } $arr[$a->id]->foo(); }', ], 'assertAfterNotEmptyArrayCheck' => [ 'code' => ' [ 'code' => 'c[$s]) && empty($this->c[$t])) {} } }', ], 'assertNotEmptyTwiceOnStaticPropertyArray' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'arr[0])) { return $this->arr[0]; } $this->arr[0] = new stdClass; return $this->arr[0]; } }', ], 'assertPropertiesOfElseStatement' => [ 'code' => 'a === "foo") { } elseif ($obj->b === "bar") { } else if ($obj->b === "baz") {} if ($obj->b === "baz") {} }', ], 'assertPropertiesOfElseifStatement' => [ 'code' => 'a === "foo") { } elseif ($obj->b === "bar") { } elseif ($obj->b === "baz") {} if ($obj->b === "baz") {} }', ], 'assertArrayWithOffset' => [ 'code' => ' [ 'code' => ' [ 'code' => 'b && !$b->b; echo $a->b ? 1 : 0; }', ], 'literalStringComparisonInIf' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => '> */ $a = null; if (isset($a["b"]) || isset($a["c"])) { $all_params = ($a["b"] ?? []) + ($a["c"] ?? []); }', ], 'assertOnNestedLogic' => [ 'code' => ' 5) {} } }', ], 'arrayUnionTypeSwitching' => [ 'code' => ' $map */ function foo(array $map, string $o) : void { if ($mapped_type = $map[$o] ?? null) { if (is_int($mapped_type)) { return; } } if (($mapped_type = $map[""] ?? null) && is_string($mapped_type)) { } }', ], 'propertySetOnElementInConditional' => [ 'code' => 'old) && is_string($diff_elem->new)) || (is_int($diff_elem->old) && is_int($diff_elem->new)) ) { } }', ], 'manyNestedAsserts' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => '> $arr * @return array */ public static function getArr(array $arr) : array { if (!isset($arr[static::class])) { $arr[static::class] = ["hello" => 5]; } return $arr[static::class]; } }', ], 'assertOnVarVar' => [ 'code' => '> $arr * @return array */ function getArr(array $arr, string $s) : array { if (!isset($arr[$s])) { $arr[$s] = ["hello" => 5]; } return $arr[$s]; } }', ], 'assertOnPropertyStaticClassKey' => [ 'code' => '> */ private static $arr = []; /** @return array */ public static function getArr() : array { $arr = self::$arr; if (!isset($arr[static::class])) { $arr[static::class] = ["hello" => 5]; } return $arr[static::class]; } }', ], 'assertOnStaticPropertyOffset' => [ 'code' => '|null */ private static $map = []; public static function foo(string $id) : ?string { if (isset(self::$map[$id])) { return self::$map[$id]; } return null; } }', ], 'issetTwice' => [ 'code' => ' $p */ function foo(array $p, int $id) : void { if ((isset($p[$id]) && rand(0, 1)) || (!isset($p[$id]) && rand(0, 1)) ) { isset($p[$id]) ? $p[$id] : new B; isset($p[$id]) ? $p[$id]->foo() : "bar"; } }', ], 'reconcileEmptinessBetter' => [ 'code' => ' [ 'code' => ' [ 'code' => ' $collection * @psalm-return array */ function order(iterable $collection): array { if ($collection instanceof \Traversable) { $collection = iterator_to_array($collection, false); } return $collection; }', ], 'memoizeChainedImmutableCallsInside' => [ 'code' => 'root; } } class Project { private ?Assessment $assessment = null; /** @psalm-mutation-free */ public function getAssessment(): ?Assessment { return $this->assessment; } } function f(Project $project): int { if (($project->getAssessment() !== null) && ($project->getAssessment()->getRoot() !== null) ) { return strlen($project->getAssessment()->getRoot()); } throw new RuntimeException(); }', ], 'memoizeChainedImmutableCallsOutside' => [ 'code' => 'root; } } class Project { private ?Assessment $assessment = null; /** @psalm-mutation-free */ public function getAssessment(): ?Assessment { return $this->assessment; } } function f(Project $project): int { if (($project->getAssessment() === null) || ($project->getAssessment()->getRoot() === null) ) { throw new RuntimeException(); } return strlen($project->getAssessment()->getRoot()); }', ], 'propertyChainedOutside' => [ 'code' => 'assessment === null) || ($project->assessment->root === null) ) { throw new RuntimeException(); } return strlen($project->assessment->root); }', ], 'castIsType' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' */ public $args = []; } function barr(FuncCall $function) : void { if (!$function->name instanceof A) { return; } if ($function->name->parts === ["function_exists"] && isset($function->args[0]) ) { // do something } elseif ($function->name->parts === ["class_exists"] && isset($function->args[0]) ) { // do something else } }', ], 'largeConditional' => [ 'code' => ' */ function splitDocLine($return_block) { $brackets = \'\'; $type = \'\'; $expects_callable_return = false; $return_block = str_replace("\t", \' \', $return_block); $quote_char = null; $escaped = false; for ($i = 0, $l = strlen($return_block); $i < $l; ++$i) { $char = $return_block[$i]; $next_char = $i < $l - 1 ? $return_block[$i + 1] : null; $last_char = $i > 0 ? $return_block[$i - 1] : null; if ($quote_char) { if ($char === $quote_char && $i > 1 && !$escaped) { $quote_char = null; $type .= $char; continue; } if (rand(0, 1)) { $escaped = true; $type .= $char; continue; } $escaped = false; $type .= $char; continue; } if ($char === \'"\' || $char === \'\\\\\') { $quote_char = $char; $type .= $char; continue; } if (rand(0, 1)) { $expects_callable_return = true; $type .= $char; continue; } if ($char === \'[\' || $char === \'{\' || $char === \'(\' || $char === \'<\') { $brackets .= $char; } elseif ($char === \']\' || $char === \'}\' || $char === \')\' || $char === \'>\') { $last_bracket = substr($brackets, -1); $brackets = substr($brackets, 0, -1); if (($char === \']\' && $last_bracket !== \'[\') || ($char === \'}\' && $last_bracket !== \'{\') || ($char === \')\' && $last_bracket !== \'(\') || ($char === \'>\' && $last_bracket !== \'<\') ) { return []; } } elseif ($char === \' \') { if ($brackets) { $expects_callable_return = false; $type .= \' \'; continue; } if ($next_char === \'|\' || $next_char === \'&\') { $nexter_char = $i < $l - 2 ? $return_block[$i + 2] : null; if ($nexter_char === \' \') { ++$i; $type .= $next_char . \' \'; continue; } } if ($last_char === \'|\' || $last_char === \'&\') { $type .= \' \'; continue; } if ($next_char === \':\') { ++$i; $type .= \' :\'; $expects_callable_return = true; continue; } if ($expects_callable_return) { $type .= \' \'; $expects_callable_return = false; continue; } $remaining = trim(preg_replace(\'@^[ \t]*\* *@m\', \' \', substr($return_block, $i + 1))); if ($remaining) { /** @var array */ return array_merge([rtrim($type)], preg_split(\'/\s+/\', $remaining)); } return [$type]; } $expects_callable_return = false; $type .= $char; } return [$type]; }', ], 'nonEmptyStringAfterLiteralCheck' => [ 'code' => ' [ 'code' => 'format("Y") === "2020") == true) { $a->format("d-m-Y"); }', ], 'getClassIsStatic' => [ 'code' => ' [ 'code' => ' [ 'code' => 'next?->value; } function skipTwo(IntLinkedList $l) : ?int { return $l->next?->next?->value; }', 'assertions' => [], 'ignored_issues' => [], 'php_version' => '8.0', ], 'nullsafeMethodCall' => [ 'code' => 'next; } } function skipOne(IntLinkedList $l) : ?int { return $l->getNext()?->value; } function skipTwo(IntLinkedList $l) : ?int { return $l->getNext()?->getNext()?->value; }', 'assertions' => [], 'ignored_issues' => [], 'php_version' => '8.0', ], 'onlySingleErrorForEarlyExit' => [ 'code' => 'bar($arr)) { return; } }', ], 'nonRedundantConditionAfterThing' => [ 'code' => 'takes($b)) || $b === null ) {} }', ], 'usedAssertedVarButNotWithStrongerTypeGuarantee' => [ 'code' => ' [ 'code' => ' [ 'code' => ' : list) */ function foo($bar): string {} /** @var int */ $baz = 1; $a = foo($baz); /** @var float */ $baz = 1.; $b = foo($baz); /** @var int|float */ $baz = 1; $c = foo($baz); ', 'assertions' => [ '$a' => 'list', '$b' => 'list', '$c' => 'list', ], ], 'negateTypeInGenericContext' => [ 'code' => '|Invalid $val * @psalm-assert-if-true Valid $val */ function isValid($val): bool { return $val instanceof Valid; } /** * @template T * @param Valid|Invalid $val */ function genericContext($val): void { $takesValid = /** @param Valid $_valid */ function ($_valid): void {}; $takesInvalid = /** @param Invalid $_invalid */ function ($_invalid): void {}; isValid($val) ? $takesValid($val) : $takesInvalid($val); }', ], 'reconcileMoreThanOneGenericObject' => [ 'code' => ' $val * @psalm-assert-if-true Valid $val */ function isValid($val): bool { return $val instanceof Valid; } /** * @template T * @param Valid|Invalid $val1 * @param Valid|Invalid $val2 * @param Valid|Invalid $val3 */ function inGenericContext($val1, $val2, $val3): void { $takesValid = /** @param Valid $_valid */ function ($_valid): void {}; if (isValid($val1) && isValid($val2) && isValid($val3)) { $takesValid($val1); $takesValid($val2); $takesValid($val3); } }', ], 'ternaryRedefineAllVars' => [ 'code' => ' [ '$_a===' => "'N'|'Y'", ], ], 'assertionsWorksBothWays' => [ 'code' => ' [ '$a===' => '2', '$b===' => '2', ], ], 'nullErasureWithSmallerAndGreater' => [ 'code' => ' 0) { echo $a + 3; } if ($a >= 0) { /** @psalm-suppress PossiblyNullOperand */ echo $a + 3; } if (0 < $a) { echo $a + 3; } if (0 <= $a) { /** @psalm-suppress PossiblyNullOperand */ echo $a + 3; } if (0 > $a) { echo $a + 3; } if (0 >= $a) { /** @psalm-suppress PossiblyNullOperand */ echo $a + 3; } ', ], 'falseErasureWithSmallerAndGreater' => [ 'code' => ' 0) { echo $a + 3; } if ($a >= 0) { /** @psalm-suppress PossiblyFalseOperand */ echo $a + 3; } if (0 < $a) { echo $a + 3; } if (0 <= $a) { /** @psalm-suppress PossiblyFalseOperand */ echo $a + 3; } if (0 > $a) { echo $a + 3; } if (0 >= $a) { /** @psalm-suppress PossiblyFalseOperand */ echo $a + 3; } ', ], 'SimpleXMLElementNotAlwaysTruthy' => [ 'code' => 'b; if (!$n instanceof SimpleXMLElement) { return; } if (!$n) { echo "false"; }', ], 'nullIsFalsyEvenInTemplate' => [ 'code' => ' */ class AbstarctRepository implements RepositoryInterface { public function find(int $id) { return null; } } /** * @template T as Animal * @extends AbstarctRepository */ class AnimalRepository extends AbstarctRepository {} /** * @extends AnimalRepository */ class CatRepository extends AnimalRepository {} /** * @extends AnimalRepository */ class DogRepository extends AnimalRepository {} function doSomething(AnimalRepository $repository) : void { $foo = $repository->find(1); if (!$foo) { return; } $foo->foo(); }', ], 'variable::classAssertion' => [ 'code' => ' [ 'code' => 'b; if (!$n instanceof SimpleXMLIterator) { return; } if (!$n) { echo "false"; }', ], '#7771: non-UTF8 binary data is passed' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ '$int' => 'int<48, 57>|int<256, 1000>', ], ], 'ctypeLowerMakesStringLowercase' => [ 'code' => ' [ 'code' => <<<'PHP' [ '$a===' => '1', ], ], 'ifDoesNotLeak' => [ 'code' => <<<'PHP' [ '$a===' => '1', ], ], 'ifElseDoesNotLeak' => [ 'code' => <<<'PHP' [ '$a===' => '1', ], ], 'ifElseInvertedDoesNotLeak' => [ 'code' => <<<'PHP' [ '$a===' => '1', ], ], 'ifNotIssetDoesNotLeakArrayAssertions' => [ 'code' => <<<'PHP' [ 'code' => ' [ '$int' => 'int<97, 122>', ], ], 'short_circuited_conditional_test' => [ 'code' => ' [ '$existing' => 'null|stdClass', ], ], ]; } public function providerInvalidCodeParse(): iterable { return [ 'makeNonNullableNull' => [ 'code' => ' 'TypeDoesNotContainNull', ], 'makeInstanceOfThingInElseif' => [ 'code' => ' 5 ? new A() : new B(); if ($a instanceof A) { } elseif ($a instanceof C) { }', 'error_message' => 'TypeDoesNotContainType', ], 'functionValueIsNotType' => [ 'code' => ' 'TypeDoesNotContainType', ], 'stringIsNotTnt' => [ 'code' => ' 'TypeDoesNotContainType', ], 'stringIsNotNull' => [ 'code' => ' 'TypeDoesNotContainNull', ], 'stringIsNotFalse' => [ 'code' => ' 'TypeDoesNotContainType', ], 'typeTransformation' => [ 'code' => ' 'TypeDoesNotContainType', ], 'nonRedundantConditionGivenDocblockType' => [ 'code' => ' 'TypeDoesNotContainType', ], 'lessSpecificArrayFields' => [ 'code' => ' "name"]);', 'error_message' => 'InvalidArgument', ], 'intersectionIncorrect' => [ 'code' => ' 'InvalidArgument', ], 'catchTypeMismatchInBinaryOp' => [ 'code' => ' */ function getStrings(): array { return ["hello", "world", 50]; } $a = getStrings(); if (is_bool($a[0]) && $a[0]) {}', 'error_message' => 'DocblockTypeContradiction', ], 'preventWeakEqualityToObject' => [ 'code' => ' 'TypeDoesNotContainType', ], 'properReconciliationInElseIf' => [ 'code' => ' 'RedundantCondition', ], 'allRemovalOfStringWithIsScalar' => [ 'code' => ' 'RedundantCondition', ], 'noRemovalOfStringWithIsScalar' => [ 'code' => ' 'TypeDoesNotContainType', ], 'impossibleNullEquality' => [ 'code' => ' 'TypeDoesNotContainNull', ], 'impossibleTrueEquality' => [ 'code' => ' 'TypeDoesNotContainType', ], 'impossibleFalseEquality' => [ 'code' => ' 'TypeDoesNotContainType', ], 'impossibleNumberEquality' => [ 'code' => ' 'TypeDoesNotContainType', ], 'noIntersectionOfArrayOrTraversable' => [ 'code' => ' 'TypeDoesNotContainType', ], 'scalarToBoolContradiction' => [ 'code' => ' 'TypeDoesNotContainType', ], 'noCrashWhenCastingArray' => [ 'code' => ' 1, "b" => 2]; }', 'error_message' => 'InvalidReturnStatement', ], 'preventStrongEqualityScalarType' => [ 'code' => ' 'TypeDoesNotContainType', ], 'preventYodaStrongEqualityScalarType' => [ 'code' => ' 'TypeDoesNotContainType', ], 'classCannotNotBeSelf' => [ 'code' => ' 'RedundantCondition', ], 'preventImpossibleComparisonToTrue' => [ 'code' => ' 'DocblockTypeContradiction', ], 'preventAlwaysPossibleComparisonToTrue' => [ 'code' => ' 'RedundantConditionGivenDocblockType', ], 'preventAlwaysImpossibleComparisonToFalse' => [ 'code' => ' 'TypeDoesNotContainType', ], 'preventAlwaysPossibleComparisonToFalse' => [ 'code' => ' 'RedundantCondition', ], 'nullCoalesceImpossible' => [ 'code' => ' 'RedundantCondition', ], 'allowEmptyScalarAndNonEmptyScalarAssertions1' => [ 'code' => ' 'RedundantCondition', ], 'allowEmptyScalarAndNonEmptyScalarAssertions2' => [ 'code' => ' 'RedundantCondition', ], 'allowEmptyScalarAndNonEmptyScalarAssertions3' => [ 'code' => ' 'RedundantCondition', ], 'allowEmptyScalarAndNonEmptyScalarAssertions4' => [ 'code' => ' 'RedundantCondition', ], 'catchRedundantConditionOnBinaryOpForwards' => [ 'code' => ' 'RedundantCondition', ], 'nonEmptyString' => [ 'code' => ' 'ArgumentTypeCoercion', ], 'getClassCannotBeStringEquals' => [ 'code' => ' 'TypeDoesNotContainType', ], 'falsyValuesInIf' => [ 'code' => ' 'TypeDoesNotContainType', ], 'BooleanNotOfAlwaysTruthyisFalse' => [ 'code' => 'fluent()) { echo "always"; } ', 'error_message' => 'TypeDoesNotContainType', ], 'redundantConditionForNonEmptyString' => [ 'code' => ' 'RedundantCondition', ], 'impossibleConditionWithReference' => [ 'code' => ' 'TypeDoesNotContainType', ], 'redundantConditionWithReference' => [ 'code' => ' 'RedundantCondition', ], ]; } }