chore(诊断): AnnAssign RHS 为 接收者链.方法(...) 时补接收者基址诊断 + 最近一次属性读取失败原因

【b 机制漏豁免 —— 只加取证,不改任何判定/IR】现场:翻译
TransPyV/App/lib/core/Gen/Class/ClassGenEnum.vp:59
`ty: llvmlite.LLVMType* = self.Gen.TypeGenResolve.resolve_typedef_or_map(pool, at.attr,
imported_modules, from_imports)` 报"(Call 形态)编译期求值为空"。

已按代码**排除**出来的事实(写进注释,供后续不再重复排查):
  · 方法声明缺失会在 HandlesExprCall._HandleMethodCallLlvm 内 raise
    "Undefined method …",不会走到该 fail-fast;
  · 该函数在"方法已找到"之后不会返回 None,唯一的 None 出口是
    `ObjVal = HandleExprLlvm(Node.func.value)` 为假(L3335-3337)——
    即**接收者链 `self.Gen.TypeGenResolve` 自身求值为空**才是根因;
  · 但原报文的"基址诊断"只在 RHS 是 **Attribute** 时才打印(HandlesBase:784),
    Call 形态下接收者失败原因被丢弃 ⇒ 报错点与真因相隔数层。

修法(纯取证):HandlesBase 的通用 fail-fast 增 `elif Call(func=Attribute)` 分支,补三行:
  ① `被调者接收者诊断:` —— 复用 `_DescribeAttrBase(Gen, Node.func.value)`:接收者
     (如 `self.Gen`)的基座形态 / var_struct_class / alloca 类型 / 是否在 Gen.structs /
     class_members 项数与字段名单 / struct body 元素数 / 该字段计算偏移;
  ② `最近一次属性读取失败:` —— 回显 `Gen._LastAttrNone` 的 (类, 字段, 原因):Call 形态下
     无法用 (类, 字段) 与被报节点比对,故此处**无条件**回显(Attribute 形态仍保持
     "必须与被报节点一致"的原判据,避免旧记录误导);
  ③ `被调方法=… 已声明同名方法键(示前 4 / 共 N):` —— 区分"方法根本没声明"与
     "接收者读不出来"(后者才会命中本 fail-fast,但这一行让两者一眼可分)。

未验证:本提交只改诊断文本,行为不变;需再跑一次构建才能看到新增三行。
This commit is contained in:
TermiNexus committed 2026-09-30 14:45:55 +08:00
1 parent 00edd90c28
commit e5f044dd03
1 file changed
+28
+28
View File
@@ -783,6 +783,34 @@ class BaseHandle:
# 见 HandlesExprCall._RequireArgValue)。
if isinstance(Node, ast.Attribute):
msg += "\n│ 基址诊断: " + self._DescribeAttrBase(Gen, Node)
elif isinstance(Node, ast.Call) and isinstance(Node.func, ast.Attribute):
# 被调者形如 `接收者链.方法(...)`:整条 Call 求值为空的**唯一来源**是接收者链
# 先求值为空(HandlesExprCall._HandleMethodCallLlvm 里
# `ObjVal = HandleExprLlvm(Node.func.value)` 为假即 `return None`;
# 方法声明缺失会在同函数内 raise "Undefined method …",不会走到这里)。
# 行号只能指到整条调用,故把**接收者**的基址事实与最近一次属性读取失败原因
# 一并回显;Call 形态下无法用 (类, 字段) 与节点比对,该记录无条件回显。
try:
msg += "\n│ 被调者接收者诊断: " + self._DescribeAttrBase(Gen, Node.func.value)
except Exception as _e_d: # noqa: BLE001
msg += f"\n│ 被调者接收者诊断生成失败: {type(_e_d).__name__}: {_e_d}"
try:
_recC: Any = getattr(Gen, '_LastAttrNone', None)
if isinstance(_recC, tuple) and len(_recC) >= 3 and _recC[2]:
msg += (f"\n│ 最近一次属性读取失败: 类={_recC[0]!r} 字段={_recC[1]!r}"
f" 原因={_recC[2]}")
except Exception: # noqa: BLE001
pass
_mnC: str = getattr(Node.func, 'attr', '') or ''
_declC: list[str] = []
try:
for _fk in (getattr(Gen, 'functions', {}) or {}):
if _mnC and _fk.endswith(f'.{_mnC}'):
_declC.append(_fk)
except Exception: # noqa: BLE001
_declC = []
msg += (f"\n│ 被调方法={_mnC!r};已声明同名方法键(示前 4 / 共 {len(_declC)}): "
f"{_declC[:4]}")
_vlog().compile_error(msg, src_file, lineno, code_line)
sys.exit(1)