mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Fix closure param type inference in generic context
This commit is contained in:
parent
fb56d5ce58
commit
2e4d75d6bd
@ -405,13 +405,28 @@ class ArgumentsAnalyzer
|
||||
if ($replaced_type_part instanceof TCallable
|
||||
|| $replaced_type_part instanceof TClosure
|
||||
) {
|
||||
if (isset($replaced_type_part->params[$closure_param_offset]->type)
|
||||
&& !$replaced_type_part->params[$closure_param_offset]->type->hasTemplate()
|
||||
) {
|
||||
if (isset($replaced_type_part->params[$closure_param_offset]->type)) {
|
||||
$param_type = $replaced_type_part->params[$closure_param_offset]->type;
|
||||
|
||||
if ($param_type->hasTemplate()) {
|
||||
$param_type = TypeExpander::expandUnion(
|
||||
$codebase,
|
||||
$param_type,
|
||||
$class_storage->name ?? null,
|
||||
$calling_class_storage->name ?? null,
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
$calling_class_storage->final ?? false,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
if ($param_storage->type && !$param_type_inferred) {
|
||||
$type_match_found = UnionTypeComparator::isContainedBy(
|
||||
$codebase,
|
||||
$replaced_type_part->params[$closure_param_offset]->type,
|
||||
$param_type,
|
||||
$param_storage->type
|
||||
);
|
||||
|
||||
@ -422,7 +437,7 @@ class ArgumentsAnalyzer
|
||||
|
||||
$newly_inferred_type = Type::combineUnionTypes(
|
||||
$newly_inferred_type,
|
||||
$replaced_type_part->params[$closure_param_offset]->type,
|
||||
$param_type,
|
||||
$codebase
|
||||
);
|
||||
}
|
||||
|
@ -111,6 +111,43 @@ class CallableTest extends TestCase
|
||||
'error_levels' => [],
|
||||
'7.4',
|
||||
],
|
||||
'inferArgFromClassContextInGenericContext' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template A
|
||||
*/
|
||||
final class ArrayList
|
||||
{
|
||||
/**
|
||||
* @template B
|
||||
* @param Closure(A): B $ab
|
||||
* @return ArrayList<B>
|
||||
*/
|
||||
public function map(Closure $ab): ArrayList
|
||||
{
|
||||
throw new RuntimeException("???");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param ArrayList<T> $list
|
||||
* @return ArrayList<array{T}>
|
||||
*/
|
||||
function asTupled(ArrayList $list): ArrayList
|
||||
{
|
||||
return $list->map(function ($_a) {
|
||||
return [$_a];
|
||||
});
|
||||
}
|
||||
/** @var ArrayList<int> $a */
|
||||
$a = new ArrayList();
|
||||
$b = asTupled($a);
|
||||
',
|
||||
'assertions' => [
|
||||
'$b' => 'ArrayList<array{int}>',
|
||||
],
|
||||
],
|
||||
'varReturnType' => [
|
||||
'<?php
|
||||
$add_one = function(int $a) : int {
|
||||
|
Loading…
Reference in New Issue
Block a user