diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 7aff6c5783..2803719b65 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -1845,7 +1845,7 @@ private function processStmtNode( } if ((!$hasDefaultCase && !$exhaustive) || $finalScope === null) { - $finalScope = $scope->mergeWith($finalScope); + $finalScope = $scopeForBranches->mergeWith($finalScope); } return new InternalStatementResult($finalScope, $hasYield, $alwaysTerminating, $exitPointsForOuterLoop, $throwPoints, $impurePoints); diff --git a/tests/PHPStan/Analyser/nsrt/bug-13211.php b/tests/PHPStan/Analyser/nsrt/bug-13211.php new file mode 100644 index 0000000000..0c2dd94367 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-13211.php @@ -0,0 +1,115 @@ + 5 ? new Foo() : null; + + switch (true) { + case $a === null: + exit; + } + + assertType('Bug13211\Foo', $a); +} + +function switchTrueWithReturnNarrows(): void +{ + $a = random_int(1, 10) > 5 ? new Foo() : null; + + switch (true) { + case $a === null: + return; + } + + assertType('Bug13211\Foo', $a); +} + +function switchTrueWithThrowNarrows(): void +{ + $a = random_int(1, 10) > 5 ? new Foo() : null; + + switch (true) { + case $a === null: + throw new \Exception(); + } + + assertType('Bug13211\Foo', $a); +} + +function switchTrueMultipleCases(): void +{ + /** @var int|string|null $a */ + $a = null; + + switch (true) { + case $a === null: + exit; + case is_string($a): + exit; + } + + assertType('int', $a); +} + +function switchTrueWithInstanceof(): void +{ + /** @var Foo|int|null $a */ + $a = null; + + switch (true) { + case $a instanceof Foo: + exit; + } + + assertType('int|null', $a); +} + +function switchTrueWithBreakDoesNotNarrow(): void +{ + $a = random_int(1, 10) > 5 ? new Foo() : null; + + switch (true) { + case $a === null: + break; + } + + assertType('Bug13211\Foo|null', $a); +} + +function switchTrueWithDefaultCase(): void +{ + $a = random_int(1, 10) > 5 ? new Foo() : null; + + switch (true) { + case $a === null: + exit; + default: + break; + } + + assertType('Bug13211\Foo', $a); +} + +function regularSwitchStillWorks(): void +{ + /** @var 1|2|3 $a */ + $a = 1; + + switch ($a) { + case 1: + exit; + } + + assertType('2|3', $a); +}