From 0fa3184fd7e87fb4cbf433eb90cd9986297ddb8d Mon Sep 17 00:00:00 2001 From: Yevhenii Bilozor <153777868+neopexrl@users.noreply.github.com> Date: Sun, 26 Oct 2025 17:31:29 +0100 Subject: [PATCH 1/2] Enhance type resolution for instance variables Added logic to resolve types for instance variables and handle partial types. --- mypy/checker.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/mypy/checker.py b/mypy/checker.py index 2dd7f10e6f35..d0742cbc4512 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -3313,6 +3313,33 @@ def check_assignment( rvalue_type, lvalue_type, infer_lvalue_type = self.check_member_assignment( lvalue, instance_type, lvalue_type, rvalue, context=rvalue ) + ## --PATCH-- (ISSUE №19996 --INTERNAL ERROR with allow_redefinition_new and undeclared instance variables) + proper_rvalue_type = get_proper_type(rvalue_type) + resolved_type = None + + def can_resolve_partial(lvalue_type, proper_rvalue_type): + return lvalue_type.type is None and not isinstance(proper_rvalue_type, NoneType) + + def set_node_type(lvalue, typ): + if getattr(lvalue, "node", None) and hasattr(lvalue.node, "type"): + lvalue.node.type = typ + + if isinstance(lvalue_type, PartialType) and can_resolve_partial(lvalue_type, proper_rvalue_type): + resolved_type = make_simplified_union([proper_rvalue_type, NoneType()]) + elif lvalue_type.type is not None and isinstance(proper_rvalue_type, Instance): + if rvalue_type.type == lvalue_type.type: + resolved_type = rvalue_type + + if resolved_type is not None: + lvalue_type = resolved_type + set_node_type(lvalue, resolved_type) + else: + self.fail( + f"Cannot resolve type for instance variable '{lvalue.name}', please annotate", + lvalue, + ) + return + else: # Hacky special case for assigning a literal None # to a variable defined in a previous if From d0328183c58e62570a6eb64ae0b28a36507546d5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 26 Oct 2025 16:35:40 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/checker.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index d0742cbc4512..b6ceb8e5849e 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -3318,13 +3318,17 @@ def check_assignment( resolved_type = None def can_resolve_partial(lvalue_type, proper_rvalue_type): - return lvalue_type.type is None and not isinstance(proper_rvalue_type, NoneType) + return lvalue_type.type is None and not isinstance( + proper_rvalue_type, NoneType + ) def set_node_type(lvalue, typ): if getattr(lvalue, "node", None) and hasattr(lvalue.node, "type"): lvalue.node.type = typ - if isinstance(lvalue_type, PartialType) and can_resolve_partial(lvalue_type, proper_rvalue_type): + if isinstance(lvalue_type, PartialType) and can_resolve_partial( + lvalue_type, proper_rvalue_type + ): resolved_type = make_simplified_union([proper_rvalue_type, NoneType()]) elif lvalue_type.type is not None and isinstance(proper_rvalue_type, Instance): if rvalue_type.type == lvalue_type.type: @@ -3339,7 +3343,7 @@ def set_node_type(lvalue, typ): lvalue, ) return - + else: # Hacky special case for assigning a literal None # to a variable defined in a previous if