diff --git a/src/Psalm/Type/Union.php b/src/Psalm/Type/Union.php index 0e887334d..c8ecd8cb1 100644 --- a/src/Psalm/Type/Union.php +++ b/src/Psalm/Type/Union.php @@ -873,7 +873,9 @@ class Union $input_atomic_type->param_name, $input_atomic_type->as_type ? new Union([$input_atomic_type->as_type]) - : Type::getMixed() + : ($input_atomic_type->as === 'object' + ? Type::getObject() + : Type::getMixed()) ); } } diff --git a/tests/Template/TemplateTest.php b/tests/Template/TemplateTest.php index c94fa584c..f7212cd62 100644 --- a/tests/Template/TemplateTest.php +++ b/tests/Template/TemplateTest.php @@ -1508,6 +1508,57 @@ class TemplateTest extends TestCase echo Foo(DateTime::class)->format("c");', ], + 'genericInterface' => [ + ' $t + * @return T + */ + function generic(string $t) { + return f($t)->get(); + } + + /** @template T as object */ + interface I { + /** @return T */ + public function get() {} + } + + /** + * @template T as object + * @template-implements I + */ + class C implements I { + /** + * @var T + */ + public $t; + + /** + * @param T $t + */ + public function __construct(object $t) { + $this->t = $t; + } + + /** + * @return T + */ + public function get() { + return $this->t; + } + } + + /** + * @template T as object + * @param class-string $t + * @return I + */ + function f(string $t) { + return new C(new $t); + }', + ], ]; }