118118use PHPStan \Node \VarTagChangedExpressionTypeNode ;
119119use PHPStan \Parser \ArrowFunctionArgVisitor ;
120120use PHPStan \Parser \ClosureArgVisitor ;
121+ use PHPStan \Parser \ImmediatelyInvokedClosureVisitor ;
121122use PHPStan \Parser \Parser ;
122123use PHPStan \Php \PhpVersion ;
123124use PHPStan \PhpDoc \PhpDocInheritanceResolver ;
@@ -4228,7 +4229,7 @@ private function processClosureNode(
42284229 }
42294230
42304231 $ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters );
4231- $ closureScope = $ closureScope ->processClosureScope ($ expr , $ scope , null , $ byRefUses );
4232+ $ closureScope = $ closureScope ->processClosureScope ($ scope , null , $ byRefUses );
42324233 $ closureType = $ closureScope ->getAnonymousFunctionReflection ();
42334234 if (!$ closureType instanceof ClosureType) {
42344235 throw new ShouldNotHappenException ();
@@ -4273,6 +4274,7 @@ private function processClosureNode(
42734274
42744275 $ gatheredReturnStatements [] = new ReturnStatement ($ scope , $ node );
42754276 };
4277+
42764278 if (count ($ byRefUses ) === 0 ) {
42774279 $ statementResult = $ this ->processStmtNodes ($ expr , $ expr ->stmts , $ closureScope , $ closureStmtsCallback , StatementContext::createTopLevel ());
42784280 $ nodeCallback (new ClosureReturnStatementsNode (
@@ -4288,6 +4290,7 @@ private function processClosureNode(
42884290 }
42894291
42904292 $ count = 0 ;
4293+ $ closureResultScope = null ;
42914294 do {
42924295 $ prevScope = $ closureScope ;
42934296
@@ -4297,8 +4300,15 @@ private function processClosureNode(
42974300 foreach ($ intermediaryClosureScopeResult ->getExitPoints () as $ exitPoint ) {
42984301 $ intermediaryClosureScope = $ intermediaryClosureScope ->mergeWith ($ exitPoint ->getScope ());
42994302 }
4303+
4304+ if ($ expr ->getAttribute (ImmediatelyInvokedClosureVisitor::ATTRIBUTE_NAME ) === true ) {
4305+ $ closureResultScope = $ intermediaryClosureScope ;
4306+ break ;
4307+ }
4308+
43004309 $ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters );
4301- $ closureScope = $ closureScope ->processClosureScope ($ expr , $ intermediaryClosureScope , $ prevScope , $ byRefUses );
4310+ $ closureScope = $ closureScope ->processClosureScope ($ intermediaryClosureScope , $ prevScope , $ byRefUses );
4311+
43024312 if ($ closureScope ->equals ($ prevScope )) {
43034313 break ;
43044314 }
@@ -4308,6 +4318,10 @@ private function processClosureNode(
43084318 $ count ++;
43094319 } while ($ count < self ::LOOP_SCOPE_ITERATIONS );
43104320
4321+ if ($ closureResultScope === null ) {
4322+ $ closureResultScope = $ closureScope ;
4323+ }
4324+
43114325 $ statementResult = $ this ->processStmtNodes ($ expr , $ expr ->stmts , $ closureScope , $ closureStmtsCallback , StatementContext::createTopLevel ());
43124326 $ nodeCallback (new ClosureReturnStatementsNode (
43134327 $ expr ,
@@ -4318,7 +4332,7 @@ private function processClosureNode(
43184332 array_merge ($ statementResult ->getImpurePoints (), $ closureImpurePoints ),
43194333 ), $ closureScope );
43204334
4321- return new ProcessClosureResult ($ scope ->processClosureScope ($ expr , $ closureScope , null , $ byRefUses ), $ statementResult ->getThrowPoints (), $ statementResult ->getImpurePoints (), $ invalidateExpressions );
4335+ return new ProcessClosureResult ($ scope ->processClosureScope ($ closureResultScope , null , $ byRefUses ), $ statementResult ->getThrowPoints (), $ statementResult ->getImpurePoints (), $ invalidateExpressions );
43224336 }
43234337
43244338 /**
0 commit comments