Skip to content

Commit 8b906cf

Browse files
ondrejmirtesclaude
andcommitted
Do not mark callable-owned template types as arguments when entering a function
Templates declared by callable<T>(...)/Closure<T>(...) types in a function signature were only recognized as owned by the callable when used as a bare parameter or return type. When the template occurred only inside another type, like callable<T of object>(class-string<T> $class): list<T>, it was marked as an argument type and invoking the callable could not resolve it. Such templates always have the anonymous function template scope, which the entered function's own templates never have, so they are recognized by scope. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 4f7c44c commit 8b906cf

2 files changed

Lines changed: 14 additions & 0 deletions

File tree

‎src/Type/Generic/TemplateTypeHelper.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ public static function toArgument(Type $type): Type
131131
}
132132

133133
if ($type instanceof TemplateType) {
134+
// templates declared by a callable<T>(...)/Closure<T>(...) type in the signature
135+
// belong to the callable value, not to the entered function
136+
if ($type->getScope()->equals(TemplateTypeScope::createWithAnonymousFunction())) {
137+
return $traverse($type);
138+
}
139+
134140
return $traverse($type->toArgument());
135141
}
136142

‎tests/PHPStan/Analyser/nsrt/generic-callables.php‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,11 @@ function testNestedClosures(Closure $closure, string $str, int $int): void
7878
$result = $closure1($int);
7979
assertType('int|string', $result);
8080
}
81+
82+
/**
83+
* @param callable<T of object>(class-string<T> $class): list<T> $factory
84+
*/
85+
function templateOnlyInsideParameterType(callable $factory): void
86+
{
87+
assertType('list<DateTimeImmutable>', $factory(\DateTimeImmutable::class));
88+
}

0 commit comments

Comments
 (0)