chore(诊断): len 分派 fail-fast 追加成员槽来源明细(项数/base/下标/名序/布局槽/实例同源判定)
类别:b(机制漏豁免)/诊断增强,不改变任何成功路径。 现场:编译 StmtGenDeclMixin.vp:242 `len(mcc_pre.children)` 报 [fast-fail] len(mcc_pre.children) 分派 'list[10f3f43ddd447eec.AST*].__len__' 失败: 类='MatchCase' 偏移=6 接收者类型=i32 静态可查到的**正确**布局(temp/8c9751aec486f41c.stub.ll 实测 10 槽): [0]i8*(vtable) [1]AST*(parent) [2]MemManager*(pool) [3..6]i32(lineno/col_offset/ end_lineno/end_col_offset) [7]list[AST*]*(children) [8]AST*(pattern) [9]AST*(guard) 声明侧(.vpi):`class AST` 7 字段 + `class MatchCase(AST)` 2 字段 ⇒ 表 9 项、 children 表内下标 6 ⇒ 正确 base=1 ⇒ 正确偏移 7。而失败现场是 6 ⇒ **base 被算成 0** (表 10 项触发 `_Delta==0 ⇒ base=0`,或取值处实例与类键实例不同源)—— 只看 `偏移=6` 无法区分,故把两侧读数打进报文。 - `AssignHandle._DescribeMemberSlot` 增可选 `StructHint`:base 与失败现场**同源** (不传时行为与改前逐字一致)。 - `HandlesExprBuiltin._HandleLenLlvm` 的 len 分派失败路径(仅该路径)追加上述明细: `class_members[类] 项数/base/下标/声明槽类型`、**完整名序**、 `布局 struct name+元素数+elements[offset]`、`structs[类] 与布局是否同一对象`。 明细生成失败只追加一行说明,绝不掩盖原始 TypeError。 静态核验:py_compile 通过;全仓 symtable 未定义名扫描 0 条。
This commit is contained in:
1 parent
9afd6a45ed
commit
cad70fa8f3
2 files changed
+18
-3
No files matched your search
@@ -1612,7 +1612,8 @@ class AssignHandle(BaseHandle):
|
||||
f"或把基座显式转为 t.CPtr(无类型指针)后按 8 字节指针语义写入。{SrcInfo}")
|
||||
|
||||
def _DescribeMemberSlot(self, Gen: "Translator.LlvmGen", ClassName: str | None,
|
||||
FieldName: str, Offset: int, SelfPtr: ir.Value) -> str:
|
||||
FieldName: str, Offset: int, SelfPtr: ir.Value,
|
||||
StructHint: Any = None) -> str:
|
||||
"""`self.字段 = 值` 成员槽写入失败的**来源明细**(供 fail-fast 报文引用)。
|
||||
|
||||
槽类型有两个**互相独立**的来源,必须自洽:
|
||||
@@ -1622,11 +1623,15 @@ class AssignHandle(BaseHandle):
|
||||
现场:Generator.ExprGenConst 声明 `%"...ExprGenConst"*` 却落到 `i8**`。
|
||||
此处把两侧数据逐项列出,直接判定是声明侧退化还是布局侧退化(含 structs
|
||||
键空间大小与"是否同一对象",用于识别裸名 / sha1 全名双条目)。
|
||||
|
||||
`StructHint`(可选):调用方实际 GEP 用的那个 struct 实例。偏移基址必须与**那份
|
||||
布局**同源(见 FuncGen._member_base 的 hint 说明)——传入时本报文报出的 base /
|
||||
下标才与失败现场一致;不传时行为与改前逐字一致(回落到类键实例)。
|
||||
"""
|
||||
Lines: list[str] = []
|
||||
try:
|
||||
Members: list = Gen.class_members.get(ClassName) or []
|
||||
Base: int = Gen._member_base(ClassName)
|
||||
Base: int = Gen._member_base(ClassName, StructHint)
|
||||
Idx: int = Offset - Base
|
||||
Declared: Any = Members[Idx][1] if 0 <= Idx < len(Members) else None
|
||||
Lines.append(
|
||||
|
||||
@@ -696,10 +696,20 @@ class ExprBuiltinHandle(BaseHandle):
|
||||
try:
|
||||
result = self.Trans.ExprUtils._try_operator_overLoad(field_cls, '__len__', list_val, Gen)
|
||||
except TypeError as _e_len:
|
||||
# 来源明细(声明侧 class_members 名序/项数 vs 布局侧 elements)
|
||||
# 追加进报文:本处失败的本质是"偏移算错",只看 偏移=6 无法区分
|
||||
# 是"表多一项(→ base 被 delta==0 判 0)"还是"取值处实例与类键实例
|
||||
# 不同源"。判据/读数见 AssignHandle._DescribeMemberSlot。
|
||||
_extra_len: str = ''
|
||||
try:
|
||||
_extra_len = self.Trans.AssignHandler._DescribeMemberSlot(
|
||||
Gen, bare_cls, attr_name, offset, self_ptr, _STl2)
|
||||
except Exception as _ea:
|
||||
_extra_len = f"\n (来源明细生成失败: {type(_ea).__name__}: {_ea})"
|
||||
raise TypeError(
|
||||
f"[fast-fail] len({obj_name}.{attr_name}) 分派 '{field_cls}.__len__' 失败:"
|
||||
f"类='{bare_cls}' 偏移={offset} 接收者类型={list_val.type};"
|
||||
f"(成员偏移与 struct 布局不一致)原错误: {_e_len}")
|
||||
f"(成员偏移与 struct 布局不一致)原错误: {_e_len}{_extra_len}")
|
||||
if result is not None:
|
||||
return result
|
||||
val = self.HandleExprLlvm(arg_node)
|
||||
|
||||
Reference in new issue
Block a user