From 119765515c58dbd5053fcb702de25fdf4711ef70 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Mon, 20 Jun 2022 09:26:05 +0200 Subject: [PATCH] Fix TypeCombinator::union() for intersection of array and template type --- src/Type/TypeCombinator.php | 3 ++ .../Rules/Methods/ReturnTypeRuleTest.php | 6 +++ tests/PHPStan/Rules/Methods/data/bug-4117.php | 47 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/PHPStan/Rules/Methods/data/bug-4117.php diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 9ba14f5425..ce77dda2ee 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -161,6 +161,9 @@ public static function union(Type ...$types): Type $intermediateArrayType = null; $intermediateAccessoryTypes = []; foreach ($types[$i]->getTypes() as $innerType) { + if ($innerType instanceof TemplateType) { + continue 2; + } if ($innerType instanceof ArrayType) { $intermediateArrayType = $innerType; continue; diff --git a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php index b3229ae4ee..d7b28fb919 100644 --- a/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php @@ -706,4 +706,10 @@ public function testBug7460(): void $this->analyse([__DIR__ . '/data/bug-7460.php'], []); } + public function testBug4117(): void + { + $this->checkExplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-4117.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-4117.php b/tests/PHPStan/Rules/Methods/data/bug-4117.php new file mode 100644 index 0000000000..7874fb460c --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-4117.php @@ -0,0 +1,47 @@ + + */ +class GenericList implements IteratorAggregate +{ + /** @var array */ + protected $items = []; + + /** + * @return ArrayIterator + */ + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->items); + } + + /** + * @return ?T + */ + public function broken(int $key) + { + $item = $this->items[$key] ?? null; + if ($item) { + } + + return $item; + } + + /** + * @return ?T + */ + public function works(int $key) + { + $item = $this->items[$key] ?? null; + + return $item; + } +}