-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Prevent crash with Unpack of a fixed tuple in PEP695 type alias #18451
Prevent crash with Unpack of a fixed tuple in PEP695 type alias #18451
Conversation
This comment has been minimized.
This comment has been minimized.
Primer results are terrible, I'll look closer tomorrow - all those errors should have moved to another location, not disappeared entirely. |
… copy preventing union items update.
57ba734
to
0ceb6ad
Compare
This comment has been minimized.
This comment has been minimized.
This is more complicated than I expected. The problem reduces to the following (playground): from collections.abc import Callable, Coroutine
from typing import Any, Concatenate, Generic, TypeVar
IntFun = TypeVar("IntFun", bound=Callable[Concatenate[int, ...], str])
StrFun = TypeVar("StrFun", bound=Callable[Concatenate[str, ...], str])
AnyFun = TypeVar("AnyFun", bound=Callable[..., str])
class IntC(Generic[IntFun]): ...
class StrC(Generic[StrFun]): ...
AnyC = IntC[AnyFun] | StrC[AnyFun]
def run(_: AnyC[IntFun]) -> IntFun: ... # E: Type argument "IntFun" of "StrC" must be a subtype of "Callable[[str, VarArg(Any), KwArg(Any)], str]" [type-var] (the error exists on master and does not exist with this patch applied) And I have no idea what is more reasonable here. |
Even simpler reproducer (no callables): import typing
IntT = typing.TypeVar("IntT", bound=int)
StrT = typing.TypeVar("StrT", bound=str)
AnyT = typing.TypeVar("AnyT", bound=typing.Any)
class IntC(typing.Generic[IntT]): ...
class StrC(typing.Generic[StrT]): ...
AnyC = IntC[AnyT] | StrC[AnyT]
def run(_: AnyC[StrT]) -> StrT: ... # E: Type argument "StrT" of "IntC" must be a subtype of "int" IMO there should be an error on |
@A5rocks I'm not sure I want to see any errors on the |
I think
... which isn't very useful. I mean at best we could pretend "subtype" here means the PEP 483 version of it (which doesn't include
and like, assignability allows |
Not giving error on type alias definition is intentional. It is to allow a pattern like this: # in one file
T = TypeVar("T", bound=int)
class C(Generic[T]): ...
# in other file
T = TypeVar("T") # same as bound=object
A = list[C[T]]
x: A[int] # OK
y: A[str] # Error People often use "throw away" type variable for type aliases. With the error at alias definition, one would be forced to copy over all type variable bounds for no added safety. |
I agree that this strictness with definition-time checks somewhat harms usability. Anyway, let's see where #18456 goes. I don't believe that changing behaviour of aliases to fix the tree traversal is reasonable. Is there something else we can visit instead of In the meantime #18456 takes another approach that doesn't affect checking existing aliases, but suffers from not modifying the tuple where it is expected. Maybe that's good enough? |
@sterliakov A proper fix would be to simply update Btw another thing (that I noticed while looking at your other attempt) is that you may need to add this line # Invalidate recursive status cache in case it was previously set.
existing.node._is_recursive = None to the new syntax code path, as it looks like I forgot to copy it in #17961 (if you do, please also add a corresponding test), you can make a separate PR for this. |
Amazing, thanks! I got lost in
It's there in reused |
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
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.
Please update the PR description so that it reflects the current state of the PR.
Fixes #18309.
Add missing
visit_type_alias_stmt()
implementation to mixedtraverser.py to visit the alias target directly.