Skip to content

Commit 66ffa81

Browse files
phpstan-botclaude
andcommitted
Fix IntegerRangeType count narrowing for falsey context with unbounded max
When the range has no upper bound (e.g. int<1, max>), the falsey context should not narrow using the min value, as this incorrectly eliminates arrays that could satisfy the condition for some (but not all) values in the range. Only set sizeType when the context is truthy and min is available, or when falsey and max is available. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 638c010 commit 66ffa81

File tree

2 files changed

+9
-8
lines changed

2 files changed

+9
-8
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ public function specifyTypesInCondition(
280280
) {
281281
$argType = $scope->getType($expr->right->getArgs()[0]->value);
282282

283+
$sizeType = null;
283284
if ($leftType instanceof ConstantIntegerType) {
284285
if ($orEqual) {
285286
$sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo($leftType->getValue());
@@ -293,22 +294,22 @@ public function specifyTypesInCondition(
293294
} else {
294295
$sizeType = IntegerRangeType::createAllGreaterThan($leftType->getMax());
295296
}
296-
} elseif ($leftType->getMin() !== null) {
297+
} elseif ($context->truthy() && $leftType->getMin() !== null) {
297298
if ($orEqual) {
298299
$sizeType = IntegerRangeType::createAllGreaterThanOrEqualTo($leftType->getMin());
299300
} else {
300301
$sizeType = IntegerRangeType::createAllGreaterThan($leftType->getMin());
301302
}
302-
} else {
303-
$sizeType = $leftType->shift($offset);
304303
}
305304
} else {
306305
$sizeType = $leftType;
307306
}
308307

309-
$specifiedTypes = $this->specifyTypesForCountFuncCall($expr->right, $argType, $sizeType, $context, $scope, $expr);
310-
if ($specifiedTypes !== null) {
311-
$result = $result->unionWith($specifiedTypes);
308+
if ($sizeType !== null) {
309+
$specifiedTypes = $this->specifyTypesForCountFuncCall($expr->right, $argType, $sizeType, $context, $scope, $expr);
310+
if ($specifiedTypes !== null) {
311+
$result = $result->unionWith($specifiedTypes);
312+
}
312313
}
313314

314315
if (

tests/PHPStan/Analyser/nsrt/bug-4700.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ function(array $array, int $count): void {
2121
assertType('int<1, 5>', count($a));
2222
assertType('list{0: mixed~null, 1?: mixed~null, 2?: mixed~null, 3?: mixed~null, 4?: mixed~null}', $a);
2323
} else {
24-
assertType('0', count($a));
25-
assertType('array{}', $a);
24+
assertType('int<0, 5>', count($a));
25+
assertType('array{}|list{0: mixed~null, 1?: mixed~null, 2?: mixed~null, 3?: mixed~null, 4?: mixed~null}', $a);
2626
}
2727
};
2828

0 commit comments

Comments
 (0)