@@ -2570,7 +2570,9 @@ public function processExprNode(
25702570 throw new ShouldNotHappenException ();
25712571 }
25722572
2573- return $ this ->processExprNode ($ stmt , $ newExpr , $ scope , $ storage , $ nodeCallback , $ context );
2573+ $ newExprResult = $ this ->processExprNode ($ stmt , $ newExpr , $ scope , $ storage , $ nodeCallback , $ context );
2574+ $ storage ->storeResult ($ expr , $ newExprResult );
2575+ return $ newExprResult ;
25742576 }
25752577
25762578 $ existingExprResult = $ storage ->findResult ($ expr );
@@ -2581,6 +2583,7 @@ public function processExprNode(
25812583 throw new ShouldNotHappenException (sprintf ('Expr %s on line %d has already been analysed ' , get_class ($ expr ), $ expr ->getStartLine ()));
25822584 }
25832585
2586+ $ originalScope = $ scope ;
25842587 $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ expr , $ scope , $ storage , $ context );
25852588
25862589 if ($ expr instanceof Variable) {
@@ -2630,6 +2633,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
26302633 );
26312634 }
26322635
2636+ $ beforeScope = $ scope ;
26332637 $ result = $ this ->processExprNode ($ stmt , $ expr ->expr , $ scope , $ storage , $ nodeCallback , $ context ->enterDeep ());
26342638 $ hasYield = $ result ->hasYield ();
26352639 $ throwPoints = $ result ->getThrowPoints ();
@@ -2641,7 +2645,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
26412645 $ scope = $ scope ->exitExpressionAssign ($ expr ->expr );
26422646 }
26432647
2644- $ result = new ExpressionResult ($ scope , $ hasYield , $ isAlwaysTerminating , $ throwPoints , $ impurePoints );
2648+ $ result = new ExpressionResult ($ scope , $ beforeScope , $ hasYield , $ isAlwaysTerminating , $ throwPoints , $ impurePoints );
26452649 $ this ->storeResult ($ storage , $ expr , $ result );
26462650
26472651 return $ result ;
@@ -2683,6 +2687,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
26832687 if ($ expr instanceof Expr \AssignOp \Coalesce) {
26842688 $ result = new ExpressionResult (
26852689 $ result ->getScope ()->mergeWith ($ originalScope ),
2690+ $ originalScope ,
26862691 $ result ->hasYield (),
26872692 $ result ->isAlwaysTerminating (),
26882693 $ result ->getThrowPoints (),
@@ -3188,12 +3193,14 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
31883193 $ impurePoints = array_merge ($ impurePoints , $ result ->getImpurePoints ());
31893194 $ isAlwaysTerminating = $ isAlwaysTerminating || $ result ->isAlwaysTerminating ();
31903195 } elseif ($ expr instanceof Expr \NullsafeMethodCall) {
3196+ $ beforeScope = $ scope ;
31913197 $ nonNullabilityResult = $ this ->ensureShallowNonNullability ($ scope , $ scope , $ expr ->var );
31923198 $ exprResult = $ this ->processExprNode ($ stmt , new MethodCall ($ expr ->var , $ expr ->name , $ expr ->args , array_merge ($ expr ->getAttributes (), ['virtualNullsafeMethodCall ' => true ])), $ nonNullabilityResult ->getScope (), $ storage , $ nodeCallback , $ context );
31933199 $ scope = $ this ->revertNonNullability ($ exprResult ->getScope (), $ nonNullabilityResult ->getSpecifiedExpressions ());
31943200
31953201 $ result = new ExpressionResult (
31963202 $ scope ,
3203+ $ beforeScope ,
31973204 $ exprResult ->hasYield (),
31983205 false ,
31993206 $ exprResult ->getThrowPoints (),
@@ -3402,12 +3409,14 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
34023409 }
34033410 }
34043411 } elseif ($ expr instanceof Expr \NullsafePropertyFetch) {
3412+ $ beforeScope = $ scope ;
34053413 $ nonNullabilityResult = $ this ->ensureShallowNonNullability ($ scope , $ scope , $ expr ->var );
34063414 $ exprResult = $ this ->processExprNode ($ stmt , new PropertyFetch ($ expr ->var , $ expr ->name , array_merge ($ expr ->getAttributes (), ['virtualNullsafePropertyFetch ' => true ])), $ nonNullabilityResult ->getScope (), $ storage , $ nodeCallback , $ context );
34073415 $ scope = $ this ->revertNonNullability ($ exprResult ->getScope (), $ nonNullabilityResult ->getSpecifiedExpressions ());
34083416
34093417 $ result = new ExpressionResult (
34103418 $ scope ,
3419+ $ beforeScope ,
34113420 $ exprResult ->hasYield (),
34123421 false ,
34133422 $ exprResult ->getThrowPoints (),
@@ -3448,11 +3457,13 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
34483457 $ scope = $ result ->getScope ();
34493458 }
34503459 } elseif ($ expr instanceof Expr \Closure) {
3460+ $ beforeScope = $ scope ;
34513461 $ processClosureResult = $ this ->processClosureNode ($ stmt , $ expr , $ scope , $ storage , $ nodeCallback , $ context , null );
34523462 $ scope = $ processClosureResult ->getScope ();
34533463
34543464 $ result = new ExpressionResult (
34553465 $ scope ,
3466+ $ beforeScope ,
34563467 false ,
34573468 false ,
34583469 [],
@@ -3465,6 +3476,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
34653476 $ result = $ this ->processArrowFunctionNode ($ stmt , $ expr , $ scope , $ storage , $ nodeCallback , null );
34663477 $ exprResult = new ExpressionResult (
34673478 $ result ->getScope (),
3479+ $ scope ,
34683480 $ result ->hasYield (),
34693481 false ,
34703482 [],
@@ -3571,6 +3583,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
35713583
35723584 $ result = new ExpressionResult (
35733585 $ leftMergedWithRightScope ,
3586+ $ scope ,
35743587 $ leftResult ->hasYield () || $ rightResult ->hasYield (),
35753588 $ leftResult ->isAlwaysTerminating (),
35763589 array_merge ($ leftResult ->getThrowPoints (), $ rightResult ->getThrowPoints ()),
@@ -3594,6 +3607,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
35943607
35953608 $ result = new ExpressionResult (
35963609 $ leftMergedWithRightScope ,
3610+ $ scope ,
35973611 $ leftResult ->hasYield () || $ rightResult ->hasYield (),
35983612 $ leftResult ->isAlwaysTerminating (),
35993613 array_merge ($ leftResult ->getThrowPoints (), $ rightResult ->getThrowPoints ()),
@@ -3851,7 +3865,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
38513865 }
38523866 } elseif ($ expr instanceof List_) {
38533867 // only in assign and foreach, processed elsewhere
3854- return new ExpressionResult ($ scope , false , false , [], []);
3868+ return new ExpressionResult ($ scope , $ scope , false , false , [], []);
38553869 } elseif ($ expr instanceof New_) {
38563870 $ parametersAcceptor = null ;
38573871 $ constructorReflection = null ;
@@ -4067,6 +4081,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
40674081
40684082 $ result = new ExpressionResult (
40694083 $ finalScope ,
4084+ $ scope ,
40704085 $ ternaryCondResult ->hasYield (),
40714086 $ isAlwaysTerminating ,
40724087 $ throwPoints ,
@@ -4422,6 +4437,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context, $sto
44224437
44234438 $ result = new ExpressionResult (
44244439 $ scope ,
4440+ $ originalScope ,
44254441 $ hasYield ,
44264442 $ isAlwaysTerminating ,
44274443 $ throwPoints ,
@@ -5167,7 +5183,7 @@ private function processArrowFunctionNode(
51675183 $ this ->callNodeCallback ($ nodeCallback , new InArrowFunctionNode ($ arrowFunctionType , $ expr ), $ arrowFunctionScope , $ storage );
51685184 $ exprResult = $ this ->processExprNode ($ stmt , $ expr ->expr , $ arrowFunctionScope , $ storage , $ nodeCallback , ExpressionContext::createTopLevel ());
51695185
5170- $ result = new ExpressionResult ($ scope , false , $ exprResult ->isAlwaysTerminating (), $ exprResult ->getThrowPoints (), $ exprResult ->getImpurePoints ());
5186+ $ result = new ExpressionResult ($ scope , $ scope , false , $ exprResult ->isAlwaysTerminating (), $ exprResult ->getThrowPoints (), $ exprResult ->getImpurePoints ());
51715187 $ this ->storeResult ($ storage , $ expr , $ result );
51725188
51735189 return $ result ;
@@ -5799,7 +5815,7 @@ private function processArgs(
57995815 }
58005816
58015817 // not storing this, it's scope after processing all args
5802- return new ExpressionResult ($ scope , $ hasYield , $ isAlwaysTerminating , $ throwPoints , $ impurePoints );
5818+ return new ExpressionResult ($ scope , $ scope , $ hasYield , $ isAlwaysTerminating , $ throwPoints , $ impurePoints );
58035819 }
58045820
58055821 /**
@@ -5903,6 +5919,7 @@ private function processAssignVar(
59035919 bool $ enterExpressionAssign ,
59045920 ): ExpressionResult
59055921 {
5922+ $ originalScope = $ scope ;
59065923 $ this ->callNodeCallback ($ nodeCallback , $ var , $ enterExpressionAssign ? $ scope ->enterExpressionAssign ($ var ) : $ scope , $ storage );
59075924 $ hasYield = false ;
59085925 $ throwPoints = [];
@@ -6350,7 +6367,7 @@ private function processAssignVar(
63506367 new GetOffsetValueTypeExpr ($ assignedExpr , $ dimExpr ),
63516368 $ nodeCallback ,
63526369 $ context ,
6353- static fn (MutatingScope $ scope ): ExpressionResult => new ExpressionResult ($ scope , false , false , [], []),
6370+ static fn (MutatingScope $ scope ): ExpressionResult => new ExpressionResult ($ scope , $ scope , false , false , [], []),
63546371 $ enterExpressionAssign ,
63556372 );
63566373 $ scope = $ result ->getScope ();
@@ -6436,7 +6453,7 @@ private function processAssignVar(
64366453 }
64376454
64386455 // stored where processAssignVar is called
6439- return new ExpressionResult ($ scope , $ hasYield , $ isAlwaysTerminating , $ throwPoints , $ impurePoints );
6456+ return new ExpressionResult ($ scope , $ originalScope , $ hasYield , $ isAlwaysTerminating , $ throwPoints , $ impurePoints );
64406457 }
64416458
64426459 /**
@@ -6452,7 +6469,7 @@ private function processVirtualAssign(MutatingScope $scope, ExpressionResultStor
64526469 $ assignedExpr ,
64536470 new VirtualAssignNodeCallback ($ nodeCallback ),
64546471 ExpressionContext::createDeep (),
6455- static fn (MutatingScope $ scope ): ExpressionResult => new ExpressionResult ($ scope , false , false , [], []),
6472+ static fn (MutatingScope $ scope ): ExpressionResult => new ExpressionResult ($ scope , $ scope , false , false , [], []),
64566473 false ,
64576474 );
64586475 }
0 commit comments