From b3f72d675bac9eb8921c4752330a6141063cd73d Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 28 Sep 2026 16:52:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(ctx):=20=E6=96=B9=E6=B3=95=E4=BD=93?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E5=A4=B1=E8=B4=A5=E8=B7=AF=E5=BE=84=E4=B9=9F?= =?UTF-8?q?=E5=A4=8D=E4=BD=8D=E3=80=8C=E5=BD=93=E5=89=8D=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E3=80=8D=E4=B8=8A=E4=B8=8B=E6=96=87=EF=BC=8C=E4=BF=AE=20self?= =?UTF-8?q?=20=E8=A2=AB=E6=8C=89=E5=86=85=E5=B1=82=E7=89=B9=E5=8C=96?= =?UTF-8?q?=E7=B1=BB=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象:编译 ExprGenFstr.translate_joined_str 时 self.Gen 被按 list[cfc4ca8da95a30e1.AST*] 解析 → 属性在类中找不到(连带错误)。 链路:parts.get(pi) 触发泛型特化按需补全(HandlesExprCall._try_complete_generic_specialization)→ 内层 list[...] 方法发射时 _EmitFunctionLlvm 先置 _CurrentCpythonObjectClass = 内层类(HandlesFunctions:1978)→ 方法体编译失败只 re-raise,末尾的类名/var_struct_class 复位被跳过 → 上层调用点**吞掉**该异常继续编译外层方法,于是外层 self.X 全按内层类解析、后续指令也会误插进内层函数的块。 两处修复:① _try_complete_generic_specialization 的 except 里同时复位 Gen.builder/func 与 _CurrentCpythonObjectClass/Gen._current_class_name(该点会吞异常,必须自己收尾);② _EmitFunctionLlvm 的失败路径在 re-raise 前复位 Gen._current_class_name / _CurrentCpythonObjectClass / var_struct_class / global_struct_class(对所有吞异常的调用点都成立)。 --- lib/core/Handles/HandlesExprCall.py | 16 ++++++++++++++++ lib/core/Handles/HandlesFunctions.py | 12 ++++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index c6b72dd..e4fe8a3 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -2894,6 +2894,18 @@ class ExprCallHandle(BaseHandle): # 不预先标记:_specialize_generic_class 内部缓存逻辑会检测 # cached_declare_only=True 且 declare_only=False,自动补发方法体 # 并更新缓存为 (spec_name, False)。预注册机制(L117)防止递归。 + # + # 上下文快照:本函数**吞掉**特化异常、让外层方法继续编译,故必须在失败时把 + # 编译器上下文复位——`_EmitFunctionLlvm` 的类名/构建器恢复只在**成功路径** + # 执行(失败路径直接 re-raise),异常穿过多层后 `Gen.builder/func` 与 + # `_CurrentCpythonObjectClass` 会停在内层特化方法的中间状态:外层方法随后 + # 的 `self.X` 被按内层类解析(ExprGenFstr.vp 的 `self.Gen` 被按 + # `list[cfc4ca8da95a30e1.AST*]` 解析 → "属性 'Gen' 在类中找不到"的连带错误), + # 且后续指令会误插进内层函数的块。 + _saved_builder: object = Gen.builder + _saved_func: object = Gen.func + _saved_cpython_class: str | None = getattr(self.Trans, '_CurrentCpythonObjectClass', None) + _saved_class_name: object = getattr(Gen, '_current_class_name', None) try: self.Trans.ClassHandler._specialize_generic_class( base_name, cached_type_args, Gen, @@ -2902,6 +2914,10 @@ class ExprCallHandle(BaseHandle): except Exception: # 失败时恢复 declare_only 标记,避免后续调用跳过补发 Gen._generic_class_specializations[spec_key] = (cached_name, True) + Gen.builder = _saved_builder + Gen.func = _saved_func + self.Trans._CurrentCpythonObjectClass = _saved_cpython_class + Gen._current_class_name = _saved_class_name def _compute_field_byte_offset(self, Gen: LlvmGeneratorMixin, ClassName: str, field_name: str) -> int | None: """计算字段在 struct 中的字节偏移(按 LLVM 布局含对齐)。 diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index 13f5ca2..8f67ebf 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -2086,6 +2086,18 @@ class FunctionHandle(BaseHandle): Gen.builder.ret_void() except Exception: pass + # 失败路径也要复位「当前方法」上下文(成功路径的复位在函数末尾,异常 + # 直接 re-raise 会跳过它)。上层有吞掉异常的调用点(如泛型特化按需补全 + # _try_complete_generic_specialization、类按需实例化),它们让外层方法 + # 继续编译;若此时 _CurrentCpythonObjectClass / var_struct_class 仍指向 + # 内层特化类,外层方法的 `self.X` 会被按内层类解析(典型现象: + # ExprGenFstr.translate_joined_str 的 `self.Gen` 被按 + # `list[cfc4ca8da95a30e1.AST*]` 解析 → "属性 'Gen' 在类中找不到")。 + Gen._current_class_name = _saved_class_name + self.Trans._CurrentCpythonObjectClass = saved_cpython_class + Gen.var_struct_class = saved_var_struct_class + if hasattr(Gen, 'global_struct_class'): + Gen.global_struct_class = saved_global_struct_class raise if not Gen.builder.block.is_terminated: if 'naked' in fn_attrs: