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

Fix #4731 - expand out class-bound generic types when evaluating instance method

This commit is contained in:
Matt Brown 2020-11-29 21:36:50 -05:00 committed by Daniil Gentili
parent 1f8e80e820
commit 9789b53617
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
3 changed files with 42 additions and 4 deletions

View File

@ -570,7 +570,8 @@ class ArgumentsAnalyzer
$class_storage,
$self_fq_class_name,
$calling_class_storage,
$function_storage->template_types ?: []
$function_storage->template_types ?: [],
$class_generic_params
);
if ($template_types) {

View File

@ -341,15 +341,20 @@ class CallAnalyzer
}
/**
* This gets all the template params (and their types) that we think
* we'll need to know about
*
* @return array<string, array<string, Type\Union>>
* @param array<string, non-empty-array<string, Type\Union>> $existing_template_types
* @param array<string, array<string, Type\Union>> $class_template_params
*/
public static function getTemplateTypesForCall(
\Psalm\Codebase $codebase,
?ClassLikeStorage $declaring_class_storage,
?string $appearing_class_name,
?ClassLikeStorage $calling_class_storage,
array $existing_template_types = []
array $existing_template_types = [],
array $class_template_params = []
) : array {
$template_types = $existing_template_types;
@ -369,7 +374,7 @@ class CallAnalyzer
$atomic_type->defining_class,
$atomic_type->param_name,
$calling_class_storage->template_extended_params,
$template_types
$class_template_params + $template_types
);
} else {
$output_type_candidate = new Type\Union([$atomic_type]);
@ -392,7 +397,8 @@ class CallAnalyzer
} elseif ($declaring_class_storage->template_types) {
foreach ($declaring_class_storage->template_types as $template_name => $type_map) {
foreach ($type_map as $key => $type) {
$template_types[$template_name][$key] = $type;
$template_types[$template_name][$key]
= $class_template_params[$template_name][$key] ?? $type;
}
}
}

View File

@ -3770,6 +3770,37 @@ class ClassTemplateTest extends TestCase
}',
'error_message' => 'InvalidArgument',
],
'bindRedirectedTemplate' => [
'<?php
/**
* @template TIn
* @template TOut
*/
final class Map
{
/** @param Closure(TIn): TOut $c */
public function __construct(private Closure $c) {}
/**
* @template TIn2 as list<TIn>
* @param TIn2 $in
* @return list<TOut>
*/
public function __invoke(array $in) : array {
return array_map(
$this->c,
$in
);
}
}
$m = new Map(fn(int $num) => (string) $num);
$m(["a"]);',
'error_message' => 'InvalidScalarArgument',
[],
false,
'8.0'
],
];
}
}