diff --git a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php index 216423696d..df1bf3499a 100644 --- a/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php +++ b/src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php @@ -3,6 +3,7 @@ namespace PHPStan\Type\Php; use PhpParser\Node\Expr\Array_; +use PhpParser\Node\Expr\BinaryOp\Equal; use PhpParser\Node\Expr\BinaryOp\Identical; use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; @@ -52,7 +53,16 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $needleExpr = $node->getArgs()[0]->value; $arrayExpr = $node->getArgs()[1]->value; - if ($arrayExpr instanceof Array_ && $isStrictComparison) { + + $needleType = $scope->getType($needleExpr); + $arrayType = $scope->getType($arrayExpr); + $arrayValueType = $arrayType->getIterableValueType(); + + $isStrictComparison = $isStrictComparison + || $needleType->isEnum()->yes() + || $arrayValueType->isEnum()->yes(); + + if ($arrayExpr instanceof Array_) { $types = null; foreach ($arrayExpr->items as $item) { if ($item === null) { @@ -62,7 +72,12 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n $types = null; break; } - $itemTypes = $this->typeSpecifier->resolveIdentical(new Identical($needleExpr, $item->value), $scope, $context, null); + + if ($isStrictComparison) { + $itemTypes = $this->typeSpecifier->resolveIdentical(new Identical($needleExpr, $item->value), $scope, $context, null); + } else { + $itemTypes = $this->typeSpecifier->resolveEqual(new Equal($needleExpr, $item->value), $scope, $context, null); + } if ($types === null) { $types = $itemTypes; @@ -77,14 +92,6 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n } } - $needleType = $scope->getType($needleExpr); - $arrayType = $scope->getType($arrayExpr); - $arrayValueType = $arrayType->getIterableValueType(); - - $isStrictComparison = $isStrictComparison - || $needleType->isEnum()->yes() - || $arrayValueType->isEnum()->yes(); - if (!$isStrictComparison) { if ( $context->true() diff --git a/tests/PHPStan/Analyser/nsrt/in_array_loose.php b/tests/PHPStan/Analyser/nsrt/in_array_loose.php new file mode 100644 index 0000000000..4600ae0a13 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/in_array_loose.php @@ -0,0 +1,48 @@ +analyse([__DIR__ . '/data/bug-11313.php'], []); } + public function testBug9436(): void + { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0.'); + } + + $this->analyse([__DIR__ . '/data/bug-9436.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-9436.php b/tests/PHPStan/Rules/Comparison/data/bug-9436.php new file mode 100644 index 0000000000..55846cc903 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-9436.php @@ -0,0 +1,15 @@ += 8.0 + +namespace Bug9436; + +$foo = rand(0, 100); + +if (!in_array($foo, [0, 1, 2])) { + exit(); +} + +$bar = match ($foo) { + 0 => 'a', + 1 => 'b', + 2 => 'c', +};