From cb14292170bc52d2c0d0985afdfac846fa56673a Mon Sep 17 00:00:00 2001 From: Takuya Aramaki Date: Mon, 10 Oct 2022 10:36:20 +0900 Subject: [PATCH] Fix return type of array_search() with constant array type haystack --- ...SearchFunctionDynamicReturnTypeExtension.php | 15 +++------------ .../PHPStan/Analyser/NodeScopeResolverTest.php | 1 + tests/PHPStan/Analyser/data/bug-3789.php | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 tests/PHPStan/Analyser/data/bug-3789.php diff --git a/src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php b/src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php index 7190cb4d392..4a8dbd56de6 100644 --- a/src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php +++ b/src/Type/Php/ArraySearchFunctionDynamicReturnTypeExtension.php @@ -11,7 +11,6 @@ use PHPStan\Type\ConstantScalarType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; use PHPStan\Type\NullType; -use PHPStan\Type\ObjectWithoutClassType; use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\TypeUtils; @@ -93,33 +92,25 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, private function resolveTypeFromConstantHaystackAndNeedle(Type $needle, ConstantArrayType $haystack): Type { $matchesByType = []; + $hasIdenticalValue = false; foreach ($haystack->getValueTypes() as $index => $valueType) { $isNeedleSuperType = $valueType->isSuperTypeOf($needle); if ($isNeedleSuperType->no()) { - $matchesByType[] = new ConstantBooleanType(false); continue; } if ($needle instanceof ConstantScalarType && $valueType instanceof ConstantScalarType && $needle->getValue() === $valueType->getValue() ) { - return $haystack->getKeyTypes()[$index]; + $hasIdenticalValue = true; } $matchesByType[] = $haystack->getKeyTypes()[$index]; - if (!$isNeedleSuperType->maybe()) { - continue; - } - - $matchesByType[] = new ConstantBooleanType(false); } if (count($matchesByType) > 0) { - if ( - $haystack->getIterableValueType()->accepts($needle, true)->yes() - && $needle->isSuperTypeOf(new ObjectWithoutClassType())->no() - ) { + if ($hasIdenticalValue) { return TypeCombinator::union(...$matchesByType); } diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index c7dec07665a..c0b90613c91 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -1055,6 +1055,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8008.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5552.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Properties/data/bug-7839.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3789.php'); } /** diff --git a/tests/PHPStan/Analyser/data/bug-3789.php b/tests/PHPStan/Analyser/data/bug-3789.php new file mode 100644 index 00000000000..c5d89f2a5df --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-3789.php @@ -0,0 +1,17 @@ +