Background
Generic function bar calls generic function foo. Their templates (T and Q, respectively) have different names but the exact same definition.
A parameter of type value-of<Q> is passed unchanged to foo as a parameter of type value-of<T>.
Problem
PHPStan (both v1.12.7 and whatever version currently runs in the playground) deems the parameter type unsolvable.
This also happens if the templates are both named T (because, of course, they still are different templates).
Example code
<?php declare(strict_types = 1);
class Bug
{
/**
* @template T of BackedEnum
* @param class-string<T> $class
* @param value-of<T> $value
*/
public static function foo(string $class, mixed $value): void
{
}
/**
* @template Q of BackedEnum
* @param class-string<Q> $class
* @param value-of<Q> $value
*/
public static function bar(string $class, mixed $value): void
{
// Parameter #2 $value of static method Bug::foo() contains unresolvable type.
self::foo($class, $value);
}
}
Playground links
Same code as above: https://phpstan.org/r/b8dd4d29-d647-4d2e-bff5-cc6cddf4d9af
With both templates named T (same error): https://phpstan.org/r/32dce00f-6cec-486c-8479-25a2ac2b7c46
With template T unrestricted and Q of BackedEnum (same error): https://phpstan.org/r/83fcca8c-8c3d-448e-810d-d73ed3faecd9
With both templates unrestricted (no errors, but unfeasible for my use case): https://phpstan.org/r/1b4fe7c2-7516-4e98-8938-3d98908ef414
Expected output
No errors. PHPStan should be able to infer that a value-of<Q> is a value-of<T> if Q is equal to, or a subtype of, T.
Did PHPStan help you today? Did it make you happy in any way?
PHPStan turns PHP into something resembling a programming language. 😄 So yes, it makes me happy!
Background
Generic function
barcalls generic functionfoo. Their templates (TandQ, respectively) have different names but the exact same definition.A parameter of type
value-of<Q>is passed unchanged tofooas a parameter of typevalue-of<T>.Problem
PHPStan (both v1.12.7 and whatever version currently runs in the playground) deems the parameter type unsolvable.
This also happens if the templates are both named
T(because, of course, they still are different templates).Example code
Playground links
Same code as above: https://phpstan.org/r/b8dd4d29-d647-4d2e-bff5-cc6cddf4d9af
With both templates named
T(same error): https://phpstan.org/r/32dce00f-6cec-486c-8479-25a2ac2b7c46With template
Tunrestricted andQ of BackedEnum(same error): https://phpstan.org/r/83fcca8c-8c3d-448e-810d-d73ed3faecd9With both templates unrestricted (no errors, but unfeasible for my use case): https://phpstan.org/r/1b4fe7c2-7516-4e98-8938-3d98908ef414
Expected output
No errors. PHPStan should be able to infer that a
value-of<Q>is avalue-of<T>ifQis equal to, or a subtype of,T.Did PHPStan help you today? Did it make you happy in any way?
PHPStan turns PHP into something resembling a programming language. 😄 So yes, it makes me happy!