118
118
use PHPStan \Node \VarTagChangedExpressionTypeNode ;
119
119
use PHPStan \Parser \ArrowFunctionArgVisitor ;
120
120
use PHPStan \Parser \ClosureArgVisitor ;
121
+ use PHPStan \Parser \ImmediatelyInvokedClosureVisitor ;
121
122
use PHPStan \Parser \Parser ;
122
123
use PHPStan \Php \PhpVersion ;
123
124
use PHPStan \PhpDoc \PhpDocInheritanceResolver ;
@@ -4228,7 +4229,7 @@ private function processClosureNode(
4228
4229
}
4229
4230
4230
4231
$ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters );
4231
- $ closureScope = $ closureScope ->processClosureScope ($ expr , $ scope , null , $ byRefUses );
4232
+ $ closureScope = $ closureScope ->processClosureScope ($ scope , null , $ byRefUses );
4232
4233
$ closureType = $ closureScope ->getAnonymousFunctionReflection ();
4233
4234
if (!$ closureType instanceof ClosureType) {
4234
4235
throw new ShouldNotHappenException ();
@@ -4273,6 +4274,7 @@ private function processClosureNode(
4273
4274
4274
4275
$ gatheredReturnStatements [] = new ReturnStatement ($ scope , $ node );
4275
4276
};
4277
+
4276
4278
if (count ($ byRefUses ) === 0 ) {
4277
4279
$ statementResult = $ this ->processStmtNodes ($ expr , $ expr ->stmts , $ closureScope , $ closureStmtsCallback , StatementContext::createTopLevel ());
4278
4280
$ nodeCallback (new ClosureReturnStatementsNode (
@@ -4288,6 +4290,7 @@ private function processClosureNode(
4288
4290
}
4289
4291
4290
4292
$ count = 0 ;
4293
+ $ closureResultScope = null ;
4291
4294
do {
4292
4295
$ prevScope = $ closureScope ;
4293
4296
@@ -4297,8 +4300,15 @@ private function processClosureNode(
4297
4300
foreach ($ intermediaryClosureScopeResult ->getExitPoints () as $ exitPoint ) {
4298
4301
$ intermediaryClosureScope = $ intermediaryClosureScope ->mergeWith ($ exitPoint ->getScope ());
4299
4302
}
4303
+
4304
+ if ($ expr ->getAttribute (ImmediatelyInvokedClosureVisitor::ATTRIBUTE_NAME ) === true ) {
4305
+ $ closureResultScope = $ intermediaryClosureScope ;
4306
+ break ;
4307
+ }
4308
+
4300
4309
$ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters );
4301
- $ closureScope = $ closureScope ->processClosureScope ($ expr , $ intermediaryClosureScope , $ prevScope , $ byRefUses );
4310
+ $ closureScope = $ closureScope ->processClosureScope ($ intermediaryClosureScope , $ prevScope , $ byRefUses );
4311
+
4302
4312
if ($ closureScope ->equals ($ prevScope )) {
4303
4313
break ;
4304
4314
}
@@ -4308,6 +4318,10 @@ private function processClosureNode(
4308
4318
$ count ++;
4309
4319
} while ($ count < self ::LOOP_SCOPE_ITERATIONS );
4310
4320
4321
+ if ($ closureResultScope === null ) {
4322
+ $ closureResultScope = $ closureScope ;
4323
+ }
4324
+
4311
4325
$ statementResult = $ this ->processStmtNodes ($ expr , $ expr ->stmts , $ closureScope , $ closureStmtsCallback , StatementContext::createTopLevel ());
4312
4326
$ nodeCallback (new ClosureReturnStatementsNode (
4313
4327
$ expr ,
@@ -4318,7 +4332,7 @@ private function processClosureNode(
4318
4332
array_merge ($ statementResult ->getImpurePoints (), $ closureImpurePoints ),
4319
4333
), $ closureScope );
4320
4334
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 );
4322
4336
}
4323
4337
4324
4338
/**
0 commit comments