From 2b3ad7648b98c2ccfebe183f2e712f54752b0836 Mon Sep 17 00:00:00 2001 From: "Kai (Kazuya Ito)" Date: Sun, 1 Mar 2026 15:02:09 +0900 Subject: [PATCH 1/3] Update Duplicate parameter error --- mypy/nodes.py | 2 +- test-data/unit/check-fastparse.test | 12 ++++++------ test-data/unit/check-functions.test | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index e3b8f24d1ad06..1128de5705426 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -5101,7 +5101,7 @@ def check_arg_names( seen_names: set[str | None] = set() for name, node in zip(names, nodes): if name is not None and name in seen_names: - fail(f'Duplicate argument "{name}" in {description}', node) + fail(f'Duplicate parameter "{name}" in {description}', node) break seen_names.add(name) diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index 4eef7a0e116cb..a0b619349d23f 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -280,22 +280,22 @@ def f7(x: int): # E: Function has duplicate type signatures def f(x, y, z): pass -def g(x, y, x): # E: Duplicate argument "x" in function definition +def g(x, y, x): # E: Duplicate parameter "x" in function definition pass -def h(x, y, *x): # E: Duplicate argument "x" in function definition +def h(x, y, *x): # E: Duplicate parameter "x" in function definition pass -def i(x, y, *z, **z): # E: Duplicate argument "z" in function definition +def i(x, y, *z, **z): # E: Duplicate parameter "z" in function definition pass -def j(x: int, y: int, *, x: int = 3): # E: Duplicate argument "x" in function definition +def j(x: int, y: int, *, x: int = 3): # E: Duplicate parameter "x" in function definition pass -def k(*, y, z, y): # E: Duplicate argument "y" in function definition +def k(*, y, z, y): # E: Duplicate parameter "y" in function definition pass -lambda x, y, x: ... # E: Duplicate argument "x" in function definition +lambda x, y, x: ... # E: Duplicate parameter "x" in function definition [case testNoCrashOnImportFromStar] from pack import * diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 7eb6723844b4c..3856f76687ff3 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -1937,7 +1937,7 @@ def k(f: Callable[[KwArg(), NamedArg(Any, 'x')], int]): pass # E: A **kwargs arg from typing import Callable from mypy_extensions import Arg, VarArg, KwArg, DefaultArg -def f(f: Callable[[Arg(int, 'x'), int, Arg(int, 'x')], int]): pass # E: Duplicate argument "x" in Callable +def f(f: Callable[[Arg(int, 'x'), int, Arg(int, 'x')], int]): pass # E: Duplicate parameter "x" in Callable [builtins fixtures/dict.pyi] From da0d0809f21970c2e9c1fc10a03577c1433c1a97 Mon Sep 17 00:00:00 2001 From: "Kai (Kazuya Ito)" Date: Mon, 2 Mar 2026 09:05:43 +0900 Subject: [PATCH 2/3] Update "self and cls" related code --- mypy/checker.py | 4 ++-- mypy/nodes.py | 6 +++--- mypy/semanal.py | 12 ++++++------ mypy/suggestions.py | 4 ++-- mypy/typeops.py | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index fc636e9a7218c..7d6f2fa90ee8e 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1349,7 +1349,7 @@ def check_func_def( if typ.type_is: arg_index = 0 # For methods and classmethods, we want the second parameter - if ref_type is not None and defn.has_self_or_cls_argument: + if ref_type is not None and defn.has_self_or_cls_parameter: arg_index = 1 if arg_index < len(typ.arg_types) and not is_subtype( typ.type_is, typ.arg_types[arg_index] @@ -1624,7 +1624,7 @@ def require_correct_self_argument(self, func: Type, defn: FuncDef) -> bool: if ref_type is None: return False - if not defn.has_self_or_cls_argument or ( + if not defn.has_self_or_cls_parameter or ( func.arg_kinds and func.arg_kinds[0] in [nodes.ARG_STAR, nodes.ARG_STAR2] ): return False diff --git a/mypy/nodes.py b/mypy/nodes.py index 1128de5705426..dc893a0656025 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -604,7 +604,7 @@ def __init__(self) -> None: self.is_property = False self.is_class = False # Is this a `@staticmethod` (explicit or implicit)? - # Note: use has_self_or_cls_argument to check if there is `self` or `cls` argument + # Note: use has_self_or_cls_parameter to check if there is `self` or `cls` parameter self.is_static = False self.is_final = False self.is_explicit_override = False @@ -622,8 +622,8 @@ def fullname(self) -> str: return self._fullname @property - def has_self_or_cls_argument(self) -> bool: - """If used as a method, does it have an argument for method binding (`self`, `cls`)? + def has_self_or_cls_parameter(self) -> bool: + """If used as a method, does it have an parameter for method binding (`self`, `cls`)? This is true for `__new__` even though `__new__` does not undergo method binding, because we still usually assume that `cls` corresponds to the enclosing class. diff --git a/mypy/semanal.py b/mypy/semanal.py index e2c073fd4dea8..ad5d6e969da41 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1121,12 +1121,12 @@ def remove_unpack_kwargs(self, defn: FuncDef, typ: CallableType) -> CallableType return typ.copy_modified(arg_types=new_arg_types, unpack_kwargs=True) def prepare_method_signature(self, func: FuncDef, info: TypeInfo, has_self_type: bool) -> None: - """Check basic signature validity and tweak annotation of self/cls argument.""" + """Check basic signature validity and tweak annotation of self/cls parameter.""" # Only non-static methods are special, as well as __new__. functype = func.type if func.name == "__new__": func.is_static = True - if func.has_self_or_cls_argument: + if func.has_self_or_cls_parameter: if func.name in ["__init_subclass__", "__class_getitem__"]: func.is_class = True if func.arguments and isinstance(functype, CallableType): @@ -1149,7 +1149,7 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo, has_self_type: # This error is off by default, since it is explicitly allowed # by the PEP 673. self.fail( - 'Redundant "Self" annotation for the first method argument', + 'Redundant "Self" annotation for the first method parameter', func, code=codes.REDUNDANT_SELF_TYPE, ) @@ -1668,10 +1668,10 @@ def analyze_function_body(self, defn: FuncItem) -> None: for arg in defn.arguments: self.add_local(arg.variable, defn) - # The first argument of a non-static, non-class method is like 'self' + # The first parameter of a non-static, non-class method is like 'self' # (though the name could be different), having the enclosing class's # instance type. - if is_method and defn.has_self_or_cls_argument and defn.arguments: + if is_method and defn.has_self_or_cls_parameter and defn.arguments: if not defn.is_class: defn.arguments[0].variable.is_self = True else: @@ -6117,7 +6117,7 @@ def visit_member_expr(self, expr: MemberExpr) -> None: # check for self.bar or cls.bar in method/classmethod func_def = self.function_stack[-1] if ( - func_def.has_self_or_cls_argument + func_def.has_self_or_cls_parameter and func_def.info is self.type and isinstance(func_def.type, CallableType) and func_def.arguments diff --git a/mypy/suggestions.py b/mypy/suggestions.py index 39a220e34091e..5c42eaf5fed9b 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -478,7 +478,7 @@ def get_guesses_from_parent(self, node: FuncDef) -> list[CallableType]: def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature: """Compute a suggestion for a function. - Return the type and whether the first argument should be ignored. + Return the type and whether the first parameter should be ignored. """ graph = self.graph callsites, orig_errors = self.get_callsites(node) @@ -487,7 +487,7 @@ def get_suggestion(self, mod: str, node: FuncDef) -> PyAnnotateSignature: if self.no_errors and orig_errors: raise SuggestionFailure("Function does not typecheck.") - is_method = bool(node.info) and node.has_self_or_cls_argument + is_method = bool(node.info) and node.has_self_or_cls_parameter with state.strict_optional_set(graph[mod].options.strict_optional): guesses = self.get_guesses( diff --git a/mypy/typeops.py b/mypy/typeops.py index 839c6454ca28f..db1a44c77f654 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -885,7 +885,7 @@ def callable_type( fdef: FuncItem, fallback: Instance, ret_type: Type | None = None ) -> CallableType: # TODO: somewhat unfortunate duplication with prepare_method_signature in semanal - if fdef.info and fdef.has_self_or_cls_argument and fdef.arg_names: + if fdef.info and fdef.has_self_or_cls_parameter and fdef.arg_names: self_type: Type = fill_typevars(fdef.info) if fdef.is_class or fdef.name == "__new__": self_type = TypeType.make_normalized(self_type) From c7e6186260adaac5407f45bcdab053414757abf7 Mon Sep 17 00:00:00 2001 From: "Kai (Kazuya Ito)" Date: Mon, 2 Mar 2026 10:02:41 +0900 Subject: [PATCH 3/3] Correct Redundant "Self" error message --- docs/source/error_code_list2.rst | 4 ++-- test-data/unit/check-selftype.test | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/error_code_list2.rst b/docs/source/error_code_list2.rst index 36cf05d4f3f85..d8120abb6c7d0 100644 --- a/docs/source/error_code_list2.rst +++ b/docs/source/error_code_list2.rst @@ -94,7 +94,7 @@ Check that methods do not have redundant Self annotations [redundant-self] -------------------------------------------------------------------------- If a method uses the ``Self`` type in the return type or the type of a -non-self argument, there is no need to annotate the ``self`` argument +non-self parameter, there is no need to annotate the ``self`` parameter explicitly. Such annotations are allowed by :pep:`673` but are redundant. If you enable this error code, mypy will generate an error if there is a redundant ``Self`` type. @@ -108,7 +108,7 @@ Example: from typing import Self class C: - # Error: Redundant "Self" annotation for the first method argument + # Error: Redundant "Self" annotation for the first method parameter def copy(self: Self) -> Self: return type(self)() diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index c157200352562..0785532c832fa 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -1728,13 +1728,13 @@ class C: from typing import Self, Type class C: - def copy(self: Self) -> Self: # E: Redundant "Self" annotation for the first method argument + def copy(self: Self) -> Self: # E: Redundant "Self" annotation for the first method parameter d: Defer class Defer: ... return self @classmethod - def g(cls: Type[Self]) -> Self: # E: Redundant "Self" annotation for the first method argument + def g(cls: Type[Self]) -> Self: # E: Redundant "Self" annotation for the first method parameter d: DeferAgain class DeferAgain: ... return cls() @@ -1746,13 +1746,13 @@ class C: from typing import Self class C: - def copy(self: Self) -> Self: # E: Redundant "Self" annotation for the first method argument + def copy(self: Self) -> Self: # E: Redundant "Self" annotation for the first method parameter d: Defer class Defer: ... return self @classmethod - def g(cls: type[Self]) -> Self: # E: Redundant "Self" annotation for the first method argument + def g(cls: type[Self]) -> Self: # E: Redundant "Self" annotation for the first method parameter d: DeferAgain class DeferAgain: ... return cls()