@@ -927,12 +927,14 @@ private function processStmtNode(
927927 $ hasYield = $ result ->hasYield ();
928928 $ throwPoints = $ result ->getThrowPoints ();
929929 $ impurePoints = $ result ->getImpurePoints ();
930+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
931+
930932 if ($ earlyTerminationExpr !== null ) {
931933 return new StatementResult ($ scope , $ hasYield , true , [
932934 new StatementExitPoint ($ stmt , $ scope ),
933935 ], $ overridingThrowPoints ?? $ throwPoints , $ impurePoints );
934936 }
935- return new StatementResult ($ scope , $ hasYield , false , [], $ overridingThrowPoints ?? $ throwPoints , $ impurePoints );
937+ return new StatementResult ($ scope , $ hasYield , $ isAlwaysTerminating , [], $ overridingThrowPoints ?? $ throwPoints , $ impurePoints );
936938 } elseif ($ stmt instanceof Node \Stmt \Namespace_) {
937939 if ($ stmt ->name !== null ) {
938940 $ scope = $ scope ->enterNamespace ($ stmt ->name ->toString ());
@@ -2464,20 +2466,22 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context): Exp
24642466 $ hasYield = $ result ->hasYield ();
24652467 $ throwPoints = $ result ->getThrowPoints ();
24662468 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
2469+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
24672470 $ scope = $ result ->getScope ();
24682471
24692472 if ($ expr instanceof AssignRef) {
24702473 $ scope = $ scope ->exitExpressionAssign ($ expr ->expr );
24712474 }
24722475
2473- return new ExpressionResult ($ scope , $ hasYield , $ throwPoints , $ impurePoints );
2476+ return new ExpressionResult ($ scope , $ hasYield , $ throwPoints , $ impurePoints, isAlwaysTerminating: $ isAlwaysTerminating );
24742477 },
24752478 true ,
24762479 );
24772480 $ scope = $ result ->getScope ();
24782481 $ hasYield = $ result ->hasYield ();
24792482 $ throwPoints = $ result ->getThrowPoints ();
24802483 $ impurePoints = $ result ->getImpurePoints ();
2484+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
24812485 $ vars = $ this ->getAssignedVariables ($ expr ->var );
24822486 if (count ($ vars ) > 0 ) {
24832487 $ varChangedScope = false ;
@@ -2509,6 +2513,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context): Exp
25092513 $ result ->hasYield (),
25102514 $ result ->getThrowPoints (),
25112515 $ result ->getImpurePoints (),
2516+ isAlwaysTerminating: $ result ->isAlwaysTerminating (),
25122517 );
25132518 }
25142519
@@ -2520,6 +2525,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context): Exp
25202525 $ hasYield = $ result ->hasYield ();
25212526 $ throwPoints = $ result ->getThrowPoints ();
25222527 $ impurePoints = $ result ->getImpurePoints ();
2528+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
25232529 if (
25242530 ($ expr instanceof Expr \AssignOp \Div || $ expr instanceof Expr \AssignOp \Mod) &&
25252531 !$ scope ->getType ($ expr ->expr )->toNumber ()->isSuperTypeOf (new ConstantIntegerType (0 ))->no ()
@@ -5380,12 +5386,14 @@ private function processAssignVar(
53805386 $ hasYield = false ;
53815387 $ throwPoints = [];
53825388 $ impurePoints = [];
5389+ $ isAlwaysTerminating = false ;
53835390 $ isAssignOp = $ assignedExpr instanceof Expr \AssignOp && !$ enterExpressionAssign ;
53845391 if ($ var instanceof Variable && is_string ($ var ->name )) {
53855392 $ result = $ processExprCallback ($ scope );
53865393 $ hasYield = $ result ->hasYield ();
53875394 $ throwPoints = $ result ->getThrowPoints ();
53885395 $ impurePoints = $ result ->getImpurePoints ();
5396+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
53895397 if (in_array ($ var ->name , Scope::SUPERGLOBAL_VARIABLES , true )) {
53905398 $ impurePoints [] = new ImpurePoint ($ scope , $ var , 'superglobal ' , 'assign to superglobal variable ' , true );
53915399 }
@@ -5470,6 +5478,7 @@ private function processAssignVar(
54705478 $ hasYield = $ result ->hasYield ();
54715479 $ throwPoints = $ result ->getThrowPoints ();
54725480 $ impurePoints = $ result ->getImpurePoints ();
5481+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
54735482 $ scope = $ result ->getScope ();
54745483 if ($ enterExpressionAssign ) {
54755484 $ scope = $ scope ->exitExpressionAssign ($ var );
@@ -5521,6 +5530,7 @@ private function processAssignVar(
55215530 $ hasYield = $ hasYield || $ result ->hasYield ();
55225531 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
55235532 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5533+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
55245534 $ scope = $ result ->getScope ();
55255535
55265536 $ varType = $ scope ->getType ($ var );
@@ -5626,6 +5636,7 @@ static function (): void {
56265636 $ hasYield = $ objectResult ->hasYield ();
56275637 $ throwPoints = $ objectResult ->getThrowPoints ();
56285638 $ impurePoints = $ objectResult ->getImpurePoints ();
5639+ $ isAlwaysTerminating = $ objectResult ->isAlwaysTerminating ();
56295640 $ scope = $ objectResult ->getScope ();
56305641
56315642 $ propertyName = null ;
@@ -5636,6 +5647,7 @@ static function (): void {
56365647 $ hasYield = $ hasYield || $ propertyNameResult ->hasYield ();
56375648 $ throwPoints = array_merge ($ throwPoints , $ propertyNameResult ->getThrowPoints ());
56385649 $ impurePoints = array_merge ($ impurePoints , $ propertyNameResult ->getImpurePoints ());
5650+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ propertyNameResult ->isAlwaysTerminating ();
56395651 $ scope = $ propertyNameResult ->getScope ();
56405652 }
56415653
@@ -5644,6 +5656,7 @@ static function (): void {
56445656 $ hasYield = $ hasYield || $ result ->hasYield ();
56455657 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
56465658 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5659+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
56475660 $ scope = $ result ->getScope ();
56485661
56495662 if ($ var ->name instanceof Expr && $ this ->phpVersion ->supportsPropertyHooks ()) {
@@ -5731,6 +5744,7 @@ static function (): void {
57315744 $ hasYield = $ propertyNameResult ->hasYield ();
57325745 $ throwPoints = $ propertyNameResult ->getThrowPoints ();
57335746 $ impurePoints = $ propertyNameResult ->getImpurePoints ();
5747+ $ isAlwaysTerminating = $ propertyNameResult ->isAlwaysTerminating ();
57345748 $ scope = $ propertyNameResult ->getScope ();
57355749 }
57365750
@@ -5739,6 +5753,7 @@ static function (): void {
57395753 $ hasYield = $ hasYield || $ result ->hasYield ();
57405754 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
57415755 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5756+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
57425757 $ scope = $ result ->getScope ();
57435758
57445759 if ($ propertyName !== null ) {
@@ -5783,6 +5798,7 @@ static function (): void {
57835798 $ hasYield = $ result ->hasYield ();
57845799 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
57855800 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5801+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
57865802 $ scope = $ result ->getScope ();
57875803 foreach ($ var ->items as $ i => $ arrayItem ) {
57885804 if ($ arrayItem === null ) {
@@ -5800,13 +5816,15 @@ static function (): void {
58005816 $ hasYield = $ hasYield || $ keyResult ->hasYield ();
58015817 $ throwPoints = array_merge ($ throwPoints , $ keyResult ->getThrowPoints ());
58025818 $ impurePoints = array_merge ($ impurePoints , $ keyResult ->getImpurePoints ());
5819+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ keyResult ->isAlwaysTerminating ();
58035820 $ itemScope = $ keyResult ->getScope ();
58045821 }
58055822
58065823 $ valueResult = $ this ->processExprNode ($ stmt , $ arrayItem ->value , $ itemScope , $ nodeCallback , $ context ->enterDeep ());
58075824 $ hasYield = $ hasYield || $ valueResult ->hasYield ();
58085825 $ throwPoints = array_merge ($ throwPoints , $ valueResult ->getThrowPoints ());
58095826 $ impurePoints = array_merge ($ impurePoints , $ valueResult ->getImpurePoints ());
5827+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ valueResult ->isAlwaysTerminating ();
58105828
58115829 if ($ arrayItem ->key === null ) {
58125830 $ dimExpr = new Node \Scalar \Int_ ($ i );
@@ -5827,6 +5845,7 @@ static function (): void {
58275845 $ hasYield = $ hasYield || $ result ->hasYield ();
58285846 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
58295847 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5848+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
58305849 }
58315850 } elseif ($ var instanceof ExistingArrayDimFetch) {
58325851 $ dimFetchStack = [];
@@ -5905,7 +5924,7 @@ static function (): void {
59055924 }
59065925 }
59075926
5908- return new ExpressionResult ($ scope , $ hasYield , $ throwPoints , $ impurePoints );
5927+ return new ExpressionResult ($ scope , $ hasYield , $ throwPoints , $ impurePoints, isAlwaysTerminating: $ isAlwaysTerminating );
59095928 }
59105929
59115930 /**
0 commit comments