diff --git a/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php b/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php index 89119466d..a3fd78e28 100644 --- a/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/AssignmentMapVisitor.php @@ -77,11 +77,13 @@ class AssignmentMapVisitor extends PhpParser\NodeVisitorAbstract || $node instanceof PhpParser\Node\Expr\MethodCall || $node instanceof PhpParser\Node\Expr\StaticCall ) { - foreach ($node->getArgs() as $arg) { - $arg_var_id = ExpressionIdentifier::getRootVarId($arg->value, $this->this_class_name); + if (!$node->isFirstClassCallable()) { + foreach ($node->getArgs() as $arg) { + $arg_var_id = ExpressionIdentifier::getRootVarId($arg->value, $this->this_class_name); - if ($arg_var_id) { - $this->assignment_map[$arg_var_id][$arg_var_id] = true; + if ($arg_var_id) { + $this->assignment_map[$arg_var_id][$arg_var_id] = true; + } } } diff --git a/tests/ClosureTest.php b/tests/ClosureTest.php index e5f6c9551..def99f995 100644 --- a/tests/ClosureTest.php +++ b/tests/ClosureTest.php @@ -773,6 +773,40 @@ class ClosureTest extends TestCase [], '8.1', ], + 'FirstClassCallable:AssignmentVisitorMap' => [ + ' */ + public array $handlers = []; + + public function register(): void { + foreach ([1, 2, 3] as $index) { + $this->push($this->handler(...)); + } + } + + /** + * @param Closure():void $closure + * @return void + */ + private function push(\Closure $closure): void { + $this->handlers[] = $closure; + } + + private function handler(): void { + } + } + + $test = new Test(); + $test->register(); + $handlers = $test->handlers; + ', + 'assertions' => [ + '$handlers' => 'list', + ], + 'ignored_issues' => [], + 'php_version' => '8.1', + ], 'arrowFunctionReturnsNeverImplictly' => [ '