From d9b1295a8cf5bd912f4c586a4c355e221eda5f20 Mon Sep 17 00:00:00 2001 From: STerliakov Date: Mon, 30 Jun 2025 01:12:56 +0200 Subject: [PATCH 1/2] Do not show protocol compat notice for unpacking --- mypy/checkexpr.py | 9 ++++++--- test-data/unit/check-functions.test | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 603acbe84f0f..8223ccfe4ca0 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2684,9 +2684,12 @@ def check_arg( context=context, outer_context=outer_context, ) - self.msg.incompatible_argument_note( - original_caller_type, callee_type, context, parent_error=error - ) + if not caller_kind.is_star(): + # For *args and **kwargs this note would be incorrect - we're comparing + # iterable/mapping type with union of relevant arg types. + self.msg.incompatible_argument_note( + original_caller_type, callee_type, context, parent_error=error + ) if not self.msg.prefer_simple_messages(): self.chk.check_possible_missing_await( caller_type, callee_type, context, error.code diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index ceb7af433dce..496899dd3dd1 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -3694,3 +3694,17 @@ def defer() -> int: ... [out] main: note: In function "a": main:6: error: Unsupported operand types for + ("int" and "str") + +[case testNoExtraNoteForUnpacking] +from typing import Protocol + +class P(Protocol): + arg: int + # Something that list and dict also have + def __contains__(self, item: object) -> bool: ... + +def foo(x: P, y: P) -> None: ... + +foo(*[0, '']) # E: Argument 1 to "foo" has incompatible type "*list[object]"; expected "P" +foo(**{'x': 0, 'y': ''}) # E: Argument 1 to "foo" has incompatible type "**dict[str, object]"; expected "P" +[builtins fixtures/dict.pyi] From 05cf2e5107bb46f094e1dc4247e740aff7727a5b Mon Sep 17 00:00:00 2001 From: STerliakov Date: Mon, 30 Jun 2025 01:48:07 +0200 Subject: [PATCH 2/2] Add explicit types to guard against join-vs-union changes --- test-data/unit/check-functions.test | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 496899dd3dd1..07cfd09b2529 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -3705,6 +3705,8 @@ class P(Protocol): def foo(x: P, y: P) -> None: ... -foo(*[0, '']) # E: Argument 1 to "foo" has incompatible type "*list[object]"; expected "P" -foo(**{'x': 0, 'y': ''}) # E: Argument 1 to "foo" has incompatible type "**dict[str, object]"; expected "P" +args: list[object] +foo(*args) # E: Argument 1 to "foo" has incompatible type "*list[object]"; expected "P" +kwargs: dict[str, object] +foo(**kwargs) # E: Argument 1 to "foo" has incompatible type "**dict[str, object]"; expected "P" [builtins fixtures/dict.pyi]