Closed
Description
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")