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

Fix #1320 - allow iterable comparison

This commit is contained in:
Matthew Brown 2019-02-10 23:51:26 -05:00
parent 8fc0b43973
commit 867ea1fa34
2 changed files with 70 additions and 3 deletions

View File

@ -693,6 +693,44 @@ class Reconciler
return Type::getMixed();
}
if ($new_var_type === 'iterable' && !$existing_var_type->hasMixed()) {
$iterable_types = [];
$did_remove_type = false;
foreach ($existing_var_atomic_types as $type) {
if ($type->isIterable($codebase)) {
$iterable_types[] = $type;
} elseif ($type instanceof TObject) {
$iterable_types[] = new Type\Atomic\TCallableObject();
$did_remove_type = true;
} else {
$did_remove_type = true;
}
}
if ((!$iterable_types || !$did_remove_type) && !$is_equality) {
if ($key && $code_location) {
self::triggerIssueForImpossible(
$existing_var_type,
$old_var_type_string,
$key,
$new_var_type,
!$did_remove_type,
$code_location,
$suppressed_issues
);
}
}
if ($iterable_types) {
return new Type\Union($iterable_types);
}
$failed_reconciliation = 2;
return Type::getMixed();
}
if ($new_var_type === 'numeric' && !$existing_var_type->hasMixed()) {
$numeric_types = [];
$did_remove_type = false;
@ -1717,6 +1755,12 @@ class Reconciler
$existing_var_type->removeType($atomic_key);
}
}
return $existing_var_type;
}
if ($new_var_type === 'iterable') {
$existing_var_type->removeType('array');
}
if ($new_var_type === 'non-empty-countable') {
@ -1797,8 +1841,6 @@ class Reconciler
) {
$existing_var_type->removeType('array-key');
$existing_var_type->addType(new TInt);
} elseif ($new_var_type === 'iterable') {
$existing_var_type->removeType('array');
} elseif (strtolower($new_var_type) === 'int'
&& isset($existing_var_type->getTypes()['array-key'])
) {

View File

@ -1186,13 +1186,38 @@ class TypeReconciliationTest extends TestCase
return is_object($maybe) ? get_class($maybe) : $maybe;
}'
],
'removeIterable' => [
'removeArrayWithIterableCheck' => [
'<?php
$s = rand(0,1) ? "foo" : [1];
if (!is_iterable($s)) {
strlen($s);
}',
],
'removeIterableWithIterableCheck' => [
'<?php
/** @var string|iterable */
$s = rand(0,1) ? "foo" : [1];
if (!is_iterable($s)) {
strlen($s);
}',
],
'removeArrayWithIterableCheckWithExit' => [
'<?php
$a = rand(0,1) ? "foo" : [1];
if (is_iterable($a)) {
return;
}
strlen($a);',
],
'removeIterableWithIterableCheckWithExit' => [
'<?php
/** @var string|iterable */
$a = rand(0,1) ? "foo" : [1];
if (is_iterable($a)) {
return;
}
strlen($a);',
],
'removeCallable' => [
'<?php
$s = rand(0,1) ? "strlen" : [1];