1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

bugfix: resolve recursive conditional return types containing templates

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
This commit is contained in:
Maximilian Bösing 2023-09-11 00:02:11 +02:00
parent 3dc00518c6
commit 7c8a5e8b09
No known key found for this signature in database
GPG Key ID: 9A8988C93CEC81A3
3 changed files with 32 additions and 3 deletions

View File

@ -183,6 +183,7 @@ class MethodCallReturnTypeFetcher
$self_fq_class_name,
$statements_analyzer,
$args,
$template_result,
);
if ($return_type_candidate) {
@ -449,7 +450,7 @@ class MethodCallReturnTypeFetcher
$stmt_var_type = $context->vars_in_scope[$var_id]->setParentNodes(
$var_nodes,
);
$context->vars_in_scope[$var_id] = $stmt_var_type;
} else {
$method_call_node = DataFlowNode::getForMethodReturn(

View File

@ -557,7 +557,8 @@ class Methods
MethodIdentifier $method_id,
?string &$self_class,
?SourceAnalyzer $source_analyzer = null,
?array $args = null
?array $args = null,
?TemplateResult $template_result = null
): ?Union {
$original_fq_class_name = $method_id->fq_class_name;
$original_method_name = $method_id->method_name;
@ -784,9 +785,18 @@ class Methods
);
if ($found_generic_params) {
$passed_template_result = $template_result;
$template_result = new TemplateResult(
[],
$found_generic_params,
);
if ($passed_template_result !== null) {
$template_result = $template_result->merge($passed_template_result);
}
$overridden_storage_return_type = TemplateInferredTypeReplacer::replace(
$overridden_storage_return_type,
new TemplateResult([], $found_generic_params),
$template_result,
$source_analyzer->getCodebase(),
);
}

View File

@ -4,6 +4,9 @@ namespace Psalm\Internal\Type;
use Psalm\Type\Union;
use function array_merge;
use function array_replace_recursive;
/**
* This class captures the result of running Psalm's argument analysis with
* regard to generic parameters.
@ -63,4 +66,19 @@ class TemplateResult
}
}
}
public function merge(TemplateResult $result): TemplateResult
{
if ($result === $this) {
return $this;
}
$instance = clone $this;
/** @var array<string, array<string, non-empty-list<TemplateBound>>> $lower_bounds */
$lower_bounds = array_replace_recursive($instance->lower_bounds, $result->lower_bounds);
$instance->lower_bounds = $lower_bounds;
$instance->template_types = array_merge($instance->template_types, $result->template_types);
return $instance;
}
}