-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Attempt to narrow down type results in new types added into the mix in unexpected way #8238
Comments
Right after I submitted the issue I found an even simpler example with just 2 asserts. After the 1st things look fine, but after the 2nd from typing import reveal_type
type Data = str | bytes | int | float | complex
class Attribute[D: Data]:
def __init__(self, data_type: type[D], /) -> None:
reveal_type(data_type) # type of "data_type" is "type[D@Attribute]"
assert not issubclass(data_type, complex)
reveal_type(data_type) # type of "data_type" is "type[str]* | type[bytes]* | type[int]* | type[float]*"
assert not issubclass(data_type, float)
reveal_type(data_type) # type of "data_type" is "type[str]* | type[bytes]* | type[bytearray]* | type[memoryview]* | type[int]*" Even an attempt to explicitly remove from typing import reveal_type
type Data = str | bytes | int | float | complex
class Attribute[D: Data]:
def __init__(self, data_type: type[D], /) -> None:
if issubclass(data_type, bytearray | memoryview):
raise TypeError
reveal_type(data_type) # type of "data_type" is "type[str]* | type[bytes]* | type[int]* | type[float]* | type[complex]*"
assert not issubclass(data_type, complex)
reveal_type(data_type) # type of "data_type" is "type[str]* | type[bytes]* | type[bytearray]* | type[memoryview]* | type[int]* | type[float]*"
assert not issubclass(data_type, float)
reveal_type(data_type) # type of "data_type" is "type[str]* | type[bytes]* | type[bytearray]* | type[memoryview]* | type[int]*" |
Pyright is working as intended here, so this isn't a bug. Traditionally, when There is a plan to deprecate the |
I know that bytes stands in for bytearray and memoryview, but my question is why is the behavior not consistent? Why does it introduce them only after the 2nd type narrowing. And more importantly why does it ignore my explicit exclusion of |
Ah, I see what you mean. I missed that in your original post. Reopening for additional investigation. |
Yeah, my original post might be a bit confusing. Check my 2nd post, when I realized I can replicate this with an easier setup that also makes it clearer to see what happens. |
… type narrowing when using a type variable with an upper bound that includes a promotion type. This addresses #8238.
This is addressed in pyright 1.1.370 |
With this code:
reveal_type(...)
shows the type being narrowed correctly (see comments on each reveal_type line for the pyright messages)We see the types being narrowed inside the
if
intofloat
vs the rest and after theif
they are recombined to give the original set of types.Now if I add an assert to narrow it down and eliminate one of the types (complex in this case), look what happens to the inferred types (see the comments):
Right after the assert, things look fine, with
complex
being removed from the set of types and we get a list with the remaining ones. This is expected. But inside the else branch of the test below it, suddenlytype[bytearray]*
andtype[memoryview]*
are added into the mix and after the if block, they are still present in the recombined set of types, even though they were never mentioned in the original set of types intype Data = ...
.This is with command line pyright version 1.1.369
The text was updated successfully, but these errors were encountered: