1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Fix #663 - infer array return types for closures

This commit is contained in:
Matt Brown 2018-04-10 13:05:31 -04:00
parent 9bdf9eefd3
commit fe033f1b6c
2 changed files with 58 additions and 18 deletions

View File

@ -481,31 +481,35 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
$storage->return_type_location
);
if ($this->function->inferredType
&& (!$storage->return_type
$closure_yield_types = [];
$closure_return_types = EffectsAnalyser::getReturnTypes(
$this->function->stmts,
$closure_yield_types,
$ignore_nullable_issues,
$ignore_falsable_issues,
true
);
if ($closure_return_types) {
$closure_return_type = new Type\Union($closure_return_types);
if (!$storage->return_type
|| $storage->return_type->isMixed()
|| TypeChecker::isContainedBy(
$project_checker->codebase,
$this->function->inferredType,
$closure_return_type,
$storage->return_type
)
)
) {
$closure_yield_types = [];
$closure_return_types = EffectsAnalyser::getReturnTypes(
$this->function->stmts,
$closure_yield_types,
$ignore_nullable_issues,
$ignore_falsable_issues,
true
);
if ($closure_return_types && $this->function->inferredType) {
/** @var Type\Atomic\Fn */
$closure_atomic = $this->function->inferredType->getTypes()['Closure'];
$closure_atomic->return_type = new Type\Union($closure_return_types);
) {
if ($this->function->inferredType) {
/** @var Type\Atomic\Fn */
$closure_atomic = $this->function->inferredType->getTypes()['Closure'];
$closure_atomic->return_type = $closure_return_type;
}
}
}
}
if ($context->collect_references

View File

@ -431,6 +431,42 @@ class CallableTest extends TestCase
],
'error_levels' => ['MissingClosureReturnType'],
],
'inferArrayMapReturnTypeWithoutTypehints' => [
'<?php
/**
* @param array{0:string,1:string}[] $ret
* @return array{0:string,1:int}[]
*/
function f(array $ret) : array
{
return array_map(
function (array $row) {
return [
strval($row[0]),
intval($row[1]),
];
}, $ret);
}',
'assertions' => [],
'error_levels' => ['MissingClosureReturnType'],
],
'inferArrayMapReturnTypeWithTypehints' => [
'<?php
/**
* @param array{0:string,1:string}[] $ret
* @return array{0:string,1:int}[]
*/
function f(array $ret): array
{
return array_map(
function (array $row): array {
return [
strval($row[0]),
intval($row[1]),
];
}, $ret);
}',
],
];
}