diff --git a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php index aee57db63..43ddf267a 100644 --- a/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php +++ b/src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php @@ -215,10 +215,9 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour $functionlike_types = []; - if ($this->functionlike_node_scanners) { - $functionlike_node_scanner = end($this->functionlike_node_scanners); + foreach ($this->functionlike_node_scanners as $functionlike_node_scanner) { $functionlike_storage = $functionlike_node_scanner->storage; - $functionlike_types = $functionlike_storage->template_types ?? []; + $functionlike_types += $functionlike_storage->template_types ?? []; } $functionlike_node_scanner = new Reflector\FunctionLikeNodeScanner( @@ -341,8 +340,7 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour $template_types = $classlike_storage->template_types ?? []; } - if ($this->functionlike_node_scanners) { - $functionlike_node_scanner = end($this->functionlike_node_scanners); + foreach ($this->functionlike_node_scanners as $functionlike_node_scanner) { $functionlike_storage = $functionlike_node_scanner->storage; $template_types += $functionlike_storage->template_types ?? []; } diff --git a/tests/Template/FunctionTemplateTest.php b/tests/Template/FunctionTemplateTest.php index 20b03212d..be655d688 100644 --- a/tests/Template/FunctionTemplateTest.php +++ b/tests/Template/FunctionTemplateTest.php @@ -1402,6 +1402,37 @@ class FunctionTemplateTest extends TestCase } }' ], + 'doublyNestedFunctionTemplates' => [ + ' $iterable + * @psalm-param (callable(Tk, Tv): bool)|null $predicate + * + * @psalm-return iterable + */ + function filter_with_key(iterable $iterable, ?callable $predicate = null): iterable + { + return (static function () use ($iterable, $predicate): Generator { + $predicate = $predicate ?? + /** + * @psalm-param Tk $_k + * @psalm-param Tv $v + * + * @return bool + */ + function($_k, $v) { return (bool) $v; }; + + foreach ($iterable as $k => $v) { + if ($predicate($k, $v)) { + yield $k => $v; + } + } + })(); + }' + ], ]; }