Unresolvable type with `value-of` and generics
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!