Code snippet that reproduces the problem
class A {}
class B {}
class A1 extends A {
public function foo() : void {}
}
class B1 extends B {
public function bar() : void {}
}
/**
* @template T1 of A
* @template T2 of B
* @param T1|T2 $type
* @return T1|T2
*/
function f(object $type) {
return new $type();
}
(f(new A1))->foo(); // should pass
(f(new B1))->bar(); // should pass
(f(new A1))->bar(); // should fail
(f(new B1))->foo(); // should fail
https://phpstan.org/r/a7b835ae-b7a1-4cda-b7ba-3b3f13713fb6
Expected output
See above
Actual output
+---------------------------------------------------------------------+
| Line | test.php |
+---------------------------------------------------------------------+
| 21 | Call to an undefined method A1|B::foo(). |
| 21 | Unable to resolve the template type T2 in call to function f |
| 22 | Call to an undefined method A|B1::bar(). |
| 22 | Unable to resolve the template type T1 in call to function f |
| 24 | Call to an undefined method A1|B::bar(). |
| 24 | Unable to resolve the template type T2 in call to function f |
| 25 | Call to an undefined method A|B1::foo(). |
| 25 | Unable to resolve the template type T1 in call to function f |
+---------------------------------------------------------------------+
Code snippet that reproduces the problem
https://phpstan.org/r/a7b835ae-b7a1-4cda-b7ba-3b3f13713fb6
Expected output
See above
Actual output