diff --git a/App/lib/core/Gen/Type/TypeSpec.vp b/App/lib/core/Gen/Type/TypeSpec.vp index 3dd6262..3151b48 100644 --- a/App/lib/core/Gen/Type/TypeSpec.vp +++ b/App/lib/core/Gen/Type/TypeSpec.vp @@ -810,8 +810,9 @@ def _text_to_func(text: str, depth: int) -> TypeSpec | t.CPtr: # ============================================================ # InternSpec - 规范化驻留:同键只保留一份,返回驻留后的实例 -# 键 = SpecToText;**表容量**超限 → 返回 None(fail-fast,绝不静默丢弃); -# **键文本**装不下 SPEC_TEXT_MAX → 保留实例但放弃去重(绝不写入截断键)。 +# 键 = SpecToText;**表容量**超限 → fatal_error(绝不返回 None:那会让调用方条目 +# 静默丢失类型信息);**键文本**装不下 SPEC_TEXT_MAX → 保留实例但放弃去重 +# (绝不写入截断键)。 # ============================================================ def InternSpec(arena: TypeSpecArena | t.CPtr, sp: TypeSpec | t.CPtr) -> TypeSpec | t.CPtr: @@ -840,9 +841,21 @@ def InternSpec(arena: TypeSpecArena | t.CPtr, return None return (TypeSpec | t.CPtr)(t.CVoid(uint64(slot_e[0]), t.CPtr)) i += 1 - # 未命中:追加(容量检查 → fail-fast) + # 未命中:追加。**表满 = fail-fast**(Debugger/_Type.md D14 风险 2): + # 不能返回 None —— 调用链会把 None 一路传到 entry.Spec,条目**静默失去类型信息** + # (如 _entry_spec_unsigned 恒返回 0 ⇒ zext/sext 方向取错),属静默数据损坏, + # 与「不兜底 / fail-fast」原则直接冲突(原注释声称 fail-fast,实现却只返回 None)。 + # 破环:TypeSpec 与 GenApi 互为依赖(GenApi→GenTypes→TypeSpec),故**函数内懒 import** + # (同 CallGenLib.vp:220「函数内懒 import 规避顶层循环依赖」的既有模式)。 if arena.Count >= arena.Cap: - return None + import lib.core.Gen.GenApi as GenApi + GenApi.fatal_error( + None, + f"TypeSpec 驻留表已满(上限 {arena.Cap} 条),无法登记新类型", + "InternalCompilerError") + # 仅在 fatal_error 无 gen 通道(no-op)时可达:退化为「不驻留但返回完整实例」, + # 守住"不返回 None"这一底线 —— 宁失去同型共享,也不让条目静默丢类型。 + return sp dst_key: str = _spec_key_at(arena.Keys, arena.Count) if dst_key is None: return None