diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php index c0aec026878..5fac60a04fb 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php @@ -409,17 +409,13 @@ function ($assertion) use ($generic_params) { $generic_param_types = null; if ($storage->template_types) { - $declaring_fq_class_name = $declaring_method_id - ? $declaring_method_id->fq_class_name - : $fq_class_name; - foreach ($storage->template_types as $template_name => $base_type) { if (isset($template_result->upper_bounds[$template_name][$fq_class_name])) { $generic_param_type = $template_result->upper_bounds[$template_name][$fq_class_name]->type; } elseif ($storage->template_extended_params && $template_result->upper_bounds) { $generic_param_type = self::getGenericParamForOffset( - $declaring_fq_class_name, + $fq_class_name, $template_name, $storage->template_extended_params, array_map( diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index ebf915932f2..811b2efdfe9 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -440,28 +440,18 @@ public static function getGenericParamForOffset( bool $mapped = false ): Type\Union { if (isset($found_generic_params[$template_name][$fq_class_name])) { - if (!$mapped && isset($template_extended_params[$fq_class_name][$template_name])) { - foreach ($template_extended_params[$fq_class_name][$template_name]->getAtomicTypes() as $t) { - if ($t instanceof Type\Atomic\TTemplateParam) { - if ($t->param_name !== $template_name) { - return $t->as; - } - } - } - } - return $found_generic_params[$template_name][$fq_class_name]; } - foreach ($template_extended_params as $type_map) { + foreach ($template_extended_params as $extended_class_name => $type_map) { foreach ($type_map as $extended_template_name => $extended_type) { foreach ($extended_type->getAtomicTypes() as $extended_atomic_type) { if ($extended_atomic_type instanceof Type\Atomic\TTemplateParam && $extended_atomic_type->param_name === $template_name - && $extended_template_name !== $template_name + && $extended_atomic_type->defining_class === $fq_class_name ) { return self::getGenericParamForOffset( - $fq_class_name, + $extended_class_name, $extended_template_name, $template_extended_params, $found_generic_params, diff --git a/tests/Template/ClassTemplateExtendsTest.php b/tests/Template/ClassTemplateExtendsTest.php index 650f80417f0..0ad70a20772 100644 --- a/tests/Template/ClassTemplateExtendsTest.php +++ b/tests/Template/ClassTemplateExtendsTest.php @@ -4372,6 +4372,16 @@ public function foo() : string { /** @extends Collection */ class StringCollection extends Collection {}', ], + 'noInfiniteLoop' => [ + ' + */ + class ObjectStorage extends SplObjectStorage {} + + $foo = new ObjectStorage();' + ], ]; }