diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 71e145d2c6..6e73c78738 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3099,6 +3099,9 @@ public function enterMatch(Expr\Match_ $expr): self if ($expr->cond instanceof Variable) { return $this; } + if ($expr->cond instanceof AlwaysRememberedExpr) { + return $this; + } $type = $this->getType($expr->cond); $nativeType = $this->getNativeType($expr->cond); diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 88546889ff..22f17c74ef 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -72,6 +72,7 @@ use PHPStan\Node\ClosureReturnStatementsNode; use PHPStan\Node\DoWhileLoopConditionNode; use PHPStan\Node\ExecutionEndNode; +use PHPStan\Node\Expr\AlwaysRememberedExpr; use PHPStan\Node\Expr\GetIterableKeyTypeExpr; use PHPStan\Node\Expr\GetIterableValueTypeExpr; use PHPStan\Node\Expr\GetOffsetValueTypeExpr; @@ -2772,6 +2773,11 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void { } $nodeCallback(new MatchExpressionNode($expr->cond, $armNodes, $expr, $matchScope), $scope); + } elseif ($expr instanceof AlwaysRememberedExpr) { + $result = $this->processExprNode($expr->getExpr(), $scope, $nodeCallback, $context); + $hasYield = $result->hasYield(); + $throwPoints = $result->getThrowPoints(); + $scope = $result->getScope(); } elseif ($expr instanceof Expr\Throw_) { $hasYield = false; $result = $this->processExprNode($expr->expr, $scope, $nodeCallback, ExpressionContext::createDeep()); diff --git a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php index 22e582d89d..ec6c6b8a47 100644 --- a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php +++ b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php @@ -954,4 +954,13 @@ public function testBug393(): void $this->analyse([__DIR__ . '/data/bug-393.php'], []); } + public function testBug9474(): void + { + $this->cliArgumentsVariablesRegistered = true; + $this->polluteScopeWithLoopInitialAssignments = true; + $this->checkMaybeUndefinedVariables = true; + $this->polluteScopeWithAlwaysIterableForeach = true; + $this->analyse([__DIR__ . '/data/bug-9474.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Variables/data/bug-9474.php b/tests/PHPStan/Rules/Variables/data/bug-9474.php new file mode 100644 index 0000000000..443e5ce96e --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-9474.php @@ -0,0 +1,22 @@ +getColor()){ + 1 => 1, + default => throw new \Exception("Unhandled dye colour " . $color) + }; + echo $color; + return $i; + })(new GlazedTerracotta)); + } +}