From fe8aab80e72e5602da632a4e66909d08b94b9682 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Tue, 22 Jul 2025 14:00:09 +0200 Subject: [PATCH] Fix count inferences --- src/Analyser/TypeSpecifier.php | 4 +++- tests/PHPStan/Analyser/nsrt/bug-13111.php | 13 +++++++++++++ tests/PHPStan/Analyser/nsrt/list-count.php | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 tests/PHPStan/Analyser/nsrt/bug-13111.php diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 1ef2230e45..03feedfb96 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -1113,6 +1113,7 @@ private function specifyTypesForCountFuncCall( if ( $sizeType instanceof ConstantIntegerType && $sizeType->getValue() < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT + && $isList->yes() && $arrayType->getKeyType()->isSuperTypeOf(IntegerRangeType::fromInterval(0, $sizeType->getValue() - 1))->yes() ) { // turn optional offsets non-optional @@ -1129,6 +1130,7 @@ private function specifyTypesForCountFuncCall( $sizeType instanceof IntegerRangeType && $sizeType->getMin() !== null && $sizeType->getMin() < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT + && $isList->yes() && $arrayType->getKeyType()->isSuperTypeOf(IntegerRangeType::fromInterval(0, ($sizeType->getMax() ?? $sizeType->getMin()) - 1))->yes() ) { $builderData = []; @@ -1174,7 +1176,7 @@ private function specifyTypesForCountFuncCall( continue; } - $resultTypes[] = $arrayType; + $resultTypes[] = TypeCombinator::intersect($arrayType, new NonEmptyArrayType()); } return $this->create($countFuncCall->getArgs()[0]->value, TypeCombinator::union(...$resultTypes), $context, $scope)->setRootExpr($rootExpr); diff --git a/tests/PHPStan/Analyser/nsrt/bug-13111.php b/tests/PHPStan/Analyser/nsrt/bug-13111.php new file mode 100644 index 0000000000..0e51fac2ec --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-13111.php @@ -0,0 +1,13 @@ + 8]; } + +$b = foo(); +if (count($b) === 1) { + assertType('non-empty-array{0?: string, 1?: int}', $b); +} diff --git a/tests/PHPStan/Analyser/nsrt/list-count.php b/tests/PHPStan/Analyser/nsrt/list-count.php index b42f0ec8bd..f5b37b4410 100644 --- a/tests/PHPStan/Analyser/nsrt/list-count.php +++ b/tests/PHPStan/Analyser/nsrt/list-count.php @@ -407,7 +407,7 @@ protected function testOptionalKeysInUnionListWithIntRange($row, $listRow, $twoO protected function testOptionalKeysInUnionArrayWithIntRange($row, $twoOrThree): void { if (count($row) >= $twoOrThree) { - assertType('array{0: int, 1: string|null, 2?: int|null}', $row); + assertType('array{0: int, 1?: string|null, 2?: int|null, 3?: float|null}', $row); } else { assertType('array{0: int, 1?: string|null, 2?: int|null, 3?: float|null}|array{string}', $row); }