119
119
use PHPStan \Node \VarTagChangedExpressionTypeNode ;
120
120
use PHPStan \Parser \ArrowFunctionArgVisitor ;
121
121
use PHPStan \Parser \ClosureArgVisitor ;
122
+ use PHPStan \Parser \ImmediatelyInvokedClosureVisitor ;
122
123
use PHPStan \Parser \Parser ;
123
124
use PHPStan \Php \PhpVersion ;
124
125
use PHPStan \PhpDoc \PhpDocInheritanceResolver ;
@@ -4232,7 +4233,7 @@ private function processClosureNode(
4232
4233
}
4233
4234
4234
4235
$ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters );
4235
- $ closureScope = $ closureScope ->processClosureScope ($ expr , $ scope , null , $ byRefUses );
4236
+ $ closureScope = $ closureScope ->processClosureScope ($ scope , null , $ byRefUses );
4236
4237
$ closureType = $ closureScope ->getAnonymousFunctionReflection ();
4237
4238
if (!$ closureType instanceof ClosureType) {
4238
4239
throw new ShouldNotHappenException ();
@@ -4277,6 +4278,7 @@ private function processClosureNode(
4277
4278
4278
4279
$ gatheredReturnStatements [] = new ReturnStatement ($ scope , $ node );
4279
4280
};
4281
+
4280
4282
if (count ($ byRefUses ) === 0 ) {
4281
4283
$ statementResult = $ this ->processStmtNodes ($ expr , $ expr ->stmts , $ closureScope , $ closureStmtsCallback , StatementContext::createTopLevel ());
4282
4284
$ nodeCallback (new ClosureReturnStatementsNode (
@@ -4292,6 +4294,7 @@ private function processClosureNode(
4292
4294
}
4293
4295
4294
4296
$ count = 0 ;
4297
+ $ closureResultScope = null ;
4295
4298
do {
4296
4299
$ prevScope = $ closureScope ;
4297
4300
@@ -4301,8 +4304,15 @@ private function processClosureNode(
4301
4304
foreach ($ intermediaryClosureScopeResult ->getExitPoints () as $ exitPoint ) {
4302
4305
$ intermediaryClosureScope = $ intermediaryClosureScope ->mergeWith ($ exitPoint ->getScope ());
4303
4306
}
4307
+
4308
+ if ($ expr ->getAttribute (ImmediatelyInvokedClosureVisitor::ATTRIBUTE_NAME ) === true ) {
4309
+ $ closureResultScope = $ intermediaryClosureScope ;
4310
+ break ;
4311
+ }
4312
+
4304
4313
$ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters );
4305
- $ closureScope = $ closureScope ->processClosureScope ($ expr , $ intermediaryClosureScope , $ prevScope , $ byRefUses );
4314
+ $ closureScope = $ closureScope ->processClosureScope ($ intermediaryClosureScope , $ prevScope , $ byRefUses );
4315
+
4306
4316
if ($ closureScope ->equals ($ prevScope )) {
4307
4317
break ;
4308
4318
}
@@ -4312,6 +4322,10 @@ private function processClosureNode(
4312
4322
$ count ++;
4313
4323
} while ($ count < self ::LOOP_SCOPE_ITERATIONS );
4314
4324
4325
+ if ($ closureResultScope === null ) {
4326
+ $ closureResultScope = $ closureScope ;
4327
+ }
4328
+
4315
4329
$ statementResult = $ this ->processStmtNodes ($ expr , $ expr ->stmts , $ closureScope , $ closureStmtsCallback , StatementContext::createTopLevel ());
4316
4330
$ nodeCallback (new ClosureReturnStatementsNode (
4317
4331
$ expr ,
@@ -4322,7 +4336,7 @@ private function processClosureNode(
4322
4336
array_merge ($ statementResult ->getImpurePoints (), $ closureImpurePoints ),
4323
4337
), $ closureScope );
4324
4338
4325
- return new ProcessClosureResult ($ scope ->processClosureScope ($ expr , $ closureScope , null , $ byRefUses ), $ statementResult ->getThrowPoints (), $ statementResult ->getImpurePoints (), $ invalidateExpressions );
4339
+ return new ProcessClosureResult ($ scope ->processClosureScope ($ closureResultScope , null , $ byRefUses ), $ statementResult ->getThrowPoints (), $ statementResult ->getImpurePoints (), $ invalidateExpressions );
4326
4340
}
4327
4341
4328
4342
/**
0 commit comments