Skip to content

Commit 7e2be85

Browse files
staabmondrejmirtes
authored andcommitted
NodeScopeResolver: duplicate only if we actually change the storage
1 parent 901b335 commit 7e2be85

1 file changed

Lines changed: 18 additions & 15 deletions

File tree

src/Analyser/NodeScopeResolver.php

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,27 +1633,30 @@ private function processStmtNode(
16331633
}
16341634

16351635
$originalStorage = $storage;
1636-
$storage = $originalStorage->duplicate();
16371636

16381637
$bodyScope = $initScope;
16391638
$isIterableAtLeastOnce = TrinaryLogic::createYes();
16401639
$lastCondExpr = array_last($stmt->cond) ?? null;
1641-
foreach ($stmt->cond as $condExpr) {
1642-
$condResult = $this->processExprNode($stmt, $condExpr, $bodyScope, $storage, new NoopNodeCallback(), ExpressionContext::createDeep());
1643-
$initScope = $condResult->getScope();
1644-
$condResultScope = $condResult->getScope();
1640+
if (count($stmt->cond) > 0) {
1641+
$storage = $originalStorage->duplicate();
16451642

1646-
// only the last condition expression is relevant whether the loop continues
1647-
// see https://www.php.net/manual/en/control-structures.for.php
1648-
if ($condExpr === $lastCondExpr) {
1649-
$condTruthiness = ($this->treatPhpDocTypesAsCertain ? $condResultScope->getType($condExpr) : $condResultScope->getNativeType($condExpr))->toBoolean();
1650-
$isIterableAtLeastOnce = $isIterableAtLeastOnce->and($condTruthiness->isTrue());
1651-
}
1643+
foreach ($stmt->cond as $condExpr) {
1644+
$condResult = $this->processExprNode($stmt, $condExpr, $bodyScope, $storage, new NoopNodeCallback(), ExpressionContext::createDeep());
1645+
$initScope = $condResult->getScope();
1646+
$condResultScope = $condResult->getScope();
16521647

1653-
$hasYield = $hasYield || $condResult->hasYield();
1654-
$throwPoints = array_merge($throwPoints, $condResult->getThrowPoints());
1655-
$impurePoints = array_merge($impurePoints, $condResult->getImpurePoints());
1656-
$bodyScope = $condResult->getTruthyScope();
1648+
// only the last condition expression is relevant whether the loop continues
1649+
// see https://www.php.net/manual/en/control-structures.for.php
1650+
if ($condExpr === $lastCondExpr) {
1651+
$condTruthiness = ($this->treatPhpDocTypesAsCertain ? $condResultScope->getType($condExpr) : $condResultScope->getNativeType($condExpr))->toBoolean();
1652+
$isIterableAtLeastOnce = $isIterableAtLeastOnce->and($condTruthiness->isTrue());
1653+
}
1654+
1655+
$hasYield = $hasYield || $condResult->hasYield();
1656+
$throwPoints = array_merge($throwPoints, $condResult->getThrowPoints());
1657+
$impurePoints = array_merge($impurePoints, $condResult->getImpurePoints());
1658+
$bodyScope = $condResult->getTruthyScope();
1659+
}
16571660
}
16581661

16591662
if ($context->isTopLevel()) {

0 commit comments

Comments
 (0)