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
PHPStan loses type resolution when creating a union of int
and numeric-string
#10092
Comments
We've talked about this in person last year at phpDay :) The problem is that generics generalize types too much. When we initially implemented them, we decided that:
Should turn Since then we mostly changed our minds on this topic and the types shouldn't be touched at all. But there's one problem. There's a nice proposal to solve this while keeping the types the same and not generalize them: #6732 (comment) Unfortunately I'm a bit worried about the complexity and haven't yet had the courage to try to tackle it :) |
@ondrejmirtes worth splitting the problem in two parts, IMO:
|
Yeah because |
That seems wrong: the /** @return TypeInterface<numeric-string> */
function numeric_string() { throw new \Exception('irrelevant'); } I would understand if the |
PHPStan does not differentiate a source of a type like that, maybe there could be a half-step like that 🤔 |
Yeah, I think that is basically an "anchor" that needs to be considered a constraint, IMO. In this case, If PHPStan tries to widen the types, it cannot widen further than what is explicitly declared, IMO. In this case, |
Closes phpstan/phpstan#8166 Closes phpstan/phpstan#8127 Closes phpstan/phpstan#7944 Closes phpstan/phpstan#7283 Closes phpstan/phpstan#6653 Closes phpstan/phpstan#6196 Closes phpstan/phpstan#9084 Closes phpstan/phpstan#8683 Closes phpstan/phpstan#8074 Closes phpstan/phpstan#7984 Closes phpstan/phpstan#7301 Closes phpstan/phpstan#7087 Closes phpstan/phpstan#5594 Closes phpstan/phpstan#5592 Closes phpstan/phpstan#9472 Closes phpstan/phpstan#9764 Closes phpstan/phpstan#10092
Closes phpstan/phpstan#8166 Closes phpstan/phpstan#8127 Closes phpstan/phpstan#7944 Closes phpstan/phpstan#7283 Closes phpstan/phpstan#6653 Closes phpstan/phpstan#6196 Closes phpstan/phpstan#9084 Closes phpstan/phpstan#8683 Closes phpstan/phpstan#8074 Closes phpstan/phpstan#7984 Closes phpstan/phpstan#7301 Closes phpstan/phpstan#7087 Closes phpstan/phpstan#5594 Closes phpstan/phpstan#5592 Closes phpstan/phpstan#9472 Closes phpstan/phpstan#9764 Closes phpstan/phpstan#10092
Closes phpstan/phpstan#8166 Closes phpstan/phpstan#8127 Closes phpstan/phpstan#7944 Closes phpstan/phpstan#7283 Closes phpstan/phpstan#6653 Closes phpstan/phpstan#6196 Closes phpstan/phpstan#9084 Closes phpstan/phpstan#8683 Closes phpstan/phpstan#8074 Closes phpstan/phpstan#7984 Closes phpstan/phpstan#7301 Closes phpstan/phpstan#7087 Closes phpstan/phpstan#5594 Closes phpstan/phpstan#5592 Closes phpstan/phpstan#9472 Closes phpstan/phpstan#9764 Closes phpstan/phpstan#10092
Last night I came up with the idea that we mostly shouldn't generalize the generic type variables, except when they're in object generics, like Here's the resulting PR: phpstan/phpstan-src#2818 We can't do this for objects, because I want The new behaviour now only applies to bleeding edge (https://phpstan.org/blog/what-is-bleeding-edge) so definitely enable it to get the taste of the future 👍 |
@ondrejmirtes not 100% sure about the rationale, but happy that you got an epiphany on this: it is something you've been stuck with for well over a year :-) |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Bug report
When using
azjezz/psl
, thePsl\Type\union()
is used to create a union type out of two (or more)Psl\Type\TypeInterface<T>
instances.Roughly:
function union(TypeInterface<T>, TypeInterface<U>): TypeInterface<T|U>
.This works fine, but PHPStan seems to have trouble in computing union types for somehow close types like
int
andnumeric-string
, leading to inference ofint|string
rather thanint|numeric-string
.Similarly, it cannot compute
0
andpositive-int
, leading toint
being inferred, rather than0|int<1, max>
orint<0, max>
.Code snippet that reproduces the problem
https://phpstan.org/r/749e7db4-8d56-4d2d-9faa-1d3d32790ba0
Expected output
union(int, numeric-string)
should becomeint|numeric-string
(currently producesint|string
)union(0, int<1, max>)
should become0|int<1, max>
(currently producesint
)Did PHPStan help you today? Did it make you happy in any way?
Thanks for your continued work on this: makes PHP bearable :-)
The text was updated successfully, but these errors were encountered: