Skip to content
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

Overloaded metaclass __or__ does not keep typing #11648

Open
esoma opened this issue Dec 1, 2021 · 2 comments
Open

Overloaded metaclass __or__ does not keep typing #11648

esoma opened this issue Dec 1, 2021 · 2 comments
Labels

Comments

@esoma
Copy link
Contributor

esoma commented Dec 1, 2021

This is not an issue in 0.91, but it occurs in master. Given a metaclass that overrides __or__, the correct type is only maintained in the immediate result. If the result of the __or__ is stored then it will turn to builtins.object.

from typing import Union

class MyUnion(type): ...

class Meta(type):
    
    def __or__(self, other) -> MyUnion: ... # type: ignore
    
class Foo(metaclass=Meta): ...

reveal_type(Foo | Foo) # line 12
isinstance(object(), Foo | Foo)
Bar = Foo | Foo
reveal_type(Bar) # line 14
isinstance(object(), Bar) # line 15

Output in 0.91 (the behavior I expect):

test2.py:12: note: Revealed type is "test2.MyUnion"
test2.py:16: note: Revealed type is "test2.MyUnion"

Output in master:

test2.py:12: note: Revealed type is "test2.MyUnion"
test2.py:16: note: Revealed type is "builtins.object"
test2.py:17: error: Parameterized generics cannot be used with class or instance checks
test2.py:17: error: Argument 2 to "isinstance" has incompatible type "object"; expected "Union[type, UnionType, Tuple[Union[type, UnionType, Tuple[Any, ...]], ...]]"

Edit:
It occurs to me as I re-read PEP 604 that it doesn't specify that OR'd types may create an alias which can be used with isinstance, so maybe my example using it that way is not perfect, but I think the circumstances are still valid.

Edit Edit:
Reading through the PEP 604 discussion thread on typing-sig it seems that aliases composed of unions are to work with isinstance, so even simpler cases are currently broken:

class A: ...
class B: ...
C = A | B
reveal_type(C) # Revealed type is "builtins.object"
isinstance(object(), C) # error: Parameterized generics cannot be used with class or instance checks
                        # error: Argument 2 to "isinstance" has incompatible type "object"; expected "Union[type, UnionType, Tuple[Union[type, UnionType, Tuple[Any, ...]], ...]]"

Semi-related, this is getting through:

isinstance(object(), int | list[int]) # no error (should be "error: Parameterized generics cannot be used with class or instance checks")
@esoma esoma added the bug mypy got something wrong label Dec 1, 2021
@esoma
Copy link
Contributor Author

esoma commented Dec 1, 2021

Bisecting show this behavior change occurred from 56618b9

@hunterC90
Copy link

Looks like this should have the label topic-pep-604.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants