From f37551d760d56c11ff4fd549534d753306c7be40 Mon Sep 17 00:00:00 2001 From: STerliakov Date: Sat, 26 Apr 2025 17:22:05 +0200 Subject: [PATCH 1/2] Add missing branch for `is_subtype(TypeType, Overload)` --- mypy/subtypes.py | 7 ++++++- test-data/unit/check-assert-type-fail.test | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 71b8b0ba59f55..8590f66688493 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -1091,7 +1091,12 @@ def visit_type_type(self, left: TypeType) -> bool: right = self.right if isinstance(right, TypeType): return self._is_subtype(left.item, right.item) - if isinstance(right, CallableType): + if isinstance(right, (Overloaded, CallableType)): + if isinstance(right, Overloaded) and right.is_type_obj(): + # Same as in other direction: if it's a constructor callable, all + # items should belong to the same class' constructor, so it's enough + # to check one of them. + right = right.items[0] if self.proper_subtype and not right.is_type_obj(): # We can't accept `Type[X]` as a *proper* subtype of Callable[P, X] # since this will break transitivity of subtyping. diff --git a/test-data/unit/check-assert-type-fail.test b/test-data/unit/check-assert-type-fail.test index 89b3a863f8c75..5146506496418 100644 --- a/test-data/unit/check-assert-type-fail.test +++ b/test-data/unit/check-assert-type-fail.test @@ -31,3 +31,19 @@ def f(si: arr.array[int]): from typing import assert_type, Callable def myfunc(arg: int) -> None: pass assert_type(myfunc, Callable[[int], None]) # E: Expression is of type "Callable[[Arg(int, 'arg')], None]", not "Callable[[int], None]" + +[case testAssertTypeOverload] +from typing import assert_type, overload + +class Foo: + @overload + def __new__(cls, x: int) -> Foo: ... + @overload + def __new__(cls, x: str) -> Foo: ... + def __new__(cls, x: "int | str") -> Foo: + return cls(0) + +assert_type(Foo, type[Foo]) +A = Foo +assert_type(A, type[Foo]) +[builtins fixtures/tuple.pyi] From 1a1dcb7519ac21f75d08c9b0c47e4090cd85ee89 Mon Sep 17 00:00:00 2001 From: STerliakov Date: Sat, 26 Apr 2025 17:32:01 +0200 Subject: [PATCH 2/2] Fix typing --- mypy/subtypes.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 8590f66688493..84fda7955d759 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -1091,12 +1091,12 @@ def visit_type_type(self, left: TypeType) -> bool: right = self.right if isinstance(right, TypeType): return self._is_subtype(left.item, right.item) - if isinstance(right, (Overloaded, CallableType)): - if isinstance(right, Overloaded) and right.is_type_obj(): - # Same as in other direction: if it's a constructor callable, all - # items should belong to the same class' constructor, so it's enough - # to check one of them. - right = right.items[0] + if isinstance(right, Overloaded) and right.is_type_obj(): + # Same as in other direction: if it's a constructor callable, all + # items should belong to the same class' constructor, so it's enough + # to check one of them. + return self._is_subtype(left, right.items[0]) + if isinstance(right, CallableType): if self.proper_subtype and not right.is_type_obj(): # We can't accept `Type[X]` as a *proper* subtype of Callable[P, X] # since this will break transitivity of subtyping.