diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 6e0bb9ff8168..838d7b4ab722 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2651,8 +2651,12 @@ def overload_arg_similarity(actual: Type, formal: Type) -> int: else: return 0 elif isinstance(actual, TypeType): + item = actual.item if formal.type.fullname() in {"builtins.object", "builtins.type"}: return 2 + elif isinstance(item, Instance): + # FIX: this does not handle e.g. Union of instances + return overload_arg_similarity(item.type.metaclass_type, formal) else: return 0 else: diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index f2b83290cb60..78337dde5279 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -3290,6 +3290,38 @@ x3: M = cv [builtins fixtures/classmethod.pyi] +[case testMetaclassOverloadResolution] +from typing import Type, overload +class A: pass + +class EM(type): pass +class E(metaclass=EM): pass + +class EM1(type): pass +class E1(metaclass=EM1): pass + +@overload +def f(x: EM) -> int: ... +@overload +def f(x: EM1) -> A: ... +@overload +def f(x: str) -> str: ... +def f(x: object) -> object: return '' + +e: EM +reveal_type(f(e)) # E: Revealed type is 'builtins.int' + +et: Type[E] +reveal_type(f(et)) # E: Revealed type is 'builtins.int' + +e1: EM1 +reveal_type(f(e1)) # E: Revealed type is '__main__.A' + +e1t: Type[E1] +reveal_type(f(e1t)) # E: Revealed type is '__main__.A' + +reveal_type(f('')) # E: Revealed type is 'builtins.str' + -- Synthetic types crashes -- -----------------------