From f67cfcb2e15e2be31274000fafafc2f005b250dd Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Wed, 17 Mar 2021 17:00:50 +0100 Subject: [PATCH] Fixed === and !== type inference with treatPhpDocTypesAsCertain=false --- src/Analyser/MutatingScope.php | 18 ++++++++++--- src/Testing/TypeInferenceTestCase.php | 5 ++-- .../Analyser/NodeScopeResolverTest.php | 1 + tests/PHPStan/Analyser/data/bug-4650.php | 27 +++++++++++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 tests/PHPStan/Analyser/data/bug-4650.php diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index e4d062748e..7e92ae47db 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -810,8 +810,13 @@ private function resolveType(Expr $node): Type } if ($node instanceof Expr\BinaryOp\Identical) { - $leftType = $this->getType($node->left); - $rightType = $this->getType($node->right); + if ($this->treatPhpDocTypesAsCertain) { + $leftType = $this->getType($node->left); + $rightType = $this->getType($node->right); + } else { + $leftType = $this->getNativeType($node->left); + $rightType = $this->getNativeType($node->right); + } if ( ( @@ -851,8 +856,13 @@ private function resolveType(Expr $node): Type } if ($node instanceof Expr\BinaryOp\NotIdentical) { - $leftType = $this->getType($node->left); - $rightType = $this->getType($node->right); + if ($this->treatPhpDocTypesAsCertain) { + $leftType = $this->getType($node->left); + $rightType = $this->getType($node->right); + } else { + $leftType = $this->getNativeType($node->left); + $rightType = $this->getNativeType($node->right); + } if ( ( diff --git a/src/Testing/TypeInferenceTestCase.php b/src/Testing/TypeInferenceTestCase.php index ec05239ae3..e9084e02da 100644 --- a/src/Testing/TypeInferenceTestCase.php +++ b/src/Testing/TypeInferenceTestCase.php @@ -153,8 +153,9 @@ public function gatherAssertTypes(string $file): array $actualType = $scope->getType($node->args[1]->value); $assert = ['type', $file, $expectedType, $actualType, $node->getLine()]; } elseif ($functionName === 'PHPStan\\Testing\\assertNativeType') { - $expectedType = $scope->getNativeType($node->args[0]->value); - $actualType = $scope->getNativeType($node->args[1]->value); + $nativeScope = $scope->doNotTreatPhpDocTypesAsCertain(); + $expectedType = $nativeScope->getNativeType($node->args[0]->value); + $actualType = $nativeScope->getNativeType($node->args[1]->value); $assert = ['type', $file, $expectedType, $actualType, $node->getLine()]; } elseif ($functionName === 'PHPStan\\Testing\\assertVariableCertainty') { $certainty = $node->args[0]->value; diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 84b079a6f9..278ad05c65 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -379,6 +379,7 @@ public function dataFileAsserts(): iterable require_once __DIR__ . '/data/type-aliases.php'; yield from $this->gatherAssertTypes(__DIR__ . '/data/type-aliases.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4650.php'); } /** diff --git a/tests/PHPStan/Analyser/data/bug-4650.php b/tests/PHPStan/Analyser/data/bug-4650.php new file mode 100644 index 0000000000..f378375869 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-4650.php @@ -0,0 +1,27 @@ + $idx + */ + function doFoo(array $idx): void { + assertType('array&nonEmpty', $idx); + assertNativeType('array', $idx); + + assertType('array()', []); + assertNativeType('array()', []); + + assertType('false', $idx === []); + assertNativeType('bool', $idx === []); + assertType('true', $idx !== []); + assertNativeType('bool', $idx !== []); + } + +}