Skip to content

Commit f555f50

Browse files
committed
Fix null coalesce type inference for correlated int range variables
- Fixed getCoalesceType() in MutatingScope to avoid over-narrowing the right side of ?? when conditional expressions from scope merging make correlated variables all null together - The fix uses the narrowed scope only when it successfully removes null from the right type (useful for `if ($a || $b) { $a ?? $b }` patterns), and falls back to the unfiltered type otherwise - New regression test in tests/PHPStan/Analyser/nsrt/bug-14213.php Closes phpstan/phpstan#14213
1 parent 1340aeb commit f555f50

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

src/Analyser/MutatingScope.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6536,7 +6536,13 @@ private function getCoalesceType(BinaryOp\Coalesce $node): Type
65366536
return TypeCombinator::removeNull($this->filterByTruthyValue($issetLeftExpr)->getType($node->left));
65376537
}
65386538

6539-
$rightType = $this->filterByFalseyValue($issetLeftExpr)->getType($node->right);
6539+
$unfilteredRightType = $this->getType($node->right);
6540+
if (!$unfilteredRightType->isNull()->no()) {
6541+
$narrowedRightType = $this->filterByFalseyValue($issetLeftExpr)->getType($node->right);
6542+
$rightType = $narrowedRightType->isNull()->no() ? $narrowedRightType : $unfilteredRightType;
6543+
} else {
6544+
$rightType = $unfilteredRightType;
6545+
}
65406546

65416547
if ($result === null) {
65426548
return TypeCombinator::union(
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug14213;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld
8+
{
9+
public static function coalesce_int_range(): void
10+
{
11+
$x0 = $x1 = $x2 = null;
12+
13+
if (rand(0, 1)) {
14+
$x0 = rand(0, 1);
15+
$x1 = rand(2, 3);
16+
$x2 = rand(4, 5);
17+
}
18+
19+
$x = (
20+
$x0 ??
21+
$x1 ??
22+
$x2
23+
);
24+
25+
assertType('int<0, 5>|null', $x);
26+
}
27+
}

0 commit comments

Comments
 (0)