Skip to content

Commit daf5d79

Browse files
phpstan-botclaude
andcommitted
Apply symmetric fix for integer range generalization in gotGreater && gotSmaller case
Instead of immediately widening to IntegerType (plain int) when integer ranges grow in both directions, compute the actual observed min/max bounds from both iterations using IntegerRangeType::fromInterval(). This mirrors the fix already applied for constant integers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4d9968f commit daf5d79

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/Analyser/MutatingScope.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4204,7 +4204,37 @@ private function generalizeType(Type $a, Type $b, int $depth): Type
42044204
}
42054205

42064206
if ($gotGreater && $gotSmaller) {
4207-
$resultTypes[] = new IntegerType();
4207+
$newMin = $min;
4208+
$newMax = $max;
4209+
foreach ($integerRanges['b'] as $range) {
4210+
if ($range->getMin() === null) {
4211+
$rangeMin = PHP_INT_MIN;
4212+
} else {
4213+
$rangeMin = $range->getMin();
4214+
}
4215+
if ($range->getMax() === null) {
4216+
$rangeMax = PHP_INT_MAX;
4217+
} else {
4218+
$rangeMax = $range->getMax();
4219+
}
4220+
4221+
if ($rangeMin < $newMin) {
4222+
$newMin = $rangeMin;
4223+
}
4224+
if ($rangeMax <= $newMax) {
4225+
continue;
4226+
}
4227+
4228+
$newMax = $rangeMax;
4229+
}
4230+
4231+
if ($newMin === PHP_INT_MIN) {
4232+
$newMin = null;
4233+
}
4234+
if ($newMax === PHP_INT_MAX) {
4235+
$newMax = null;
4236+
}
4237+
$resultTypes[] = IntegerRangeType::fromInterval($newMin, $newMax);
42084238
} elseif ($gotGreater) {
42094239
$resultTypes[] = IntegerRangeType::fromInterval($min, null);
42104240
} elseif ($gotSmaller) {

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,22 @@ public function iterateRowColumnIndices(int $rows, int $columns): void
100100
}
101101
}
102102
}
103+
104+
class Test4
105+
{
106+
/**
107+
* @param int<5, 10> $index
108+
*/
109+
public function integerRangeGrowsBothDirections(int $size, int $index): void
110+
{
111+
for ($i = 0; $i < $size; $i++) {
112+
assertType('int<3, 12>', $index);
113+
if ($index > 7) {
114+
$index = rand(3, 4);
115+
} else {
116+
$index = $index + 5;
117+
}
118+
}
119+
assertType('int<3, 12>', $index);
120+
}
121+
}

0 commit comments

Comments
 (0)