From 4a28525275829539f3a70b87fcb044e4c431028e Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Fri, 27 Dec 2019 13:01:44 -0500 Subject: [PATCH] Fix removal of traversable from iterable Fixes #2509 --- .../Internal/Type/NegatedAssertionReconciler.php | 8 +++++--- tests/TypeReconciliation/ConditionalTest.php | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php index 21c9f3312..9a3f466bc 100644 --- a/src/Psalm/Internal/Type/NegatedAssertionReconciler.php +++ b/src/Psalm/Internal/Type/NegatedAssertionReconciler.php @@ -238,13 +238,15 @@ class NegatedAssertionReconciler extends Reconciler } if (strtolower($assertion) === 'traversable' - && isset($existing_var_type->getTypes()['iterable']) + && isset($existing_var_atomic_types['iterable']) ) { + /** @var Type\Atomic\TIterable */ + $iterable = $existing_var_atomic_types['iterable']; $existing_var_type->removeType('iterable'); $existing_var_type->addType(new TArray( [ - new Type\Union([new TArrayKey]), - new Type\Union([new TMixed]), + $iterable->type_params[0], + $iterable->type_params[1], ] )); } elseif (strtolower($assertion) === 'int' diff --git a/tests/TypeReconciliation/ConditionalTest.php b/tests/TypeReconciliation/ConditionalTest.php index 7bbe333be..83d933014 100644 --- a/tests/TypeReconciliation/ConditionalTest.php +++ b/tests/TypeReconciliation/ConditionalTest.php @@ -2376,6 +2376,20 @@ class ConditionalTest extends \Psalm\Tests\TestCase return $foo; }' ], + 'isNotTraversable' => [ + ' $collection + * @psalm-return array + */ + function order(iterable $collection): array { + if ($collection instanceof \Traversable) { + $collection = iterator_to_array($collection, false); + } + + return $collection; + }' + ], ]; }