Skip to content

Commit e23471b

Browse files
committed
errors on recursive count
1 parent 193a4f6 commit e23471b

3 files changed

Lines changed: 29 additions & 8 deletions

File tree

src/Analyser/TypeSpecifier.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ public function specifyTypesInCondition(
369369
$subtractedType = $scope->getType($expr->right->right);
370370
if (
371371
$countArgType->isList()->yes()
372+
&& $this->isNormalCountCall($expr->right->left, $countArgType, $scope)->yes()
372373
&& IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($subtractedType)->yes()
373374
) {
374375
$arrayArg = $expr->right->left->getArgs()[0]->value;
@@ -1239,6 +1240,16 @@ public function specifyTypesInCondition(
12391240
return (new SpecifiedTypes([], []))->setRootExpr($expr);
12401241
}
12411242

1243+
private function isNormalCountCall(FuncCall $countFuncCall, Type $typeToCount, Scope $scope): TrinaryLogic
1244+
{
1245+
if (count($countFuncCall->getArgs()) === 1) {
1246+
return TrinaryLogic::createYes();
1247+
}
1248+
1249+
$mode = $scope->getType($countFuncCall->getArgs()[1]->value);
1250+
return (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->result->or($typeToCount->getIterableValueType()->isArray()->negate());
1251+
}
1252+
12421253
private function specifyTypesForCountFuncCall(
12431254
FuncCall $countFuncCall,
12441255
Type $type,
@@ -1248,18 +1259,11 @@ private function specifyTypesForCountFuncCall(
12481259
Expr $rootExpr,
12491260
): ?SpecifiedTypes
12501261
{
1251-
if (count($countFuncCall->getArgs()) === 1) {
1252-
$isNormalCount = TrinaryLogic::createYes();
1253-
} else {
1254-
$mode = $scope->getType($countFuncCall->getArgs()[1]->value);
1255-
$isNormalCount = (new ConstantIntegerType(COUNT_NORMAL))->isSuperTypeOf($mode)->result->or($type->getIterableValueType()->isArray()->negate());
1256-
}
1257-
12581262
$isConstantArray = $type->isConstantArray();
12591263
$isList = $type->isList();
12601264
$oneOrMore = IntegerRangeType::fromInterval(1, null);
12611265
if (
1262-
!$isNormalCount->yes()
1266+
!$this->isNormalCountCall($countFuncCall, $type, $scope)->yes()
12631267
|| (!$isConstantArray->yes() && !$isList->yes())
12641268
|| !$oneOrMore->isSuperTypeOf($sizeType)->yes()
12651269
|| $sizeType->isSuperTypeOf($type->getArraySize())->yes()

tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,10 @@ public function testBug13770(): void
11981198
'Offset -5|int<0, max> might not exist on list<int>.',
11991199
190,
12001200
],
1201+
[
1202+
'Offset int<0, max> might not exist on list<mixed>.',
1203+
203,
1204+
],
12011205
]);
12021206
}
12031207

tests/PHPStan/Rules/Arrays/data/bug-13770.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,17 @@ public function errorsBecauseMaybeTooSmall(array $array, int $index): int
192192

193193
return 0;
194194
}
195+
196+
/**
197+
* @param list<mixed> $array
198+
* @param 0|positive-int $index
199+
*/
200+
public function errorsOnRecursiveCount(array $array, int $index): int
201+
{
202+
if ($index <= count($array, COUNT_RECURSIVE) - 5) {
203+
return $array[$index];
204+
}
205+
206+
return 0;
207+
}
195208
}

0 commit comments

Comments
 (0)