diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index 5c28e8332a76c..06e716372f248 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -287,6 +287,13 @@ def __hash__(self) -> int: # This is a catch-all for remaining uncategorized errors. MISC: Final = ErrorCode("misc", "Miscellaneous other checks", "General") +CALL_ARG_MISC: Final = ErrorCode( + "call-arg", "Check number, names and kinds of arguments in calls", "General", sub_code_of=MISC +) +# CALL_ARG_MISC reuses the "call-arg" code string, so keep CALL_ARG as the canonical +# code that "call-arg" resolves to in the registry. +error_codes[CALL_ARG.code] = CALL_ARG + OVERLOAD_CANNOT_MATCH: Final = ErrorCode( "overload-cannot-match", "Warn if an @overload signature can never be matched", diff --git a/mypy/messages.py b/mypy/messages.py index 93d5f2c212d0e..ffac78201a6cd 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -970,8 +970,9 @@ def too_many_positional_arguments(self, callee: CallableType, context: Context) msg = "Too many positional arguments" else: msg = "Too many positional arguments" + for_function(callee) - self.fail(msg, context) + self.fail(msg, context, code=codes.CALL_ARG_MISC) self.maybe_note_about_special_args(callee, context) + self.note_defined_here(callee, context, code=codes.CALL_ARG_MISC) def maybe_note_about_special_args(self, callee: CallableType, context: Context) -> None: if self.prefer_simple_messages(): @@ -1018,7 +1019,9 @@ def unexpected_keyword_argument( ) self.note_defined_here(callee, context) - def note_defined_here(self, callee: CallableType, context: Context) -> None: + def note_defined_here( + self, callee: CallableType, context: Context, code: ErrorCode = codes.CALL_ARG + ) -> None: module = find_defining_module(self.modules, callee) if ( module @@ -1031,7 +1034,7 @@ def note_defined_here(self, callee: CallableType, context: Context) -> None: fname = "Called function" else: fname = fname.split(" of ")[0] # use short method names in the note - self.note(f'{fname} defined in "{module.fullname}"', context, code=codes.CALL_ARG) + self.note(f'{fname} defined in "{module.fullname}"', context, code=code) def duplicate_argument_value(self, callee: CallableType, index: int, context: Context) -> None: self.fail( diff --git a/mypy/test/testtypes.py b/mypy/test/testtypes.py index ac6d24b1ef4c0..6de922cb7f234 100644 --- a/mypy/test/testtypes.py +++ b/mypy/test/testtypes.py @@ -236,7 +236,7 @@ def test_typeddict_type_constructor_signature(self) -> None: assert closed.is_closed with self.assertRaises(TypeError): - TypedDictType( # type: ignore[misc] + TypedDictType( # type: ignore[call-arg] {"x": self.fx.o}, {"x"}, set(), self.fx.a, 10, 20, True ) diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 85a2264c2088b..5296d813334e4 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -331,6 +331,17 @@ def h(x: int, y: int, z: int) -> None: pass h(y=1, z=1) # E: Missing positional argument "x" in call to "h" [call-arg] h(y=1) # E: Missing positional arguments "x", "z" in call to "h" [call-arg] +[case testTooManyPositionalArgumentsErrorCode] +def f(a: int, *, b: int) -> None: pass +f(1, 2) # E: Too many positional arguments for "f" [call-arg] +f(1, 2) # type: ignore[call-arg] +f(1, 2) # type: ignore[misc] + +[case testTooManyPositionalArgumentsCoveredByMiscUnused] +# flags: --warn-unused-ignores +def f(a: int, *, b: int) -> None: pass +f(1, 2) # type: ignore[misc] # E: Unused "type: ignore" comment, use narrower [call-arg] instead of [misc] code [unused-ignore] + [case testErrorCodeArgType] def f(x: int) -> None: pass f('') # E: Argument 1 to "f" has incompatible type "str"; expected "int" [arg-type] diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index f11c2b6f4fc40..6f5e11d85ee48 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -495,6 +495,21 @@ def f(a: int, *, b: str) -> None: pass f(1) # E: Missing named argument "b" for "f" +[case testTooManyPositionalArgumentsFromOtherModule] +import m +m.f(1, 2) +[file m.py] +def f(a: int, *, b: int) -> None: + pass +[out] +main:2: error: Too many positional arguments for "f" +main:2: note: "f" defined in "m" + +[case testTooManyPositionalArgumentsForSameModule] +def f(a: int, *, b: int) -> None: + pass +f(1, 2) # E: Too many positional arguments for "f" + [case testStarArgsAndKwArgsSpecialCase] from typing import Dict, Mapping diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 285ae92325d8e..158b95aa598d0 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -132,6 +132,7 @@ main:5: error: Argument "rename" to "namedtuple" has incompatible type "str"; ex main:6: error: Unexpected keyword argument "unrecognized_arg" for "namedtuple" main:6: note: "namedtuple" defined in "collections" main:7: error: Too many positional arguments for "namedtuple" +main:7: note: "namedtuple" defined in "collections" [case testNamedTupleDefaults] from collections import namedtuple diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 4d68f93a21eda..e48700c69e38e 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -1112,6 +1112,7 @@ reveal_type(t3) # N: Revealed type is "Any" T4 = TypeAliasType("T4") # E: Missing positional argument "value" in call to "TypeAliasType" T5 = TypeAliasType("T5", int, str) # E: Too many positional arguments for "TypeAliasType" \ + # N: "TypeAliasType" defined in "typing_extensions" \ # E: Argument 3 to "TypeAliasType" has incompatible type "type[str]"; expected "tuple[TypeVar? | ParamSpec? | TypeVarTuple?, ...]" [builtins fixtures/tuple.pyi] [typing fixtures/typing-full.pyi]