Skip to content

Commit 7c587ab

Browse files
committed
Only use last for condition to filter scope
1 parent 11e0ab6 commit 7c587ab

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed

src/Analyser/NodeScopeResolver.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,13 +1314,18 @@ private function processStmtNode(
13141314

13151315
$bodyScope = $initScope;
13161316
$isIterableAtLeastOnce = TrinaryLogic::createYes();
1317+
$lastCondExpr = $stmt->cond[count($stmt->cond) - 1] ?? null;
13171318
foreach ($stmt->cond as $condExpr) {
13181319
$condResult = $this->processExprNode($stmt, $condExpr, $bodyScope, static function (): void {
13191320
}, ExpressionContext::createDeep());
13201321
$initScope = $condResult->getScope();
13211322
$condResultScope = $condResult->getScope();
1322-
$condTruthiness = ($this->treatPhpDocTypesAsCertain ? $condResultScope->getType($condExpr) : $condResultScope->getNativeType($condExpr))->toBoolean();
1323-
$isIterableAtLeastOnce = $isIterableAtLeastOnce->and($condTruthiness->isTrue());
1323+
1324+
if ($condExpr === $lastCondExpr) {
1325+
$condTruthiness = ($this->treatPhpDocTypesAsCertain ? $condResultScope->getType($condExpr) : $condResultScope->getNativeType($condExpr))->toBoolean();
1326+
$isIterableAtLeastOnce = $isIterableAtLeastOnce->and($condTruthiness->isTrue());
1327+
}
1328+
13241329
$hasYield = $hasYield || $condResult->hasYield();
13251330
$throwPoints = array_merge($throwPoints, $condResult->getThrowPoints());
13261331
$impurePoints = array_merge($impurePoints, $condResult->getImpurePoints());
@@ -1332,8 +1337,8 @@ private function processStmtNode(
13321337
do {
13331338
$prevScope = $bodyScope;
13341339
$bodyScope = $bodyScope->mergeWith($initScope);
1335-
foreach ($stmt->cond as $condExpr) {
1336-
$bodyScope = $this->processExprNode($stmt, $condExpr, $bodyScope, static function (): void {
1340+
if ($lastCondExpr !== null) {
1341+
$bodyScope = $this->processExprNode($stmt, $lastCondExpr, $bodyScope, static function (): void {
13371342
}, ExpressionContext::createDeep())->getTruthyScope();
13381343
}
13391344
$bodyScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, static function (): void {
@@ -1363,8 +1368,8 @@ private function processStmtNode(
13631368
}
13641369

13651370
$bodyScope = $bodyScope->mergeWith($initScope);
1366-
foreach ($stmt->cond as $condExpr) {
1367-
$bodyScope = $this->processExprNode($stmt, $condExpr, $bodyScope, $nodeCallback, ExpressionContext::createDeep())->getTruthyScope();
1371+
if ($lastCondExpr !== null) {
1372+
$bodyScope = $this->processExprNode($stmt, $lastCondExpr, $bodyScope, $nodeCallback, ExpressionContext::createDeep())->getTruthyScope();
13681373
}
13691374

13701375
$finalScopeResult = $this->processStmtNodes($stmt, $stmt->stmts, $bodyScope, $nodeCallback, $context)->filterOutLoopExitPoints();
@@ -1378,8 +1383,8 @@ private function processStmtNode(
13781383
$loopScope = $this->processExprNode($stmt, $loopExpr, $loopScope, $nodeCallback, ExpressionContext::createTopLevel())->getScope();
13791384
}
13801385
$finalScope = $finalScope->generalizeWith($loopScope);
1381-
foreach ($stmt->cond as $condExpr) {
1382-
$finalScope = $finalScope->filterByFalseyValue($condExpr);
1386+
if ($lastCondExpr !== null) {
1387+
$finalScope = $finalScope->filterByFalseyValue($lastCondExpr);
13831388
}
13841389

13851390
foreach ($finalScopeResult->getExitPointsByType(Break_::class) as $breakExitPoint) {

tests/PHPStan/Analyser/nsrt/for-loop-i-type.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,12 @@ public static function groupCapacities(array $startTimes): array
9494

9595
return $capacities;
9696
}
97+
98+
public function lastConditionResult(): void
99+
{
100+
for ($i = 0, $j = 5; $i < 10, $j > 0; $i++, $j--) {
101+
assertType('int<0, max>', $i); // int<0,4> would be more precise, see https://github.com/phpstan/phpstan/issues/11872
102+
assertType('int<1, 5>', $j);
103+
}
104+
}
97105
}

0 commit comments

Comments
 (0)