diff --git a/mypy/subtypes.py b/mypy/subtypes.py index a280c217cd8a7..9848cb45154b8 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -249,13 +249,19 @@ def visit_overloaded(self, left: Overloaded) -> bool: return True return False elif isinstance(right, Overloaded): - # TODO: this may be too restrictive - if len(left.items()) != len(right.items()): - return False - for i in range(len(left.items())): - if not is_subtype(left.items()[i], right.items()[i], self.check_type_parameter, + # Ensure each overload in the left side is accounted for. + sub_overloads = left.items()[:] + while sub_overloads: + left_item = sub_overloads[-1] + for right_item in right.items(): + if is_subtype(left_item, right_item, self.check_type_parameter, ignore_pos_arg_names=self.ignore_pos_arg_names): + sub_overloads.pop() + break + else: + # One of the overloads was not present in the right side. return False + return True elif isinstance(right, UnboundType): return True diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 1dd3353ec903c..36c66a906001d 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -1419,23 +1419,6 @@ class B(A): [out] tmp/foo.pyi:8: error: Signature of "__add__" incompatible with supertype "A" -[case testOverloadedOperatorMethodOverrideWithSwitchedItemOrder] -from foo import * -[file foo.pyi] -from typing import overload, Any -class A: - @overload - def __add__(self, x: 'B') -> 'B': pass - @overload - def __add__(self, x: 'A') -> 'A': pass -class B(A): - @overload - def __add__(self, x: 'A') -> 'A': pass - @overload - def __add__(self, x: 'B') -> 'B': pass -[out] -tmp/foo.pyi:8: error: Signature of "__add__" incompatible with supertype "A" - [case testReverseOperatorMethodArgumentType] from typing import Any class A: pass @@ -2494,6 +2477,33 @@ reveal_type(f(BChild())) # E: Revealed type is 'foo.B' [builtins fixtures/classmethod.pyi] [out] +[case testSubtypeWithMoreOverloadsThanSupertypeSucceeds] +from foo import * +[file foo.pyi] +from typing import overload + + +class X: pass +class Y: pass +class Z: pass + + +class A: + @overload + def f(self, x: X) -> X: pass + @overload + def f(self, y: Y) -> Y: pass + +class B(A): + @overload + def f(self, x: X) -> X: pass + @overload + def f(self, y: Y) -> Y: pass + @overload + def f(self, z: Z) -> Z: pass +[builtins fixtures/classmethod.pyi] +[out] + [case testTypeTypeOverlapsWithObjectAndType] from foo import * [file foo.pyi]