Skip to content

Commit c4e7c87

Browse files
github-actions[bot]phpstan-bot
authored andcommitted
Fix non-negative-int generalized to int in for loop
- Fixed overly aggressive type generalization in MutatingScope::generalizeType() for constant integers when values expand in both directions across loop iterations - Instead of widening to plain `int`, now computes actual observed bounds, allowing the next iteration to correctly determine stable vs growing bounds - New regression test in tests/PHPStan/Analyser/nsrt/bug-12163.php Closes phpstan/phpstan#12163
1 parent d32efcb commit c4e7c87

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

src/Analyser/MutatingScope.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4112,7 +4112,19 @@ private function generalizeType(Type $a, Type $b, int $depth): Type
41124112
}
41134113

41144114
if ($gotGreater && $gotSmaller) {
4115-
$resultTypes[] = new IntegerType();
4115+
$newMin = $min;
4116+
$newMax = $max;
4117+
foreach ($constantIntegers['b'] as $int) {
4118+
if ($int->getValue() < $newMin) {
4119+
$newMin = $int->getValue();
4120+
}
4121+
if ($int->getValue() <= $newMax) {
4122+
continue;
4123+
}
4124+
4125+
$newMax = $int->getValue();
4126+
}
4127+
$resultTypes[] = IntegerRangeType::fromInterval($newMin, $newMax);
41164128
} elseif ($gotGreater) {
41174129
$resultTypes[] = IntegerRangeType::fromInterval($min, null);
41184130
} elseif ($gotSmaller) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug12163;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Test
8+
{
9+
public function iterateRowColumnIndices(int $rows, int $columns): void
10+
{
11+
if ($rows < 1 || $columns < 1) return;
12+
$size = $rows * $columns;
13+
14+
$rowIndex = 0;
15+
$columnIndex = 0;
16+
for ($i = 0; $i < $size; $i++) {
17+
assertType('int<0, max>', $rowIndex);
18+
assertType('int<0, max>', $columnIndex);
19+
if ($columnIndex < $columns) {
20+
$columnIndex++;
21+
} else {
22+
$columnIndex = 0;
23+
$rowIndex++;
24+
}
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)