diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index a15d08bac9..c987a27457 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -1774,7 +1774,7 @@ private function resolveType(Expr $node): Type } } else { $arrayBuilder->degradeToGeneralArray(); - $arrayBuilder->setOffsetValueType(new IntegerType(), $valueType->getIterableValueType()); + $arrayBuilder->setOffsetValueType(new IntegerType(), $valueType->getIterableValueType(), !$valueType->isIterableAtLeastOnce()->yes() && !$valueType->getIterableValueType()->isIterableAtLeastOnce()->yes()); } } else { $arrayBuilder->setOffsetValueType( diff --git a/src/Type/Constant/ConstantArrayTypeBuilder.php b/src/Type/Constant/ConstantArrayTypeBuilder.php index aebd713e9e..04c93f3c73 100644 --- a/src/Type/Constant/ConstantArrayTypeBuilder.php +++ b/src/Type/Constant/ConstantArrayTypeBuilder.php @@ -105,6 +105,9 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt $this->keyTypes[] = TypeUtils::generalizeType($offsetType, GeneralizePrecision::moreSpecific()); $this->valueTypes[] = $valueType; + if ($optional) { + $this->optionalKeys[] = count($this->keyTypes) - 1; + } $this->degradeToGeneralArray = true; } diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index ffcc6d973d..68294b6ef3 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -533,6 +533,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5017.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5992.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6001.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5287.php'); if (PHP_VERSION_ID >= 70400) { yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5458.php'); diff --git a/tests/PHPStan/Analyser/data/bug-5287.php b/tests/PHPStan/Analyser/data/bug-5287.php new file mode 100644 index 0000000000..3bcb5eb4fb --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-5287.php @@ -0,0 +1,59 @@ + $arr + */ +function foo(array $arr): void +{ + $arrSpread = [...$arr]; + assertType('array', $arrSpread); +} + +/** + * @param list $arr + */ +function foo2(array $arr): void +{ + $arrSpread = [...$arr]; + assertType('non-empty-array', $arrSpread); +} + +/** + * @param non-empty-list $arr + */ +function foo3(array $arr): void +{ + $arrSpread = [...$arr]; + assertType('non-empty-array', $arrSpread); +} + +/** + * @param non-empty-array $arr + */ +function foo3(array $arr): void +{ + $arrSpread = [...$arr]; + assertType('non-empty-array', $arrSpread); +} + +/** + * @param non-empty-array $arr + */ +function foo4(array $arr): void +{ + $arrSpread = [...$arr]; + assertType('non-empty-array', $arrSpread); +} + +/** + * @param array{foo: 17, bar: 19} $arr + */ +function bar(array $arr): void +{ + $arrSpread = [...$arr]; + assertType('array{17, 19}', $arrSpread); +}