diff --git a/mypy/subtypes.py b/mypy/subtypes.py index c91250edc1ab..4af105898bf3 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -151,6 +151,11 @@ def visit_instance(self, left: Instance) -> bool: return all(self.check_type_parameter(lefta, righta, tvar.variance) for lefta, righta, tvar in zip(t.args, right.args, right.type.defn.type_vars)) + if isinstance(right, TypeType): + item = right.item + if isinstance(item, TupleType): + item = item.fallback + return isinstance(item, Instance) and is_subtype(left, item.type.metaclass_type) else: return False @@ -269,11 +274,13 @@ def visit_type_type(self, left: TypeType) -> bool: if isinstance(right, CallableType): # This is unsound, we don't check the __init__ signature. return right.is_type_obj() and is_subtype(left.item, right.ret_type) - if (isinstance(right, Instance) and - right.type.fullname() in ('builtins.type', 'builtins.object')): - # Treat builtins.type the same as Type[Any]; - # treat builtins.object the same as Any. - return True + if isinstance(right, Instance): + if right.type.fullname() in ('builtins.type', 'builtins.object'): + # Treat builtins.type the same as Type[Any]; + # treat builtins.object the same as Any. + return True + item = left.item + return isinstance(item, Instance) and is_subtype(item, right.type.metaclass_type) return False diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 820b3a42070a..62b0d16dc060 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -2845,3 +2845,15 @@ class Concrete(metaclass=Meta): reveal_type(Concrete + X()) # E: Revealed type is 'builtins.str' Concrete + "hello" # E: Unsupported operand types for + ("Meta" and "str") + +[case testMetaclassSelftype] +from typing import TypeVar, Type + +class M(type): pass +T = TypeVar('T', bound='A') + +class M1(M): + def foo(cls: Type[T]) -> T: ... + +class A(metaclass=M1): pass +reveal_type(A.foo()) # E: Revealed type is '__main__.A*'