You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Cannot infer type of generic attributes in match statements when inheritance is involved #13620
changed the title [-]Cannot infer type of attributes in `match` statements when inheritance is involved[/-][+]Cannot infer type of generic attributes in `match` statements when inheritance is involved[/+]on Sep 7, 2022
fromtypingimportGeneric, TypeVarT=TypeVar("T")
classBase(Generic[T]):
...
classA(Base[T]):
x: T__match_args__= ('x', )
def__init__(self, x: T):
self.x=xa: Base[str] =A("foo")
reveal_type(a) # Base[str] (correct)matcha:
caseA(b):
reveal_type(b) # Any (incorrect! Should be builtins.str)
Right now it is unclear to me: how to properly handle Base in the first place? It does not have x, it does not have __init__, it does not have __match_args__. Should it be even allowed to match A(b)? Probably yes, but this example is hard to process.
@sobolevn my understanding is that it doesn't matter that Base doesn't have __match_args__ or __init__, this should only matter for the case statements.
...but in the end the problem doesn't appear specific to match as @AlexWaygood demonstrates.
The core problem is that mypy should infer that the T in A[T] can only be str once the value is narrowed to Base[str].
Ideally, we should use something like map_instance_to_supertype to preserve type information about current type arguments.
But, we need a completely new approach for this. It is not implemented at all.
So, we take the subtype, go for all the route inside mro tree to find our supertype.
Then, in reverse order we apply type arguments from one parent to its subclass until we reach the our instance.
Then, we return the mapped instance and it will solve our problem.
Activity
[-]Cannot infer type of attributes in `match` statements when inheritance is involved[/-][+]Cannot infer type of generic attributes in `match` statements when inheritance is involved[/+]AlexWaygood commentedon Sep 7, 2022
This is possibly a repro without pattern-matching:
https://mypy-play.net/?mypy=latest&python=3.10&gist=5ba0af842f3a9d75ab0498009e0d92cb
sobolevn commentedon Sep 7, 2022
I think it is something similar to #13607 🤔
But, I am not sure. I didn't have any time to debug this yet.
sobolevn commentedon Sep 8, 2022
There are couple of this with this example:
Right now it is unclear to me: how to properly handle
Basein the first place? It does not havex, it does not have__init__, it does not have__match_args__. Should it be even allowed to matchA(b)? Probably yes, but this example is hard to process.ariebovenberg commentedon Sep 8, 2022
@sobolevn my understanding is that it doesn't matter that
Basedoesn't have__match_args__or__init__, this should only matter for thecasestatements....but in the end the problem doesn't appear specific to
matchas @AlexWaygood demonstrates.The core problem is that
mypyshould infer that theTinA[T]can only bestronce the value is narrowed toBase[str].sobolevn commentedon Sep 8, 2022
Yeap, this is another problem :)
I am actually working on code that @AlexWaygood provided. It is much easier for me to understand.
sobolevn commentedon Sep 9, 2022
Ok, the problem is in this line:
mypy/mypy/meet.py
Line 713 in 8147b0c
Ideally, we should use something like
map_instance_to_supertypeto preserve type information about current type arguments.But, we need a completely new approach for this. It is not implemented at all.
So, we take the subtype, go for all the route inside
mrotree to find our supertype.Then, in reverse order we apply type arguments from one parent to its subclass until we reach the our instance.
Then, we return the mapped instance and it will solve our problem.
sobolevn commentedon Sep 9, 2022
Ok, I found
map_type_from_supertype