fix(tpv): InternSpec 表满改为 fatal(不再返回 None 静默丢类型信息)

表容量超限原实现只是 return None,但注释声称 fail-fast:None 会沿调用链传到 entry.Spec,条目静默失去类型信息(_entry_spec_unsigned 恒返回 0 ⇒ zext/sext 方向取错),属静默数据损坏。

改为 GenApi.fatal_error(InternalCompilerError);TypeSpec 与 GenApi 互为依赖(GenApi→GenTypes→TypeSpec),故函数内懒 import 破环(同 CallGenLib.vp:220 既有模式)。仅当 fatal_error 无 gen 通道时退化为不驻留返回完整实例,守住不返回 None 的底线。SPEC_INTERN_MAX 仍为 8192(当前未触发)。
This commit is contained in:
TermiNexus committed 2026-09-12 10:21:27 +08:00
1 parent 1039969f69
commit 7fbf69ae63
1 file changed
+17 -4
+17 -4
View File
@@ -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