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); }