diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 8ff656bb57..0434f735f0 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -3192,7 +3192,7 @@ static function (): void { return new ExpressionResult( $result->getScope(), $result->hasYield(), - $result->isAlwaysTerminating(), + false, [], [], ); @@ -4804,7 +4804,7 @@ private function processArrowFunctionNode( $nodeCallback(new InArrowFunctionNode($arrowFunctionType, $expr), $arrowFunctionScope); $exprResult = $this->processExprNode($stmt, $expr->expr, $arrowFunctionScope, $nodeCallback, ExpressionContext::createTopLevel()); - return new ExpressionResult($scope, false, false, $exprResult->getThrowPoints(), $exprResult->getImpurePoints()); + return new ExpressionResult($scope, false, $exprResult->isAlwaysTerminating(), $exprResult->getThrowPoints(), $exprResult->getImpurePoints()); } /** @@ -5226,6 +5226,7 @@ private function processArgs( if ($callCallbackImmediately) { $throwPoints = array_merge($throwPoints, array_map(static fn (ThrowPoint $throwPoint) => $throwPoint->isExplicit() ? ThrowPoint::createExplicit($scope, $throwPoint->getType(), $arg->value, $throwPoint->canContainAnyThrowable()) : ThrowPoint::createImplicit($scope, $arg->value), $arrowFunctionResult->getThrowPoints())); $impurePoints = array_merge($impurePoints, $arrowFunctionResult->getImpurePoints()); + $isAlwaysTerminating = $isAlwaysTerminating || $arrowFunctionResult->isAlwaysTerminating(); } } else { $exprType = $scope->getType($arg->value); diff --git a/tests/PHPStan/Analyser/ExpressionResultTest.php b/tests/PHPStan/Analyser/ExpressionResultTest.php index dbca93c756..4315c53168 100644 --- a/tests/PHPStan/Analyser/ExpressionResultTest.php +++ b/tests/PHPStan/Analyser/ExpressionResultTest.php @@ -79,6 +79,10 @@ public static function dataIsAlwaysTerminating(): array 'fn() => yield (exit());', false, ], + [ + '(fn() => exit())();', // immediately invoked function expression + true, + ], [ '@exit();', true, @@ -99,6 +103,10 @@ public static function dataIsAlwaysTerminating(): array 'exit() ?? $x;', true, ], + [ + 'call_user_func(fn() => exit());', + true, + ], [ 'var_dump(1+exit());', true,