diff --git a/mypy/typeops.py b/mypy/typeops.py index 13082225e5fd..866eb72ede3e 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -521,15 +521,18 @@ def callable_corresponding_argument( # def right(a: int = ...) -> None: ... # def left(__a: int = ..., *, a: int = ...) -> None: ... - from mypy.subtypes import is_equivalent + from mypy.subtypes import is_subtype if ( not (by_name.required or by_pos.required) and by_pos.name is None and by_name.pos is None - and is_equivalent(by_name.typ, by_pos.typ) ): - return FormalArgument(by_name.name, by_pos.pos, by_name.typ, False) + # We actually want the intersection of by_name.typ and by_pos.typ + if is_subtype(by_name.typ, by_pos.typ): + return FormalArgument(by_name.name, by_pos.pos, by_name.typ, False) + if is_subtype(by_pos.typ, by_name.typ): + return FormalArgument(by_name.name, by_pos.pos, by_pos.typ, False) return by_name if by_name is not None else by_pos diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index e7f6ff04c13e..560d4a5c12fc 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -231,9 +231,21 @@ def f(x: 'A') -> Any: # E: Overloaded function implementation does not accept al reveal_type(f(A())) # N: Revealed type is "__main__.B" reveal_type(f(B())) # N: Revealed type is "__main__.A" - [builtins fixtures/isinstance.pyi] +[case testTypeCheckOverloadImplOverlapVarArgsAndKwargs] +from __future__ import annotations +from typing import overload + +@overload +def foo(x: int) -> None: ... +@overload +def foo(a: str, /) -> None: ... + +def foo(*args: int | str, **kw: int) -> None: + pass +[builtins fixtures/tuple.pyi] + [case testTypeCheckOverloadWithImplTooSpecificRetType] from typing import overload, Any