From 23f8967fb520285cb5e4722f376dac0566848668 Mon Sep 17 00:00:00 2001 From: Brown Date: Thu, 6 Feb 2020 19:40:18 -0500 Subject: [PATCH] Fix conditional class-string template replacement --- src/Psalm/Type/Union.php | 54 ++++++++++----------- tests/Template/ClassTemplateExtendsTest.php | 27 +++++++++++ 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/src/Psalm/Type/Union.php b/src/Psalm/Type/Union.php index a502106d6..3f6302f96 100644 --- a/src/Psalm/Type/Union.php +++ b/src/Psalm/Type/Union.php @@ -1186,38 +1186,38 @@ class Union } elseif ($atomic_type instanceof Type\Atomic\TTemplateParamClass) { $template_type = isset($template_types[$atomic_type->param_name][$atomic_type->defining_class]) ? clone $template_types[$atomic_type->param_name][$atomic_type->defining_class][0] - : Type::getMixed(); + : null; - foreach ($template_type->types as $template_type_part) { - if ($template_type_part instanceof Type\Atomic\TMixed - || $template_type_part instanceof Type\Atomic\TObject - ) { - $unknown_class_string = new Type\Atomic\TClassString(); + $class_template_type = null; - $new_types[$unknown_class_string->getKey()] = $unknown_class_string; - $keys_to_unset[] = $key; - } elseif ($template_type_part instanceof Type\Atomic\TNamedObject) { - $literal_class_string = new Type\Atomic\TClassString( - $template_type_part->value, - $template_type_part - ); + if ($template_type) { + foreach ($template_type->types as $template_type_part) { + if ($template_type_part instanceof Type\Atomic\TMixed + || $template_type_part instanceof Type\Atomic\TObject + ) { + $class_template_type = new Type\Atomic\TClassString(); + } elseif ($template_type_part instanceof Type\Atomic\TNamedObject) { + $class_template_type = new Type\Atomic\TClassString( + $template_type_part->value, + $template_type_part + ); + } elseif ($template_type_part instanceof Type\Atomic\TTemplateParam) { + $first_atomic_type = array_values($template_type_part->as->types)[0]; - $new_types[$literal_class_string->getKey()] = $literal_class_string; - $keys_to_unset[] = $key; - } elseif ($template_type_part instanceof Type\Atomic\TTemplateParam) { - $first_atomic_type = array_values($template_type_part->as->types)[0]; - - $mapped_template_class = new Type\Atomic\TTemplateParamClass( - $template_type_part->param_name, - $template_type_part->as->getId(), - $first_atomic_type instanceof TNamedObject ? $first_atomic_type : null, - $template_type_part->defining_class - ); - - $new_types[$mapped_template_class->getKey()] = $mapped_template_class; - $keys_to_unset[] = $key; + $class_template_type = new Type\Atomic\TTemplateParamClass( + $template_type_part->param_name, + $template_type_part->as->getId(), + $first_atomic_type instanceof TNamedObject ? $first_atomic_type : null, + $template_type_part->defining_class + ); + } } } + + if ($class_template_type) { + $keys_to_unset[] = $key; + $new_types[$class_template_type->getKey()] = $class_template_type; + } } elseif ($atomic_type instanceof Type\Atomic\TTemplateIndexedAccess) { $keys_to_unset[] = $key; diff --git a/tests/Template/ClassTemplateExtendsTest.php b/tests/Template/ClassTemplateExtendsTest.php index f047810c5..b33c34add 100644 --- a/tests/Template/ClassTemplateExtendsTest.php +++ b/tests/Template/ClassTemplateExtendsTest.php @@ -2930,6 +2930,33 @@ class ClassTemplateExtendsTest extends TestCase } }', ], + 'templateInheritanceWithParentTemplateTypes' => [ + ' $t + * @return ?T2 + */ + public function get($t) { + return new $t; + } + } + + class AChild extends A { + /** + * @template T3 + * @param class-string $t + * @return ?T3 + */ + public function get($t) { + return new $t; + } + }' + ], ]; }