diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 0b0fd5ccda..66d0921854 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -220,6 +220,32 @@ public function getValueTypes(): array return $this->valueTypes; } + public function getFirstValueType(): Type + { + $valueTypes = []; + for ($i = 0, $keyTypesCount = count($this->keyTypes); $i < $keyTypesCount; $i++) { + $valueTypes[] = $this->valueTypes[$i]; + if (!$this->isOptionalKey($i)) { + break; + } + } + + return TypeCombinator::union(...$valueTypes); + } + + public function getLastValueType(): Type + { + $valueTypes = []; + for ($i = count($this->keyTypes) - 1; $i >= 0; $i--) { + $valueTypes[] = $this->valueTypes[$i]; + if (!$this->isOptionalKey($i)) { + break; + } + } + + return TypeCombinator::union(...$valueTypes); + } + public function isOptionalKey(int $i): bool { return in_array($i, $this->optionalKeys, true); diff --git a/src/Type/Php/ArrayPopFunctionReturnTypeExtension.php b/src/Type/Php/ArrayPopFunctionReturnTypeExtension.php index 75c42f8b7b..8634357820 100644 --- a/src/Type/Php/ArrayPopFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayPopFunctionReturnTypeExtension.php @@ -33,7 +33,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, return new NullType(); } - $constantArrays = TypeUtils::getConstantArrays($argType); + $constantArrays = TypeUtils::getOldConstantArrays($argType); if (count($constantArrays) > 0) { $valueTypes = []; foreach ($constantArrays as $constantArray) { @@ -42,8 +42,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, $valueTypes[] = new NullType(); continue; } - - $valueTypes[] = $constantArray->getOffsetValueType($arrayKeyTypes[count($arrayKeyTypes) - 1]); + $valueTypes[] = $constantArray->getLastValueType(); } return TypeCombinator::union(...$valueTypes); diff --git a/src/Type/Php/ArrayShiftFunctionReturnTypeExtension.php b/src/Type/Php/ArrayShiftFunctionReturnTypeExtension.php index b38a2889c5..0941b49405 100644 --- a/src/Type/Php/ArrayShiftFunctionReturnTypeExtension.php +++ b/src/Type/Php/ArrayShiftFunctionReturnTypeExtension.php @@ -33,7 +33,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, return new NullType(); } - $constantArrays = TypeUtils::getConstantArrays($argType); + $constantArrays = TypeUtils::getOldConstantArrays($argType); if (count($constantArrays) > 0) { $valueTypes = []; foreach ($constantArrays as $constantArray) { @@ -43,7 +43,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, continue; } - $valueTypes[] = $constantArray->getOffsetValueType($arrayKeyTypes[0]); + $valueTypes[] = $constantArray->getFirstValueType(); } return TypeCombinator::union(...$valueTypes); diff --git a/tests/PHPStan/Analyser/data/array-pop.php b/tests/PHPStan/Analyser/data/array-pop.php index 96663ce30b..bed663977d 100644 --- a/tests/PHPStan/Analyser/data/array-pop.php +++ b/tests/PHPStan/Analyser/data/array-pop.php @@ -38,11 +38,11 @@ public function constantArrays(array $arr): void public function constantArraysWithOptionalKeys(array $arr): void { /** @var array{a?: 0, b: 1, c: 2} $arr */ - assertType('0|2', array_pop($arr)); // should be 2 + assertType('2', array_pop($arr)); assertType('array{a?: 0, b: 1}', $arr); /** @var array{a: 0, b?: 1, c: 2} $arr */ - assertType('1|2', array_pop($arr)); // should be 2 + assertType('2', array_pop($arr)); assertType('array{a: 0, b?: 1}', $arr); /** @var array{a: 0, b: 1, c?: 2} $arr */ diff --git a/tests/PHPStan/Analyser/data/array-shift.php b/tests/PHPStan/Analyser/data/array-shift.php index 16e66003a9..8f6cc093a2 100644 --- a/tests/PHPStan/Analyser/data/array-shift.php +++ b/tests/PHPStan/Analyser/data/array-shift.php @@ -38,7 +38,7 @@ public function constantArrays(array $arr): void public function constantArraysWithOptionalKeys(array $arr): void { /** @var array{a?: 0, b: 1, c: 2} $arr */ - assertType('1', array_shift($arr)); // should be 0|1 + assertType('0|1', array_shift($arr)); assertType('array{b?: 1, c: 2}', $arr); /** @var array{a: 0, b?: 1, c: 2} $arr */