PHPantom version
main
Installation method
Built from source
Operating system
Linux x86_64
Editor
Zed
Bug description
When a template parameter is not bound to a concrete type (either
because no argument carries the binding, or because the class was
instantiated without a generic annotation), the raw template name
(e.g. TValue, TKey, TReduceReturnType, TClosure) leaks
through to the type error checker. The diagnostic then reports
"expects TValue, got string" instead of recognising the parameter
as unresolved and suppressing the check.
This affects both function-level and class-level templates:
- Function-level:
@template TReduceReturnType with
@return TReduceReturnType where no argument binds the param.
- Class-level:
Collection<TKey, TValue> where the Collection
was created without a generic annotation (e.g. collect([]),
new Collection()). Methods like push($item) still have
@param TValue $item with the raw template name, so passing
a string fires "expects TValue, got string".
Template substitution should either resolve the parameter from the
call-site arguments / class-level generic annotation, or fall back
to the template's bound (defaulting to mixed) so the raw name
never leaks through to downstream diagnostics.
Reproducer (function-level):
/**
* @template TReduceReturnType
* @return TReduceReturnType
*/
function reduce_result() { return null; }
function takes_int(int $x): void {}
function test(): void {
$result = reduce_result();
takes_int($result); // false positive: "expects int, got TReduceReturnType"
}
Reproducer (class-level):
/**
* @template TValue
*/
class Collection {
/** @param TValue $item */
public function push($item): void {}
}
function test(): void {
$items = new Collection(); // no generic annotation
$items->push('hello'); // false positive: "expects TValue, got string"
}
Steps to reproduce
run the diagnostics
Error output or panic trace
.phpantom.toml
Additional context
No response
PHPantom version
main
Installation method
Built from source
Operating system
Linux x86_64
Editor
Zed
Bug description
When a template parameter is not bound to a concrete type (either
because no argument carries the binding, or because the class was
instantiated without a generic annotation), the raw template name
(e.g.
TValue,TKey,TReduceReturnType,TClosure) leaksthrough to the type error checker. The diagnostic then reports
"expects TValue, got string" instead of recognising the parameter
as unresolved and suppressing the check.
This affects both function-level and class-level templates:
@template TReduceReturnTypewith@return TReduceReturnTypewhere no argument binds the param.Collection<TKey, TValue>where the Collectionwas created without a generic annotation (e.g.
collect([]),new Collection()). Methods likepush($item)still have@param TValue $itemwith the raw template name, so passinga
stringfires "expects TValue, got string".Template substitution should either resolve the parameter from the
call-site arguments / class-level generic annotation, or fall back
to the template's bound (defaulting to
mixed) so the raw namenever leaks through to downstream diagnostics.
Reproducer (function-level):
Reproducer (class-level):
Steps to reproduce
run the diagnostics
Error output or panic trace
.phpantom.toml
Additional context
No response