|
182 | 182 | use PHPStan\Type\Generic\TemplateTypeMap; |
183 | 183 | use PHPStan\Type\Generic\TemplateTypeVariance; |
184 | 184 | use PHPStan\Type\Generic\TemplateTypeVarianceMap; |
| 185 | +use PHPStan\Type\IntegerRangeType; |
185 | 186 | use PHPStan\Type\IntegerType; |
186 | 187 | use PHPStan\Type\IntersectionType; |
187 | 188 | use PHPStan\Type\MixedType; |
@@ -1631,7 +1632,7 @@ private function processStmtNode( |
1631 | 1632 | if ($lastCondExpr !== null) { |
1632 | 1633 | $alwaysIterates = $alwaysIterates->and($bodyScope->getType($lastCondExpr)->toBoolean()->isTrue()); |
1633 | 1634 | $bodyScope = $this->processExprNode($stmt, $lastCondExpr, $bodyScope, $nodeCallback, ExpressionContext::createDeep())->getTruthyScope(); |
1634 | | - $bodyScope = $this->inferForLoopExpressions($stmt, $lastCondExpr, $bodyScope); |
| 1635 | + $bodyScope = $this->inferForLoopExpressions($stmt, $lastCondExpr, $bodyScope, $initScope); |
1635 | 1636 | } |
1636 | 1637 |
|
1637 | 1638 | $finalScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, $nodeCallback, $context)->filterOutLoopExitPoints(); |
@@ -7308,17 +7309,22 @@ private function getFilteringExprForMatchArm(Expr\Match_ $expr, array $condition |
7308 | 7309 | ); |
7309 | 7310 | } |
7310 | 7311 |
|
7311 | | - private function inferForLoopExpressions(For_ $stmt, Expr $lastCondExpr, MutatingScope $bodyScope): MutatingScope |
| 7312 | + private function inferForLoopExpressions( |
| 7313 | + For_ $stmt, |
| 7314 | + Expr $lastCondExpr, |
| 7315 | + MutatingScope $bodyScope, |
| 7316 | + MutatingScope $initScope, |
| 7317 | + ): MutatingScope |
7312 | 7318 | { |
7313 | 7319 | // infer $items[$i] type from for ($i = 0; $i < count($items); $i++) {...} |
7314 | 7320 |
|
| 7321 | + $positiveInt = IntegerRangeType::fromInterval(0, null); |
7315 | 7322 | if ( |
7316 | 7323 | // $i = 0 |
7317 | 7324 | count($stmt->init) === 1 |
7318 | 7325 | && $stmt->init[0] instanceof Assign |
7319 | 7326 | && $stmt->init[0]->var instanceof Variable |
7320 | | - && $stmt->init[0]->expr instanceof Node\Scalar\Int_ |
7321 | | - && $stmt->init[0]->expr->value === 0 |
| 7327 | + && $positiveInt->isSuperTypeOf($initScope->getType($stmt->init[0]->expr))->yes() |
7322 | 7328 | // $i++ or ++$i |
7323 | 7329 | && count($stmt->loop) === 1 |
7324 | 7330 | && ($stmt->loop[0] instanceof Expr\PreInc || $stmt->loop[0] instanceof Expr\PostInc) |
|
0 commit comments