diff --git a/mypy/checker.py b/mypy/checker.py index 96e41a5e1786..ef9a9440cda1 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2497,6 +2497,22 @@ def check_override( # Use boolean variable to clarify code. fail = False op_method_wider_note = False + if isinstance(override, Overloaded) and isinstance(original, CallableType): + if not self.is_forward_op_method(name): + if all(is_subtype(item.ret_type, original.ret_type) for item in override.items): + # Return True to maintain backwards compatibility with existing mypy_primer + return True + if isinstance(node, OverloadedFuncDef) and node.impl and node.impl.type: + impl_type = node.impl.type + if is_subtype(impl_type, original, ignore_pos_arg_names=True): + return True + proper_impl_type = get_proper_type(impl_type) + if isinstance(proper_impl_type, CallableType): + if any( + isinstance(get_proper_type(tp), AnyType) + for tp in proper_impl_type.arg_types + ): + return True if not is_subtype(override, original, ignore_pos_arg_names=True): fail = True elif isinstance(override, Overloaded) and self.is_forward_op_method(name): diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index 68eccb46ab21..3ad810be87c3 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -1105,6 +1105,31 @@ class B(A): def f(self, x: str) -> str: return '' [out] +[case testOverloadedMethodWithNarrowerReturnTypes] +from typing import overload, Union, Optional + +class A: + def view(self, x: Optional[int] = None) -> "A": + ... + +class B(A): + def view(self, x: Optional[int] = None) -> "B": + return B() + +class C(A): + @overload # Should be allowed since B is a subtype of A + def view(self, x: int) -> B: ... + @overload # Should be allowed since C is a subtype of A + def view(self, x: None = None) -> "C": ... + def view(self, x: Optional[int] = None) -> Union[B, C]: + if x is None: + return C() + else: + return B() + +reveal_type(C().view(None)) # N: Revealed type is "__main__.C" +reveal_type(C().view(5)) # N: Revealed type is "__main__.B" + [case testOverrideOverloadedMethodWithMoreSpecificArgumentTypes] from foo import * [file foo.pyi]