fix(type): 泛型实参归一先剥尾随星号,消除包前缀票名分裂

_norm_type_arg_name 规则 4 用 strchr('.') 切出 attr 时把尾随 '*' 一起带进了类名
('ast.ClassDef*' → attr='ClassDef*'),于是 _class_true_def_sha1 按名查不到
entry、真定义模块校正失效,留下包前缀:

  字段侧 ClassGenBase.vp:123 → list[1abcd5277fa442de.ClassDef*](无定义的幽灵名,
                              全部产物里只有 = type opaque,从无 = type {...})
  构造侧 ClassGenGeneric.vp:92 → list[e70bd9b4487d921d.ClassDef*]
  ⇒ ClassGenGeneric.vp:92 报「指针隐式转指针已禁止」。

TPC 侧名称域(SymbolUtils.ResolveTypeArgStr 的 BinOp 分支)本就是「先解析基类型 X,
再 AddPointerLayers 追加 '*'」→ {真定义sha}.X*,TPV 与之对齐。

新增规则 1.6:剥掉全部尾随 '*' → 递归归一基名 → 回贴同样多的 '*'。
i8** / int* / T* / 已带 SHA1 前缀的文本逐字不变。
This commit is contained in:
TermiNexus committed 2026-10-01 22:40:54 +08:00
1 parent 02b9429363
commit 3ccc37ca3f
1 file changed
+33
+33
View File
@@ -722,6 +722,39 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
string.strcat(g_out, g_arg2)
string.strcat(g_out, "]")
return g_out
# ---- 1.6 尾随指针星号:先归一基名,再回贴星号(2026-10-01)----
# parser 把源码 `X*` 展开为 `X | t.CPtr`,但**泛型实参文本**里的星号是原样
# 带进来的(如字段 `list[ast.ClassDef*]` 的实参段文本就是 "ast.ClassDef*")。
# 不剥离时规则 4 的 attr 会带上星号变成 "ClassDef*":
# ① `_class_true_def_sha1` 按名查不到 "ClassDef*" ⇒ 真定义模块校正失效 ⇒
# 留下**包前缀**(现场:ClassGenBase.vp:123 字段票名
# `list[1abcd5277fa442de.ClassDef*]`,而 ClassGenGeneric.vp:92 构造侧是
# `list[e70bd9b4487d921d.ClassDef*]` ⇒ TPV 报「指针隐式转指针已禁止」,
# 且该票名在全部产物里从未定义为实体结构体);
# ② 与 TPC 名称域不一致 —— SymbolUtils.ResolveTypeArgStr 的 BinOp 分支明确
# 规定 `X | t.CPtr` ≡ `rawptr[X]` ≡ `t.CPtr[X]` → `{sha}.X*`(先解析基
# 类型 X,再 AddPointerLayers 追加星号)。
# 故统一为:剥掉全部尾随 '*' → 递归归一基名 → 回贴同样多的 '*'。
# `i8**` / `int*` / `T*` / 已带 SHA1 前缀的文本都逐字不变(基名归一回原样)。
_st_n: int = 0
while seg_len > sizet(_st_n) and type_name[seg_len - sizet(_st_n) - 1] == '*':
_st_n += 1
if _st_n > 0:
_base_len_s: sizet = seg_len - sizet(_st_n)
_base_buf_s: str = pool.alloc(_base_len_s + 1)
if _base_buf_s is not None:
string.strncpy(_base_buf_s, type_name, _base_len_s)
_base_buf_s[_base_len_s] = '\0'
_base_n_s: str = self._norm_type_arg_name(pool, _base_buf_s, from_imports)
if _base_n_s is not None:
_out_s: str = _base_n_s
_si_s: int
for _si_s in range(_st_n):
_out_s = self._ptr_star_text(pool, _out_s)
if _out_s is None:
break
if _out_s is not None:
return _out_s
# ---- 2. 已规范化(SHA1 前缀)----
if self._is_sha1_prefixed(type_name) != 0:
return type_name