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