1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Fix #702 - prevent bad array to iterable cast

This commit is contained in:
Matt Brown 2018-04-30 13:17:09 -04:00
parent acacde173e
commit 6e67030925
2 changed files with 72 additions and 19 deletions

View File

@ -490,28 +490,69 @@ class TypeChecker
return false;
}
if ($container_type_part instanceof TNamedObject &&
strtolower($container_type_part->value) === 'iterable' &&
(
$input_type_part instanceof TArray ||
$input_type_part instanceof ObjectLike ||
(
$input_type_part instanceof TNamedObject &&
(
strtolower($input_type_part->value) === 'traversable'
|| $codebase->classExtendsOrImplements(
$input_type_part->value,
'Traversable'
)
|| $codebase->interfaceExtends(
$input_type_part->value,
'Traversable'
if ($container_type_part instanceof TNamedObject
&& strtolower($container_type_part->value) === 'iterable'
) {
if ($input_type_part instanceof TArray || $input_type_part instanceof ObjectLike) {
if (!$container_type_part instanceof TGenericObject) {
return true;
}
if ($input_type_part instanceof ObjectLike) {
$input_type_part = $input_type_part->getGenericArrayType();
}
$all_types_contain = true;
foreach ($input_type_part->type_params as $i => $input_param) {
$container_param = $container_type_part->type_params[$i];
if ($i === 0
&& $input_param->isMixed()
&& $container_param->hasString()
&& $container_param->hasInt()
) {
continue;
}
if (!$input_param->isEmpty() &&
!self::isContainedBy(
$codebase,
$input_param,
$container_param,
$input_param->ignore_nullable_issues,
$input_param->ignore_falsable_issues,
$has_scalar_match,
$type_coerced,
$type_coerced_from_mixed
)
) {
$all_types_contain = false;
}
}
if ($all_types_contain) {
$to_string_cast = false;
return true;
}
return false;
}
if ($input_type_part instanceof TNamedObject
&& (strtolower($input_type_part->value) === 'traversable'
|| $codebase->classExtendsOrImplements(
$input_type_part->value,
'Traversable'
) || $codebase->interfaceExtends(
$input_type_part->value,
'Traversable'
)
)
)
) {
return true;
) {
return true;
}
}
if ($container_type_part instanceof TScalar && $input_type_part instanceof Scalar) {

View File

@ -858,6 +858,18 @@ class FunctionCallTest extends TestCase
}',
'error_message' => 'FalsableReturnStatement',
],
'complainAboutArrayToIterable' => [
'<?php
class A {}
class B {}
/**
* @param iterable<mixed,A> $p
*/
function takesIterableOfA(iterable $p): void {}
takesIterableOfA([new B]); // should complain',
'error_message' => 'InvalidArgument',
],
];
}
}