From 44e67b68d67365e40f921988ce4b2be6defc2a2f Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Fri, 20 Feb 2026 23:13:08 +0000 Subject: [PATCH] Try allowing redefinitions for function arguments --- mypy/cache.py | 2 +- mypy/checker.py | 2 +- mypy/fastparse.py | 1 + mypy/nodes.py | 12 ++++-------- test-data/unit/check-redefine2.test | 4 ++-- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/mypy/cache.py b/mypy/cache.py index 9e3b39ffaaa40..80112e94c7f3b 100644 --- a/mypy/cache.py +++ b/mypy/cache.py @@ -69,7 +69,7 @@ from mypy_extensions import u8 # High-level cache layout format -CACHE_VERSION: Final = 5 +CACHE_VERSION: Final = 6 # Type used internally to represent errors: # (path, line, column, end_line, end_column, severity, message, code) diff --git a/mypy/checker.py b/mypy/checker.py index ea3e9f072afc8..784ec3939ad77 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4421,7 +4421,7 @@ def check_lvalue( if ( self.options.allow_redefinition_new and isinstance(lvalue.node, Var) - and lvalue.node.is_inferred + and (lvalue.node.is_inferred or lvalue.node.is_argument) ): inferred = lvalue.node self.store_type(lvalue, lvalue_type) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 701e449f8f338..c68d1dfc53b62 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -1145,6 +1145,7 @@ def make_argument( var = Var(arg.arg, arg_type) var.is_inferred = False + var.is_argument = True argument = Argument(var, arg_type, self.visit(default), kind, pos_only) argument.set_line(arg.lineno, arg.col_offset, arg.end_lineno, arg.end_col_offset) return argument diff --git a/mypy/nodes.py b/mypy/nodes.py index 4c238592f9927..0b31f20267053 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -1292,6 +1292,7 @@ class Var(SymbolNode): "has_explicit_value", "allow_incompatible_override", "invalid_partial_type", + "is_argument", ) __match_args__ = ("name", "type", "final_value") @@ -1351,6 +1352,8 @@ def __init__(self, name: str, type: mypy.types.Type | None = None) -> None: # If True, this means we didn't manage to infer full type and fall back to # something like list[Any]. We may decide to not use such types as context. self.invalid_partial_type = False + # Is it a variable symbol for a function argument? + self.is_argument = False @property def name(self) -> str: @@ -1414,8 +1417,6 @@ def write(self, data: WriteBuffer) -> None: write_flags( data, [ - self.is_self, - self.is_cls, self.is_initialized_in_class, self.is_staticmethod, self.is_classmethod, @@ -1453,8 +1454,6 @@ def read(cls, data: ReadBuffer) -> Var: v.setter_type = setter_type v._fullname = read_str(data) ( - v.is_self, - v.is_cls, v.is_initialized_in_class, v.is_staticmethod, v.is_classmethod, @@ -1474,7 +1473,7 @@ def read(cls, data: ReadBuffer) -> Var: v.from_module_getattr, v.has_explicit_value, v.allow_incompatible_override, - ) = read_flags(data, num_flags=21) + ) = read_flags(data, num_flags=19) tag = read_tag(data) if tag == LITERAL_COMPLEX: v.final_value = complex(read_float_bare(data), read_float_bare(data)) @@ -2368,9 +2367,6 @@ def __init__( analyzed: Expression | None = None, ) -> None: super().__init__() - if not arg_names: - arg_names = [None] * len(args) - self.callee = callee self.args = args self.arg_kinds = arg_kinds # ARG_ constants diff --git a/test-data/unit/check-redefine2.test b/test-data/unit/check-redefine2.test index 6e9441151c935..de6b216e471e5 100644 --- a/test-data/unit/check-redefine2.test +++ b/test-data/unit/check-redefine2.test @@ -562,8 +562,8 @@ def f2() -> None: def f3(x) -> None: if int(): x = 0 - reveal_type(x) # N: Revealed type is "Any" - reveal_type(x) # N: Revealed type is "Any" + reveal_type(x) # N: Revealed type is "builtins.int" + reveal_type(x) # N: Revealed type is "Any | builtins.int" [case tetNewRedefineDel] # flags: --allow-redefinition-new --local-partial-types