Bug report
When two if statements reuse the same left-hand condition $enum !== Case::X (with a 2-case enum), and the first if additionally narrows an object property via && $obj->prop === true, PHPStan incorrectly carries that property narrowing over to the second if. It then reports $obj->prop === false in the second if as always false.
This is a false positive: the first if can be skipped purely because the enum condition was false, in which case the property keeps its real (unknown) bool value. The second branch is therefore reachable.
The issue requires all of the following — removing any one of them makes the false positive disappear:
- a 2-case enum narrowed with
!== (using ===, an int, or a plain bool flag does not reproduce);
- the value being narrowed must be an object property (a local
bool variable does not reproduce);
- the same left-hand enum condition reused in both
if statements.
It reproduces without bleeding edge, and on both 2.2.2 (stable) and 2.2.x-dev.
Code snippet that reproduces the problem
https://phpstan.org/r/0852b450-c2e2-4b15-84e4-afa9e4ac1616
Expected output
No errors.
Actual output
Both errors are reported on the second if:
Result of && is always false. (booleanAnd.alwaysFalse)
Strict comparison using === between true and false will always evaluate to false. (identical.alwaysFalse)
Did PHPStan help you today? Did it make you happy in any way?
No response
Bug report
When two
ifstatements reuse the same left-hand condition$enum !== Case::X(with a 2-case enum), and the firstifadditionally narrows an object property via&& $obj->prop === true, PHPStan incorrectly carries that property narrowing over to the secondif. It then reports$obj->prop === falsein the secondifas always false.This is a false positive: the first
ifcan be skipped purely because the enum condition was false, in which case the property keeps its real (unknown)boolvalue. The second branch is therefore reachable.The issue requires all of the following — removing any one of them makes the false positive disappear:
!==(using===, anint, or a plainboolflag does not reproduce);boolvariable does not reproduce);ifstatements.It reproduces without bleeding edge, and on both 2.2.2 (stable) and 2.2.x-dev.
Code snippet that reproduces the problem
https://phpstan.org/r/0852b450-c2e2-4b15-84e4-afa9e4ac1616
Expected output
No errors.
Actual output
Both errors are reported on the second if:
Result of && is always false. (booleanAnd.alwaysFalse)
Strict comparison using === between true and false will always evaluate to false. (identical.alwaysFalse)
Did PHPStan help you today? Did it make you happy in any way?
No response