@@ -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 ()
@@ -5379,12 +5385,14 @@ private function processAssignVar(
53795385 $ hasYield = false ;
53805386 $ throwPoints = [];
53815387 $ impurePoints = [];
5388+ $ isAlwaysTerminating = false ;
53825389 $ isAssignOp = $ assignedExpr instanceof Expr \AssignOp && !$ enterExpressionAssign ;
53835390 if ($ var instanceof Variable && is_string ($ var ->name )) {
53845391 $ result = $ processExprCallback ($ scope );
53855392 $ hasYield = $ result ->hasYield ();
53865393 $ throwPoints = $ result ->getThrowPoints ();
53875394 $ impurePoints = $ result ->getImpurePoints ();
5395+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
53885396 if (in_array ($ var ->name , Scope::SUPERGLOBAL_VARIABLES , true )) {
53895397 $ impurePoints [] = new ImpurePoint ($ scope , $ var , 'superglobal ' , 'assign to superglobal variable ' , true );
53905398 }
@@ -5469,6 +5477,7 @@ private function processAssignVar(
54695477 $ hasYield = $ result ->hasYield ();
54705478 $ throwPoints = $ result ->getThrowPoints ();
54715479 $ impurePoints = $ result ->getImpurePoints ();
5480+ $ isAlwaysTerminating = $ result ->isAlwaysTerminating ();
54725481 $ scope = $ result ->getScope ();
54735482 if ($ enterExpressionAssign ) {
54745483 $ scope = $ scope ->exitExpressionAssign ($ var );
@@ -5520,6 +5529,7 @@ private function processAssignVar(
55205529 $ hasYield = $ hasYield || $ result ->hasYield ();
55215530 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
55225531 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5532+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
55235533 $ scope = $ result ->getScope ();
55245534
55255535 $ varType = $ scope ->getType ($ var );
@@ -5625,6 +5635,7 @@ static function (): void {
56255635 $ hasYield = $ objectResult ->hasYield ();
56265636 $ throwPoints = $ objectResult ->getThrowPoints ();
56275637 $ impurePoints = $ objectResult ->getImpurePoints ();
5638+ $ isAlwaysTerminating = $ objectResult ->isAlwaysTerminating ();
56285639 $ scope = $ objectResult ->getScope ();
56295640
56305641 $ propertyName = null ;
@@ -5635,6 +5646,7 @@ static function (): void {
56355646 $ hasYield = $ hasYield || $ propertyNameResult ->hasYield ();
56365647 $ throwPoints = array_merge ($ throwPoints , $ propertyNameResult ->getThrowPoints ());
56375648 $ impurePoints = array_merge ($ impurePoints , $ propertyNameResult ->getImpurePoints ());
5649+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ propertyNameResult ->isAlwaysTerminating ();
56385650 $ scope = $ propertyNameResult ->getScope ();
56395651 }
56405652
@@ -5643,6 +5655,7 @@ static function (): void {
56435655 $ hasYield = $ hasYield || $ result ->hasYield ();
56445656 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
56455657 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5658+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
56465659 $ scope = $ result ->getScope ();
56475660
56485661 if ($ var ->name instanceof Expr && $ this ->phpVersion ->supportsPropertyHooks ()) {
@@ -5730,6 +5743,7 @@ static function (): void {
57305743 $ hasYield = $ propertyNameResult ->hasYield ();
57315744 $ throwPoints = $ propertyNameResult ->getThrowPoints ();
57325745 $ impurePoints = $ propertyNameResult ->getImpurePoints ();
5746+ $ isAlwaysTerminating = $ propertyNameResult ->isAlwaysTerminating ();
57335747 $ scope = $ propertyNameResult ->getScope ();
57345748 }
57355749
@@ -5738,6 +5752,7 @@ static function (): void {
57385752 $ hasYield = $ hasYield || $ result ->hasYield ();
57395753 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
57405754 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5755+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
57415756 $ scope = $ result ->getScope ();
57425757
57435758 if ($ propertyName !== null ) {
@@ -5782,6 +5797,7 @@ static function (): void {
57825797 $ hasYield = $ result ->hasYield ();
57835798 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
57845799 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5800+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
57855801 $ scope = $ result ->getScope ();
57865802 foreach ($ var ->items as $ i => $ arrayItem ) {
57875803 if ($ arrayItem === null ) {
@@ -5799,13 +5815,15 @@ static function (): void {
57995815 $ hasYield = $ hasYield || $ keyResult ->hasYield ();
58005816 $ throwPoints = array_merge ($ throwPoints , $ keyResult ->getThrowPoints ());
58015817 $ impurePoints = array_merge ($ impurePoints , $ keyResult ->getImpurePoints ());
5818+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ keyResult ->isAlwaysTerminating ();
58025819 $ itemScope = $ keyResult ->getScope ();
58035820 }
58045821
58055822 $ valueResult = $ this ->processExprNode ($ stmt , $ arrayItem ->value , $ itemScope , $ nodeCallback , $ context ->enterDeep ());
58065823 $ hasYield = $ hasYield || $ valueResult ->hasYield ();
58075824 $ throwPoints = array_merge ($ throwPoints , $ valueResult ->getThrowPoints ());
58085825 $ impurePoints = array_merge ($ impurePoints , $ valueResult ->getImpurePoints ());
5826+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ valueResult ->isAlwaysTerminating ();
58095827
58105828 if ($ arrayItem ->key === null ) {
58115829 $ dimExpr = new Node \Scalar \Int_ ($ i );
@@ -5826,6 +5844,7 @@ static function (): void {
58265844 $ hasYield = $ hasYield || $ result ->hasYield ();
58275845 $ throwPoints = array_merge ($ throwPoints , $ result ->getThrowPoints ());
58285846 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
5847+ $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
58295848 }
58305849 } elseif ($ var instanceof ExistingArrayDimFetch) {
58315850 $ dimFetchStack = [];
@@ -5904,7 +5923,7 @@ static function (): void {
59045923 }
59055924 }
59065925
5907- return new ExpressionResult ($ scope , $ hasYield , $ throwPoints , $ impurePoints );
5926+ return new ExpressionResult ($ scope , $ hasYield , $ throwPoints , $ impurePoints, isAlwaysTerminating: $ isAlwaysTerminating );
59085927 }
59095928
59105929 /**
0 commit comments