From c1aeb64569c39ae4deb94163b4481b44959aa70c Mon Sep 17 00:00:00 2001 From: Robert Meijers Date: Fri, 5 Apr 2024 18:53:46 +0200 Subject: [PATCH] Do not generalize big array when combined with empty array Fixes phpstan/phpstan#10834 --- src/Type/TypeCombinator.php | 12 +++++++++-- .../Analyser/NodeScopeResolverTest.php | 1 + tests/PHPStan/Analyser/data/bug-10834.php | 21 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/PHPStan/Analyser/data/bug-10834.php diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 86619e5e94..b4c52cd4cf 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -664,12 +664,19 @@ private static function processArrayTypes(array $arrayTypes): array $valueTypesForGeneralArray = []; $generalArrayOccurred = false; $constantKeyTypesNumbered = []; + $filledArrays = 0; + $overflowed = false; /** @var int|float $nextConstantKeyTypeIndex */ $nextConstantKeyTypeIndex = 1; foreach ($arrayTypes as $arrayType) { - if ($generalArrayOccurred || !$arrayType->isConstantArray()->yes()) { + $isConstantArray = $arrayType->isConstantArray()->yes(); + if (!$isConstantArray || !$arrayType->isIterableAtLeastOnce()->no()) { + $filledArrays++; + } + + if ($generalArrayOccurred || !$isConstantArray) { foreach ($arrayType->getArrays() as $type) { $keyTypesForGeneralArray[] = $type->getIterableKeyType(); $valueTypesForGeneralArray[] = $type->getItemType(); @@ -693,13 +700,14 @@ private static function processArrayTypes(array $arrayTypes): array $nextConstantKeyTypeIndex *= 2; if (!is_int($nextConstantKeyTypeIndex)) { $generalArrayOccurred = true; + $overflowed = true; continue 2; } } } } - if ($generalArrayOccurred) { + if ($generalArrayOccurred && (!$overflowed || $filledArrays > 1)) { $scopes = []; $useTemplateArray = true; foreach ($arrayTypes as $arrayType) { diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 515a3d80a5..a41cdd1ffe 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -1461,6 +1461,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10468.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6613.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10187.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10834.php'); } /** diff --git a/tests/PHPStan/Analyser/data/bug-10834.php b/tests/PHPStan/Analyser/data/bug-10834.php new file mode 100644 index 0000000000..69efb18635 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-10834.php @@ -0,0 +1,21 @@ +