@@ -840,17 +840,20 @@ private function processStmtNode(
840
840
} elseif ($ stmt instanceof Echo_) {
841
841
$ hasYield = false ;
842
842
$ throwPoints = [];
843
+ $ isAlwaysTerminating = false ;
843
844
foreach ($ stmt ->exprs as $ echoExpr ) {
844
845
$ result = $ this ->processExprNode ($ stmt , $ echoExpr , $ scope , $ nodeCallback , ExpressionContext::createDeep ());
845
846
$ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
846
847
$ scope = $ result ->getScope ();
847
848
$ hasYield = $ hasYield || $ result ->hasYield ();
849
+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
848
850
}
849
851
850
852
$ throwPoints = $ overridingThrowPoints ?? $ throwPoints ;
851
853
$ impurePoints = [
852
854
new ImpurePoint ($ scope , $ stmt , 'echo ' , 'echo ' , true ),
853
855
];
856
+ return new StatementResult ($ scope , $ hasYield , $ isAlwaysTerminating , [], $ throwPoints , $ impurePoints );
854
857
} elseif ($ stmt instanceof Return_) {
855
858
if ($ stmt ->expr !== null ) {
856
859
$ result = $ this ->processExprNode ($ stmt , $ stmt ->expr , $ scope , $ nodeCallback , ExpressionContext::createDeep ());
@@ -2408,6 +2411,7 @@ public function processExprNode(Node\Stmt $stmt, Expr $expr, MutatingScope $scop
2408
2411
return $ this ->processExprNode ($ stmt , $ newExpr , $ scope , $ nodeCallback , $ context );
2409
2412
}
2410
2413
2414
+ $ isAlwaysTerminating = false ;
2411
2415
$ this ->callNodeCallbackWithExpression ($ nodeCallback , $ expr , $ scope , $ context );
2412
2416
2413
2417
if ($ expr instanceof Variable) {
@@ -2591,6 +2595,7 @@ static function (): void {
2591
2595
2592
2596
if ($ parametersAcceptor !== null ) {
2593
2597
$ expr = ArgumentsNormalizer::reorderFuncArguments ($ parametersAcceptor , $ expr ) ?? $ expr ;
2598
+ $ isAlwaysTerminating = $ parametersAcceptor ->getReturnType () instanceof NeverType;
2594
2599
}
2595
2600
$ result = $ this ->processArgs ($ stmt , $ functionReflection , null , $ parametersAcceptor , $ expr , $ scope , $ nodeCallback , $ context );
2596
2601
$ scope = $ result ->getScope ();
@@ -3299,6 +3304,7 @@ static function (): void {
3299
3304
$ hasYield = $ result ->hasYield ();
3300
3305
$ throwPoints = $ result ->getThrowPoints ();
3301
3306
$ impurePoints = $ result ->getImpurePoints ();
3307
+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
3302
3308
$ result = $ this ->processExprNode ($ stmt , $ expr ->right , $ scope , $ nodeCallback , $ context ->enterDeep ());
3303
3309
if (
3304
3310
($ expr instanceof BinaryOp \Div || $ expr instanceof BinaryOp \Mod) &&
@@ -3310,6 +3316,7 @@ static function (): void {
3310
3316
$ hasYield = $ hasYield || $ result ->hasYield ();
3311
3317
$ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
3312
3318
$ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
3319
+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
3313
3320
} elseif ($ expr instanceof Expr \Include_) {
3314
3321
$ result = $ this ->processExprNode ($ stmt , $ expr ->expr , $ scope , $ nodeCallback , $ context ->enterDeep ());
3315
3322
$ throwPoints = $ result ->getThrowPoints ();
@@ -3995,6 +4002,7 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void {
3995
4002
$ impurePoints ,
3996
4003
static fn (): MutatingScope => $ scope ->filterByTruthyValue ($ expr ),
3997
4004
static fn (): MutatingScope => $ scope ->filterByFalseyValue ($ expr ),
4005
+ $ isAlwaysTerminating ,
3998
4006
);
3999
4007
}
4000
4008
0 commit comments