diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index f1dfb1f0da..ca4d27ff3e 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3431,18 +3431,70 @@ private function intersectConditionalExpressions(array $otherConditionalExpressi } $otherHolders = $otherConditionalExpressions[$exprString]; + $allKeysMatch = true; foreach (array_keys($holders) as $key) { if (!array_key_exists($key, $otherHolders)) { - continue 2; + $allKeysMatch = false; + break; } } - $newConditionalExpressions[$exprString] = $holders; + if ($allKeysMatch) { + $newConditionalExpressions[$exprString] = $holders; + continue; + } + + // Keys don't match exactly - try matching by condition expressions + // and merge result type holders + $mergedHolders = []; + foreach ($holders as $holder) { + $conditionHolders = $holder->getConditionExpressionTypeHolders(); + foreach ($otherHolders as $otherHolder) { + if ($this->conditionExpressionHoldersMatch($conditionHolders, $otherHolder->getConditionExpressionTypeHolders())) { + $mergedTypeHolder = $holder->getTypeHolder()->and($otherHolder->getTypeHolder()); + $mergedHolder = new ConditionalExpressionHolder( + $conditionHolders, + $mergedTypeHolder, + ); + $mergedHolders[$mergedHolder->getKey()] = $mergedHolder; + break; + } + } + } + + if (count($mergedHolders) <= 0) { + continue; + } + + $newConditionalExpressions[$exprString] = $mergedHolders; } return $newConditionalExpressions; } + /** + * @param array $a + * @param array $b + */ + private function conditionExpressionHoldersMatch(array $a, array $b): bool + { + if (count($a) !== count($b)) { + return false; + } + + foreach ($a as $key => $holder) { + if (!array_key_exists($key, $b)) { + return false; + } + + if (!$holder->equals($b[$key])) { + return false; + } + } + + return true; + } + /** * @param array $newConditionalExpressions * @param array $existingConditionalExpressions diff --git a/tests/PHPStan/Rules/Variables/data/bug-6830.php b/tests/PHPStan/Rules/Variables/data/bug-6830.php index 1a4e5a4490..7306eb9a6f 100644 --- a/tests/PHPStan/Rules/Variables/data/bug-6830.php +++ b/tests/PHPStan/Rules/Variables/data/bug-6830.php @@ -16,3 +16,18 @@ function test(array $bools): void } } } + +function test2(bool $do): void +{ + if ($do) { + $x = 9999; + } + + foreach ([1, 2, 3] as $whatever) { + if ($do) { + if ($x) { + $x = 123; + } + } + } +}