TermiNexus
2e7bac1816
fix(HandlesImports/HandlesClassDef): 剥掉"祖先块前缀的陈旧半截副本",消除成员表重名条目
类别:a(编译器缺陷)
现场(用户构建日志):
WARN[StructGen]: [结构体布局] 类 'ClassGenDef' 的成员表含**重名条目**:
表 50 项 / 去重 42 项,现有 body 42 槽恰等于「去重名数 + vtable」
判据(磁盘实证 + 结构推导,非猜测):
· ClassGenDef 自身 **0** 个字段(全是方法),父类 ClassGenBase 恰 **42** 个字段;
temp / output 两份 stub 的 ClassGenDef body 都是 **42** 槽,且槽序 = ClassGenBase
的字段声明序 ⇒ body 正确、**表多出 8 条**(50 = 42 + 8)。
· ClassGenBase 自己的 Phase-1 stub 就是 42 槽(不是 8)⇒ 多出的 8 条并非"父类 stub 短",
只能来自**内存里父类表尚未收集完就被展平**(写入了半截祖先块 Block[:k],k=8)——
正是 PrependInheritedBlock 文档里写明的"已知残留"。
· 重名条目不是布局槽位(见 FuncGen._get_member_offset 的重名段),却让
_member_base 的 _Delta = 42 - 50 = -8 走进类型校准,并让回退路径的
base + 表内下标 整体偏斜(同族现场:MatchCase / TypeGenResolve 的偏移算错)。
修复(判据全部为正向事实,且与插入方向无关):
· 新增 NormalizeAncestralCopies(Table, Block, InsertAtHead) -> (新表, 是否已含完整块):
① 完整块在**头**、尾部挂前缀副本 ⇒ 剥尾(副本是被后来的整块前置推过去的);
② 完整块在**尾**、头部挂前缀副本 ⇒ 剥头(副本先写入、整块随后追加);
③ 完整块尚未出现 ⇒ 剥插入边(仅当这些名字已另有正本,见下)。
剥掉的每一项在(表里已有的 / 随后插入的)完整块里同名同型 ⇒ **不丢布局信息**,
与 PrependInheritedBlock 性质①"不删块内条目"不冲突(剥的是副本)。
第一版曾"两端都剥",离线冒烟立刻暴露会把**正本**当副本剥掉([A,B,C,D,A,B] →
[C,D,A,B],再前置整块反而多出 C,D 两份)⇒ 改为先定位完整块在哪一端、再剥另一端。
· TrimStalePrefixCopy 判据:插入边连续游程与 Block[:j] 逐项同 name 同 IR 类型,
1 ≤ j < len(Block),且这 j 个名字在表里**各另有一份**(计数 ≥ 2)——最后一条把
"子类自有字段恰好与祖先块前缀同名同型"的误判排除。
· 两个插入点(HandlesImports.PrependInheritedBlock 前置 / HandlesClassDef 展平追加)
统一走该函数,判据对称;真正剥除时各留一条 WARN(含条数与前后表长)。
· PrependInheritedBlock 原有两条幂等提前返回("表头等于块" / InheritedBlockAlreadyPresent)
合并为 _HasFull 一条(语义等价),并更新其"已知残留"段落。
· StructGen 的重名 WARN 追加**逐条明细**(名@表内下标):单看"表 50 / 去重 42"无法区分
"祖先块前缀的陈旧副本"与"两条收集路径各登记一次"(两种成因修法完全不同)。
核验:py_compile + compileall 全 lib 通过;离线冒烟(调用真实函数,8 组用例 × 两个插入方向):
①/② 均 6→4 正确剥除,"无重复 / 带自有字段 / 类型不同 / 无正本 / 空表"均不改动。
未放宽任何 fail-fast。
2026-09-30 18:41:24 +08:00
..
2026-08-21 12:36:00 +08:00
2026-09-30 15:14:31 +08:00
2026-08-17 09:36:38 +08:00
2026-09-30 16:16:38 +08:00
2026-09-30 09:53:41 +08:00
2026-09-27 00:19:44 +08:00
2026-09-30 14:45:55 +08:00
2026-09-26 19:27:22 +08:00
2026-09-30 18:41:24 +08:00
2026-08-17 09:36:38 +08:00
2026-09-30 09:53:41 +08:00
2026-09-29 13:00:11 +08:00
2026-09-30 18:23:25 +08:00
2026-09-30 16:16:38 +08:00
2026-09-30 17:00:50 +08:00
2026-09-11 22:47:21 +08:00
2026-09-30 09:53:41 +08:00
2026-09-27 15:16:08 +08:00
2026-09-26 19:27:22 +08:00
2026-09-28 13:57:04 +08:00
2026-09-30 09:53:41 +08:00
2026-08-17 09:36:38 +08:00
2026-09-30 18:41:24 +08:00
2026-09-30 14:42:56 +08:00
2026-08-17 09:36:38 +08:00
2026-09-28 15:10:39 +08:00
2026-09-26 19:27:22 +08:00
2026-08-17 09:36:38 +08:00
2026-09-29 17:35:56 +08:00
2026-08-03 02:00:49 +08:00
2026-09-26 19:27:22 +08:00