mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Fix #5211 - prevent infinite loop in template inference
This commit is contained in:
parent
7e61012359
commit
6fb7423c68
@ -409,17 +409,13 @@ class NewAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\CallAna
|
||||
$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(
|
||||
|
@ -440,28 +440,18 @@ class CallAnalyzer
|
||||
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,
|
||||
|
@ -4372,6 +4372,16 @@ class ClassTemplateExtendsTest extends TestCase
|
||||
/** @extends Collection<string> */
|
||||
class StringCollection extends Collection {}',
|
||||
],
|
||||
'noInfiniteLoop' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template TValue
|
||||
* @template-extends SplObjectStorage<object, TValue>
|
||||
*/
|
||||
class ObjectStorage extends SplObjectStorage {}
|
||||
|
||||
$foo = new ObjectStorage();'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user