fix(ctx): 方法体编译失败路径也复位「当前方法」上下文,修 self 被按内层特化类解析
现象:编译 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(对所有吞异常的调用点都成立)。
This commit is contained in:
1 parent
96d8e13c5a
commit
b3f72d675b
2 files changed
+28
No files matched your search
@@ -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 布局含对齐)。
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user