-
Notifications
You must be signed in to change notification settings - Fork 574
Fix phpstan/phpstan#14394: NAN ==/=== anything is always evaluated as false #5332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
869b3e4
b5638cc
f0cb81a
2302b10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -114,6 +114,7 @@ | |
| use function is_finite; | ||
| use function is_float; | ||
| use function is_int; | ||
| use function is_nan; | ||
| use function is_numeric; | ||
| use function is_string; | ||
| use function max; | ||
|
|
@@ -1944,6 +1945,10 @@ | |
| return new TypeResult(new ConstantBooleanType(false), []); | ||
| } | ||
|
|
||
| if ($this->containsNan($leftType) || $this->containsNan($rightType)) { | ||
| return new TypeResult(new ConstantBooleanType(false), []); | ||
| } | ||
|
|
||
| if ($leftType instanceof ConstantScalarType && $rightType instanceof ConstantScalarType) { | ||
| return new TypeResult(new ConstantBooleanType($leftType->getValue() === $rightType->getValue()), []); | ||
| } | ||
|
|
@@ -1972,6 +1977,10 @@ | |
| */ | ||
| public function resolveEqualType(Type $leftType, Type $rightType): TypeResult | ||
| { | ||
| if ($this->containsNan($leftType) || $this->containsNan($rightType)) { | ||
| return new TypeResult(new ConstantBooleanType(false), []); | ||
| } | ||
|
|
||
| if ( | ||
| ($leftType->isEnum()->yes() && $rightType->isTrue()->no()) | ||
| || ($rightType->isEnum()->yes() && $leftType->isTrue()->no()) | ||
|
|
@@ -2061,6 +2070,41 @@ | |
| return new TypeResult($resultType->toBoolean(), []); | ||
| } | ||
|
|
||
| private function containsNan(Type $type): bool | ||
| { | ||
| if ($type instanceof ConstantFloatType && is_nan($type->getValue())) { | ||
| return true; | ||
| } | ||
|
|
||
| $constantArrays = $type->getConstantArrays(); | ||
| if ($constantArrays !== [] && $type->isConstantArray()->yes()) { | ||
|
Check warning on line 2080 in src/Reflection/InitializerExprTypeResolver.php
|
||
| foreach ($constantArrays as $constantArray) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to rely on the result of the expression
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Background |
||
| if (!$this->constantArrayContainsNan($constantArray)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid a dedicated method constantArrayContainsNan and put the implementation here |
||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| private function constantArrayContainsNan(ConstantArrayType $constantArray): bool | ||
| { | ||
| $optionalKeys = $constantArray->getOptionalKeys(); | ||
| foreach ($constantArray->getValueTypes() as $index => $valueType) { | ||
| if (in_array($index, $optionalKeys, true)) { | ||
| continue; | ||
| } | ||
| if ($this->containsNan($valueType)) { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * @param BinaryOp\Plus|BinaryOp\Minus|BinaryOp\Mul|BinaryOp\Div|BinaryOp\ShiftLeft|BinaryOp\ShiftRight $expr | ||
| */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| <?php declare(strict_types = 1); | ||
|
|
||
| namespace Bug14394; | ||
|
|
||
| class Cl { | ||
| /** @param list<mixed> $v2 */ | ||
| public static function test(float $v1, array $v2): void { | ||
| if ($v1 == NAN) { echo "never reached\n"; } | ||
| if ($v1 === NAN) { echo "never reached\n"; } | ||
| if ($v2 == [NAN]) { echo "never reached\n"; } | ||
| if ($v2 === [NAN]) { echo "never reached\n"; } | ||
| } | ||
|
|
||
| /** @param array{NAN}|array{1} $v */ | ||
| public static function testUnionArrayNotAlwaysFalse(array $v): void { | ||
| if ($v === [1]) { echo "maybe reached\n"; } | ||
| if ($v == [1]) { echo "maybe reached\n"; } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove the isConstantArray check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Background tests task confirmed passing too. Both background tasks from earlier have now completed successfully — all clean.