Skip to content

Commit c737a0d

Browse files
committed
Support narrowing a constant array to a list with count
1 parent c8833df commit c737a0d

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,10 +1061,11 @@ private function specifyTypesForCountFuncCall(
10611061
$isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->result->or($type->getIterableValueType()->isArray()->negate());
10621062
}
10631063

1064+
$isConstantArray = $type->isConstantArray();
10641065
$isList = $type->isList();
10651066
if (
10661067
!$isNormalCount->yes()
1067-
|| (!$type->isConstantArray()->yes() && !$isList->yes())
1068+
|| (!$isConstantArray->yes() && !$isList->yes())
10681069
|| $type->isIterableAtLeastOnce()->no() // array{} cannot be used for further narrowing
10691070
) {
10701071
return null;
@@ -1082,9 +1083,12 @@ private function specifyTypesForCountFuncCall(
10821083
}
10831084

10841085
if (
1085-
$isList->yes()
1086-
&& $sizeType instanceof ConstantIntegerType
1086+
$sizeType instanceof ConstantIntegerType
10871087
&& $sizeType->getValue() < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
1088+
&& (
1089+
$isList->yes()
1090+
|| $isConstantArray->yes() && $arrayType->getKeyType()->isSuperTypeOf(IntegerRangeType::fromInterval(0, $sizeType->getValue() - 1))->yes()
1091+
)
10881092
) {
10891093
// turn optional offsets non-optional
10901094
$valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty();

tests/PHPStan/Analyser/nsrt/count-type.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ public function doBaz(array $arr): void
8787
assertType('1|2', count($arr));
8888
}
8989

90+
public function constantArrayWhichCanBecomeList(string $h): void
91+
{
92+
preg_match('#^([a-z0-9-]+)\..+$#', $h, $matches);
93+
if (count($matches) !== 2) {
94+
return;
95+
}
96+
97+
assertType('array{string, non-empty-string}', $matches);
98+
}
99+
90100
}
91101

92102
/**

0 commit comments

Comments
 (0)