Skip to content

Commit 7954987

Browse files
elazarggvanrossum
authored andcommitted
Patch subtyping for metaclasses (#2837)
* Patch subtyping for metaclasses * Oops - that was a test from a different PR * Add a test showing that the TypeVar works
1 parent e4c26a5 commit 7954987

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

mypy/subtypes.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ def visit_instance(self, left: Instance) -> bool:
151151
return all(self.check_type_parameter(lefta, righta, tvar.variance)
152152
for lefta, righta, tvar in
153153
zip(t.args, right.args, right.type.defn.type_vars))
154+
if isinstance(right, TypeType):
155+
item = right.item
156+
if isinstance(item, TupleType):
157+
item = item.fallback
158+
return isinstance(item, Instance) and is_subtype(left, item.type.metaclass_type)
154159
else:
155160
return False
156161

@@ -269,11 +274,13 @@ def visit_type_type(self, left: TypeType) -> bool:
269274
if isinstance(right, CallableType):
270275
# This is unsound, we don't check the __init__ signature.
271276
return right.is_type_obj() and is_subtype(left.item, right.ret_type)
272-
if (isinstance(right, Instance) and
273-
right.type.fullname() in ('builtins.type', 'builtins.object')):
274-
# Treat builtins.type the same as Type[Any];
275-
# treat builtins.object the same as Any.
276-
return True
277+
if isinstance(right, Instance):
278+
if right.type.fullname() in ('builtins.type', 'builtins.object'):
279+
# Treat builtins.type the same as Type[Any];
280+
# treat builtins.object the same as Any.
281+
return True
282+
item = left.item
283+
return isinstance(item, Instance) and is_subtype(item, right.type.metaclass_type)
277284
return False
278285

279286

test-data/unit/check-classes.test

+12
Original file line numberDiff line numberDiff line change
@@ -2882,3 +2882,15 @@ class Concrete(metaclass=Meta):
28822882

28832883
reveal_type(Concrete + X()) # E: Revealed type is 'builtins.str'
28842884
Concrete + "hello" # E: Unsupported operand types for + ("Meta" and "str")
2885+
2886+
[case testMetaclassSelftype]
2887+
from typing import TypeVar, Type
2888+
2889+
class M(type): pass
2890+
T = TypeVar('T', bound='A')
2891+
2892+
class M1(M):
2893+
def foo(cls: Type[T]) -> T: ...
2894+
2895+
class A(metaclass=M1): pass
2896+
reveal_type(A.foo()) # E: Revealed type is '__main__.A*'

0 commit comments

Comments
 (0)