From 6645d8b16efa45341b127d316894c0990e4486a2 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 3 Jun 2022 16:40:37 +0200 Subject: [PATCH 1/8] reproduce specifier bug --- src/Analyser/TypeSpecifier.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 3494a6b2587..d75d6406073 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -267,6 +267,12 @@ public function specifyTypesInCondition( ); } } + + if ( + $constantType instanceof ConstantStringType + ) { + \PHPStan\dumpType($constantType->getValue()); + } } $rightType = $scope->getType($expr->right); From 9c1229506f367c6102124832e89e491967b35525 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 4 Jun 2022 09:37:35 +0200 Subject: [PATCH 2/8] reproduce bug 1396 --- .../Analyser/NodeScopeResolverTest.php | 2 + tests/PHPStan/Analyser/data/bug-1396.php | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tests/PHPStan/Analyser/data/bug-1396.php diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 16bf724d555..450095c9203 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -905,6 +905,8 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/non-empty-string-strcasing-specifying.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/conditional-complex-templates.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7374.php'); + + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-1396.php'); } /** diff --git a/tests/PHPStan/Analyser/data/bug-1396.php b/tests/PHPStan/Analyser/data/bug-1396.php new file mode 100644 index 00000000000..e5f2f95fc86 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-1396.php @@ -0,0 +1,48 @@ +getValue() === null) { + return $this->create(); + } + + if ( + $constantType instanceof ConstantStringType + ) { + assertType('string', $constantType->getValue()); + } + } + } + } + + /** @api */ + public function create( + ): SpecifiedTypes + { + return new SpecifiedTypes(); + } +} From 2061378b28113a79df163f2308d0253ef654cc15 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 4 Jun 2022 09:38:07 +0200 Subject: [PATCH 3/8] fix --- src/Analyser/TypeSpecifier.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index d75d6406073..3494a6b2587 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -267,12 +267,6 @@ public function specifyTypesInCondition( ); } } - - if ( - $constantType instanceof ConstantStringType - ) { - \PHPStan\dumpType($constantType->getValue()); - } } $rightType = $scope->getType($expr->right); From aad5a1d76aa064cae5009f2a0f33f595c004170f Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 4 Jun 2022 09:41:53 +0200 Subject: [PATCH 4/8] simplify further --- tests/PHPStan/Analyser/data/bug-1396.php | 27 +++++++----------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/tests/PHPStan/Analyser/data/bug-1396.php b/tests/PHPStan/Analyser/data/bug-1396.php index e5f2f95fc86..e995fa2cbbe 100644 --- a/tests/PHPStan/Analyser/data/bug-1396.php +++ b/tests/PHPStan/Analyser/data/bug-1396.php @@ -11,31 +11,20 @@ class TypeSpecifier2 { /** - * @param (Expr|ConstantScalarType)[]|null $expressions * @api */ public function specifyTypesInCondition( - Expr $expr, - $expressions + ConstantScalarType $constantType ): SpecifiedTypes { - if ($expr instanceof Node\Expr\BinaryOp\Identical) { - if ($expressions !== null) { - /** @var Expr $exprNode */ - $exprNode = $expressions[0]; - /** @var ConstantScalarType $constantType */ - $constantType = $expressions[1]; - - if ($constantType->getValue() === null) { - return $this->create(); - } + if ($constantType->getValue() === null) { + return $this->create(); + } - if ( - $constantType instanceof ConstantStringType - ) { - assertType('string', $constantType->getValue()); - } - } + if ( + $constantType instanceof ConstantStringType + ) { + assertType('string', $constantType->getValue()); } } From 885bbff96a3f440c4311168799b5c285e2572997 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 4 Jun 2022 09:43:55 +0200 Subject: [PATCH 5/8] simplify --- tests/PHPStan/Analyser/data/bug-1396.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tests/PHPStan/Analyser/data/bug-1396.php b/tests/PHPStan/Analyser/data/bug-1396.php index e995fa2cbbe..a870a55ca4b 100644 --- a/tests/PHPStan/Analyser/data/bug-1396.php +++ b/tests/PHPStan/Analyser/data/bug-1396.php @@ -2,8 +2,6 @@ namespace Bug1396; -use PhpParser\Node; -use PhpParser\Node\Expr; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ConstantScalarType; use function PHPStan\Testing\assertType; @@ -18,7 +16,7 @@ public function specifyTypesInCondition( ): SpecifiedTypes { if ($constantType->getValue() === null) { - return $this->create(); + return new SpecifiedTypes(); } if ( @@ -27,11 +25,4 @@ public function specifyTypesInCondition( assertType('string', $constantType->getValue()); } } - - /** @api */ - public function create( - ): SpecifiedTypes - { - return new SpecifiedTypes(); - } } From 90671e86d2396f23557f32bc2777afef25a08a4b Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 4 Jun 2022 09:46:03 +0200 Subject: [PATCH 6/8] simplify --- tests/PHPStan/Analyser/data/bug-1396.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/PHPStan/Analyser/data/bug-1396.php b/tests/PHPStan/Analyser/data/bug-1396.php index a870a55ca4b..d5618d87588 100644 --- a/tests/PHPStan/Analyser/data/bug-1396.php +++ b/tests/PHPStan/Analyser/data/bug-1396.php @@ -8,9 +8,6 @@ class TypeSpecifier2 { - /** - * @api - */ public function specifyTypesInCondition( ConstantScalarType $constantType ): SpecifiedTypes From a60272dd5de4becb3b87b6bd4567d82d16ecfaf5 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 4 Jun 2022 09:46:30 +0200 Subject: [PATCH 7/8] simplify --- tests/PHPStan/Analyser/data/bug-1396.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Analyser/data/bug-1396.php b/tests/PHPStan/Analyser/data/bug-1396.php index d5618d87588..18d95236e92 100644 --- a/tests/PHPStan/Analyser/data/bug-1396.php +++ b/tests/PHPStan/Analyser/data/bug-1396.php @@ -6,9 +6,9 @@ use PHPStan\Type\ConstantScalarType; use function PHPStan\Testing\assertType; -class TypeSpecifier2 +class HelloWorld { - public function specifyTypesInCondition( + public function doFoo( ConstantScalarType $constantType ): SpecifiedTypes { From 85b207ccbdbc5af9d641e070ebc27016acf1fde5 Mon Sep 17 00:00:00 2001 From: Yohta Kimura Date: Tue, 5 Jul 2022 16:10:10 +0900 Subject: [PATCH 8/8] invalidate expressions when variable type has changed --- src/Analyser/MutatingScope.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 8d1dd0a58cb..9c720ae9f7a 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3401,7 +3401,7 @@ public function unsetExpression(Expr $expr): self [], $this->afterExtractCall, $this->parentScope, - ); + )->invalidateExpression($expr); } elseif ($expr instanceof Expr\ArrayDimFetch && $expr->dim !== null) { return $this->specifyExpressionType( $expr->var, @@ -3499,7 +3499,7 @@ public function specifyExpressionType(Expr $expr, Type $type, ?Type $nativeType $this->inFunctionCallsStack, $this->afterExtractCall, $this->parentScope, - ); + )->invalidateExpression($expr); } elseif ($expr instanceof Expr\ArrayDimFetch && $expr->dim !== null) { $constantArrays = TypeUtils::getOldConstantArrays($this->getType($expr->var)); if (count($constantArrays) > 0) {