Skip to content

Commit 92fe388

Browse files
phpstan-botclaude
andcommitted
Apply symmetric fix for integer range generalization in gotGreater && gotSmaller case
Instead of widening to plain int when both bounds expand, compute the actual combined min/max from both iterations using IntegerRangeType::fromInterval(). This mirrors the fix already applied for constant integers at line 4114. Added test cases (Test4, Test5) exercising the integer range path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f8275b7 commit 92fe388

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

src/Analyser/MutatingScope.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4204,7 +4204,19 @@ 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+
$rangeMin = $range->getMin();
4211+
$rangeMax = $range->getMax();
4212+
if ($newMin !== null && ($rangeMin === null || $rangeMin < $newMin)) {
4213+
$newMin = $rangeMin;
4214+
}
4215+
if ($newMax !== null && ($rangeMax === null || $rangeMax > $newMax)) {
4216+
$newMax = $rangeMax;
4217+
}
4218+
}
4219+
$resultTypes[] = IntegerRangeType::fromInterval($newMin, $newMax);
42084220
} elseif ($gotGreater) {
42094221
$resultTypes[] = IntegerRangeType::fromInterval($min, null);
42104222
} elseif ($gotSmaller) {

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,46 @@ public function iterateRowColumnIndicesDecrementing(int $rows, int $columns, int
7070
}
7171
}
7272

73+
class Test4
74+
{
75+
/**
76+
* @param int<0, 10> $index
77+
*/
78+
public function integerRangeGeneralization(int $rows, int $index): void
79+
{
80+
if ($rows < 1) return;
81+
82+
for ($i = 0; $i < $rows; $i++) {
83+
assertType('int<-3, 13>', $index);
84+
if ($index > 5) {
85+
$index++;
86+
} else {
87+
$index--;
88+
}
89+
}
90+
}
91+
}
92+
93+
class Test5
94+
{
95+
/**
96+
* @param int<5, 15> $index
97+
*/
98+
public function integerRangeGeneralizationBothDirections(int $rows, int $index): void
99+
{
100+
if ($rows < 1) return;
101+
102+
for ($i = 0; $i < $rows; $i++) {
103+
assertType('int<-10, max>', $index);
104+
if ($index > 10) {
105+
$index++;
106+
} else {
107+
$index = -$index;
108+
}
109+
}
110+
}
111+
}
112+
73113
class Bug12163
74114
{
75115
/**

0 commit comments

Comments
 (0)