Skip to content

Commit 53b917a

Browse files
phpstan-botclaude
andcommitted
Fix conditional expression filtering in processAlwaysIterableForeachScopeWithoutPollute
The previous approach (using $finalScope->conditionalExpressions filtered to $this variables) lost valid conditional expressions that existed in $this but not in $finalScope, causing false positives like "Call to an undefined method PhpParser\Node::getReturnType()". The correct approach: start from $this->conditionalExpressions (pre-foreach) and remove only entries where a condition variable's type changed between $this and $finalScope, indicating it was reassigned in the foreach body and the conditional expression is stale. When a type change is detected, the entire conditional expression key is removed (not individual holders) to avoid partial/inconsistent state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8163acb commit 53b917a

File tree

1 file changed

+10
-12
lines changed

1 file changed

+10
-12
lines changed

src/Analyser/MutatingScope.php

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3870,24 +3870,22 @@ public function processAlwaysIterableForeachScopeWithoutPollute(self $finalScope
38703870
);
38713871
}
38723872

3873-
$conditionalExpressions = [];
3874-
foreach ($finalScope->conditionalExpressions as $conditionalExprString => $holders) {
3875-
if (!isset($this->expressionTypes[$conditionalExprString])) {
3876-
continue;
3877-
}
3878-
$filteredHolders = [];
3873+
$conditionalExpressions = $this->conditionalExpressions;
3874+
foreach ($this->conditionalExpressions as $conditionalExprString => $holders) {
38793875
foreach ($holders as $holder) {
3880-
foreach (array_keys($holder->getConditionExpressionTypeHolders()) as $holderExprString) {
3876+
foreach ($holder->getConditionExpressionTypeHolders() as $holderExprString => $condTypeHolder) {
3877+
if (!isset($finalScope->expressionTypes[$holderExprString])) {
3878+
continue 2;
3879+
}
38813880
if (!isset($this->expressionTypes[$holderExprString])) {
38823881
continue 2;
38833882
}
3883+
if (!$this->expressionTypes[$holderExprString]->getType()->equals($finalScope->expressionTypes[$holderExprString]->getType())) {
3884+
unset($conditionalExpressions[$conditionalExprString]);
3885+
continue 3;
3886+
}
38843887
}
3885-
$filteredHolders[] = $holder;
3886-
}
3887-
if ($filteredHolders === []) {
3888-
continue;
38893888
}
3890-
$conditionalExpressions[$conditionalExprString] = $filteredHolders;
38913889
}
38923890

38933891
return $this->scopeFactory->create(

0 commit comments

Comments
 (0)