-
Notifications
You must be signed in to change notification settings - Fork 483
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
Handle BcMath\Number operators for simple cases #3787
base: 2.1.x
Are you sure you want to change the base?
Conversation
The result changed because getSortedTypes is called somewhere which sorts the exponent's union type and leads to a change in the result.
@@ -395,4 +395,9 @@ public function substrReturnFalseInsteadOfEmptyString(): bool | |||
return $this->versionId < 80000; | |||
} | |||
|
|||
public function supportsBcMathNumberOperatorOverloading(): bool |
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.
I copied this from the original PR. But I'm not sure whether it's correct. I assume that the reason we even need this is because earlier PHP versions might use a polyfill (which wouldn't have the operators overloaded). But PHP 8.4 can also use a polyfill, because bcmath is an optional extension.
assertType('int<4, 27>|int<16, 81>', pow($range, $x)); | ||
assertType('int<4, 27>|int<16, 81>', $range ** $x); | ||
assertType('int<4, 81>', pow($range, $x)); | ||
assertType('int<4, 81>', $range ** $x); | ||
|
||
assertType('int<4, 27>|int<16, 64>', pow($x, $range)); | ||
assertType('int<4, 27>|int<16, 64>', $x ** $range); | ||
assertType('int<4, 64>', pow($x, $range)); | ||
assertType('int<4, 64>', $x ** $range); |
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.
This is a result of UnionType::getSortedTypes
being called. I haven't looked into it, but I guess it's a bug in TypeCombinator::union
, because the result of a union shouldn't depend on the order of parameters.
EDIT: I had to fix it, because it broke the test on PHP <8.4 due to the extension only running on 8.4 and above.
assertType('true', $a or $b); | ||
} | ||
|
||
public function bcVsNever(Number $a): void |
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.
There's a bunch of inconsistencies in how never type is handled. I assume that all of these operations should result in *NEVER*
, but I'm ignoring it for this PR.
It was fixed by fixing union(int, int<null, -1>, int<1, null>) = int.
IntegerRangeType::fromInterval(8, 27), | ||
], | ||
IntegerRangeType::class, | ||
'int<4, 81>', |
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.
Was: int<4, 27>|int<16, 81>
.
IntegerRangeType::fromInterval(16, 81), | ||
], | ||
IntegerRangeType::class, | ||
'int<4, 81>', |
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.
Was: int<4, 7>|int<8, 81>
(testUnionInversed)
IntegerRangeType::fromInterval(1, null), | ||
], | ||
IntegerType::class, | ||
'int', |
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.
Was: int|int<min, -1>
(testUnionInversed)
This pull request has been marked as ready for review. |
Partially fixes: phpstan/phpstan#12099
Fixes: phpstan/phpstan#7937, phpstan/phpstan#8555
It's loosely based on #3660
Here is a demonstration of how the operators behave with various types: https://3v4l.org/jYX5J#v8.4.3
I skipped the complicated stuff. The main issue is unions. IMO it's too difficult to handle unions correctly in the extension. It would probably make more sense for PHPStan to handle the unions itself and offload only non-unions to extensions (e.g.
X|int + X|float
needs to know whatint + float
is).I also ignored a few preexisting bugs/inconsistencies (null and never types). They can be solved later.