diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py index d37723f..69ac04c 100644 --- a/lib/Projectrans/Phase2Translator.py +++ b/lib/Projectrans/Phase2Translator.py @@ -2055,11 +2055,18 @@ class Phase2Translator: error_stack = getattr(trans.translator, '_ErrorStack', []) if error_stack: self._last_ErrorStack = error_stack - chain_lines = [] - for entry in reversed(error_stack): - if len(entry) >= 3: - exc_msg, line_info = entry[1], entry[2] + # 语句栈渲染:error_stack 按"由内向外"入栈(内层语句先 append), + # 这里反转为"外层 → 内层"的调用路径;**异常消息只在最内层印一次**, + # 其余帧只印位置——否则同一段长 fail-fast 报文会被每个帧重复一遍 + # (旧格式把消息贴在每一帧后面,输出里同一句话出现 N 次,不可读)。 + entries: list = [entry for entry in error_stack if len(entry) >= 3] + chain_lines: list[str] = [] + for chain_idx, entry in enumerate(reversed(entries)): + exc_msg, line_info = entry[1], entry[2] + if chain_idx == len(entries) - 1: chain_lines.append(" %s\n %s" % (line_info, exc_msg)) + else: + chain_lines.append(" %s" % (line_info,)) if chain_lines: enriched = str(e) + "\n" + "\n".join(chain_lines) raise type(e)(enriched) from e diff --git a/lib/core/LLVMCG/FuncGen.py b/lib/core/LLVMCG/FuncGen.py index 6ff5828..51fae57 100644 --- a/lib/core/LLVMCG/FuncGen.py +++ b/lib/core/LLVMCG/FuncGen.py @@ -19,6 +19,24 @@ class FailFastError(Exception): """ +class MemberLookupFailFast(KeyError): + """成员偏移查找失败的 fail-fast 异常(**继承 KeyError** 以保持既有兜底点可用)。 + + 为什么继承 KeyError:本仓有两处 `except KeyError` 把 `_get_member_offset` 的 + 失败当作"该字段类型未知"继续回查(HandlesExprAttr 的字段类型三级回退),改成 + 其它异常类型会把这些兜底点击穿。 + + 为什么重写 `__str__`:KeyError 的默认 `__str__` 是 `repr(消息)` —— 会在报文两端 + 加引号、并把换行/制表转义成字面 `\\n`,多行 fail-fast 报文(含"源代码 (文件, 行号): + 行号 | 源码")因此彻底不可读。这里原样返回裸消息,与 FailFastError 的观感一致。 + """ + + def __str__(self) -> str: + if self.args and isinstance(self.args[0], str): + return self.args[0] + return super().__str__() + + class FuncGenMixin: def setup_from_symbol_table(self, SymbolTable: Any) -> None: @@ -737,12 +755,10 @@ class FuncGenMixin: if isinstance(_st_diag, ir.IdentifiedStructType): _struct_diag = f"{len(_st_diag.elements)} elems" if _st_diag.elements is not None else 'opaque' _member_names_diag: list = [n for n, _ in _members_diag][:16] - try: - import traceback as _tb - _tb.print_stack(file=sys.stderr) - except Exception: - pass - raise KeyError( + # 异常类型:MemberLookupFailFast(KeyError 子类 + 裸消息 __str__)—— + # 既保留 `except KeyError` 兜底点,又让报文不再被 repr 成"带引号 + \n 转义" + # 的不可读形式(原有 traceback.print_stack 调试转储一并移除,保持输出干净)。 + raise MemberLookupFailFast( f"[fast-fail] 属性 '{field_name}' 在类 '{ClassName}' 中找不到" f"(class_members={len(_members_diag)} 个: {_member_names_diag}, struct={_struct_diag})" )