Skip to content

Commit 4457c55

Browse files
staabmphpstan-bot
authored andcommitted
Fix incorrect dependent type inference after repeated boolean checks
- Fixed conditional expression resolution in filterBySpecifiedTypes to intersect types instead of overwriting when multiple conditional expressions fire for the same target - When two conditionals with the same guard produced different types (one more specific than the other), the less specific type could overwrite specifiedExpressions, causing cascading wrong matches that led to variables being incorrectly narrowed to *NEVER* - New regression test in tests/PHPStan/Analyser/nsrt/bug-14211.php Closes phpstan/phpstan#14211
1 parent 0b8e988 commit 4457c55

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

src/Analyser/MutatingScope.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3833,7 +3833,15 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
38333833
}
38343834

38353835
$conditions[$conditionalExprString][] = $conditionalExpression;
3836-
$specifiedExpressions[$conditionalExprString] = $conditionalExpression->getTypeHolder();
3836+
$newTypeHolder = $conditionalExpression->getTypeHolder();
3837+
if (array_key_exists($conditionalExprString, $specifiedExpressions) && $specifiedExpressions[$conditionalExprString]->getCertainty()->yes() && $newTypeHolder->getCertainty()->yes()) {
3838+
$specifiedExpressions[$conditionalExprString] = ExpressionTypeHolder::createYes(
3839+
$newTypeHolder->getExpr(),
3840+
TypeCombinator::intersect($specifiedExpressions[$conditionalExprString]->getType(), $newTypeHolder->getType()),
3841+
);
3842+
} else {
3843+
$specifiedExpressions[$conditionalExprString] = $newTypeHolder;
3844+
}
38373845
}
38383846
}
38393847
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Bug14211;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/** @param array<mixed> $data */
8+
function doSomething(array $data): bool {
9+
10+
if (!isset($data['x']))
11+
return false;
12+
13+
$m = isset($data['y']);
14+
15+
if ($m) {
16+
assertType('true', $m);
17+
}
18+
assertType('bool', $m);
19+
20+
if ($m) {
21+
assertType('true', $m);
22+
}
23+
24+
return true;
25+
}

0 commit comments

Comments
 (0)