diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index ebb599d056..62f1e00206 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1143,7 +1143,6 @@ public function processStmtNode( if ($stmt->expr instanceof Expr\Throw_) { $scope = $stmtScope; } - $earlyTerminationExpr = $this->findEarlyTerminatingExpr($stmt->expr, $scope); $hasAssign = false; $currentScope = $scope; $result = $this->processExprNode($stmt, $stmt->expr, $scope, $storage, new GatheringNodeCallback(static function (Node $node, Scope $scope) use ($currentScope, &$hasAssign): void { @@ -1179,7 +1178,14 @@ public function processStmtNode( $impurePoints = $result->getImpurePoints(); $isAlwaysTerminating = $result->isAlwaysTerminating(); - if ($earlyTerminationExpr !== null) { + // The expression statement is an exit point when its value type is an + // explicit never: exit/die/throw, a never-returning call, or a call + // configured as early-terminating (the call handlers give those never). + // Asked on the pre-statement scope: a conditional return type must + // resolve against the argument types the call was made with, not + // against state the statement itself just changed (bug-11565). + $statementType = $currentScope->getType($stmt->expr); + if ($statementType instanceof NeverType && $statementType->isExplicit()) { return new InternalStatementResult($scope, $hasYield, true, [ new InternalStatementExitPoint($stmt, $scope), ], $overridingThrowPoints ?? $throwPoints, $impurePoints); @@ -2761,20 +2767,6 @@ private function lookForExpressionCallback(MutatingScope $scope, Expr $expr, Clo return $scope; } - private function findEarlyTerminatingExpr(Expr $expr, Scope $scope): ?Expr - { - if ($expr instanceof Expr\Exit_ || $expr instanceof Expr\Throw_) { - return $expr; - } - - $exprType = $scope->getType($expr); - if ($exprType instanceof NeverType && $exprType->isExplicit()) { - return $expr; - } - - return null; - } - /** * @param callable(Node $node, Scope $scope): void $nodeCallback */