fix(Handles/PythonParser/DeclarationGenerator): 补齐 3 处"调用了不存在成员"的死路径 + 1 处被 hasattr 掩盖的静默降级

类别:a(编译器缺陷)

现场:翻译 TransPyV/App/lib/core/Gen/Call/CallGenLeafKit.vp 时终止编译
  RuntimeError: 翻译 ... 失败: 'ClassHandle' object has no attribute '_PreRegisterClassMembers'
  (FuncGen.py:965 有调用,方法全仓无定义)

按要求做了全仓静态扫描(ast:属性访问 vs 全仓属性定义;symtable:未定义全局名),共修 4 处:

1) HandlesClassDef.ClassHandle._PreRegisterClassMembers(缺失 → 实现)
   调用点:FuncGen._get_member_offset 的"struct body 已存在、class_members[类名] 为空"分支
   —— 该类的成员表在本次翻译里从未被收集,而按名定位字段槽位必须有表。
   实现与既有两处成员收集段同源(CollectAnnAssignMember → 追加 (名, 类型)),但**只做收集**:
     · 不展平继承前缀(调用方随后经 _member_base → EnsureClassMembersFlattened 补齐);
     · 不调用 _generate_structs(body 已存在,重入 set_body 会把残缺布局永久固化);
     · 只追加尚无同名的条目(幂等,重复命中不会把表撑长)。
   跳过 __provides__/__requires__/__require_must__(非布局槽位),并登记字段限定符。

2) HandlesExprAttr.ExprAttrHandle._load_bitfield_member(缺失 → 实现)
   读路径 7 处调用(位域分支)全部指向不存在的方法 ⇒ 任何位域字段读取都会 AttributeError。
   实现与 HandlesAssign._store_bitfield_member 严格对称:位域类 body 只有一个 storage 槽
   (elements[0]),字段位置由 class_member_bitoffsets/bitfields/signeds 表达,
   读取 = `(storage >> 位偏移) & ((1<<位宽)-1)`,有符号字段再做符号扩展;
   缺位偏移 / 位宽 ≤ 0 / struct 未具化 / storage 非整数一律 fail-fast(不返回 i32 兜底)。

3) PythonParserMixin 的 __set_default__ 分支(幽灵调用 → 明确报未支持)
   原调用 self._handle_set_default_in_parse(...) 全仓无定义。核实:该注解在 TransPyC/lib 内
   无任何消费端(只有 t.py 的定义与 StubGen/Converter 的"剥离该调用保留类型"),
   includes 全仓亦无源使用 ⇒ 不静默丢弃源码语义,改为 NotImplementedError 明确报"未支持"。

4) DeclarationGenerator._llvm_type_size_str 的数组分支(静默降级 → 修好)
   原写作 `self._ARR_TYPE_RE`(少一个 A)并以 hasattr 守卫 —— 该属性全仓从未定义 ⇒ 守卫恒假
   ⇒ 数组字段一律落到"未知类型 → 8",与 docstring 声明的"_EmitREnumLlvm 尺寸口径对齐"不符。
   改用本类已定义的 _ARRAY_TYPE_RE,并去掉守卫(属性再丢失应当响亮失败)。

核验:compileall 全 lib 通过;属性扫描剩余 26 条全为仓外对象(logging / vast AST /
llvmlite Value·Instruction·IRBuilder / 内置 Exception.args / __class__ / __dict__);
symtable 未定义全局名仅 __file__(运行时内置)。未新增/放宽任何 fail-fast。
This commit is contained in:
TermiNexus committed 2026-09-30 18:23:25 +08:00
1 parent 52ea21f082
commit c2f53852ee
4 files changed
+134 -2

No files matched your search

+13 -1
View File
@@ -225,7 +225,19 @@ class PythonParserMixin:
# 检查是否有 __set_default__ 初始化
if AnnotationContainsName(NextNode.annotation, '__set_default__'):
self._handle_set_default_in_parse(ClassKey, TargetName, ClassName, NextNode)
# 【fail-fast,替代**不存在的** _handle_set_default_in_parse
# (2026-09-30)】原调用指向的方法全仓无定义 ⇒ 一旦命中即
# `AttributeError`(与 ClassHandle._PreRegisterClassMembers
# 同族:死调用,非"未走到")。
# 现状核实:`__set_default__` 在 TransPyC/lib 内只有
# t.py 的定义与 StubGen/Converter 的"剥离该调用、保留类型",
# **没有任何消费端**读取它的 kwargs;includes 全仓亦无源使用。
# 因此这里既不调用幽灵方法,也不静默丢弃源码语义:明确报未支持,
# 语义(字段默认值如何落到 class_member_defaults)确定后再实现。
raise NotImplementedError(
f"[未支持] 注解里的 __set_default__(...):类 '{ClassKey}' "
f"字段 '{TargetName}'(TPC 翻译路径无消费端;"
f"拒绝静默丢弃该默认值语义)")
j += 1
continue
# 再处理旧格式:xxx: t.CTypedef = xxx 或 xxx: t.CPtr = xxx