fix(transpyv): 裸类名归属补「符号名真源」(entry.Ty 的 {SHA1}.{类} 前缀)+ 取证日志

类别 a(编译器缺陷):_norm_type_arg_name 规则 5.5 判定裸类名归属只认三条证据——
struct 注册表的 ModuleSha1、ModuleClasses 登记表、以及"正在定义类"。Phase A-pre 没有
"类定义窗口"(CurDefModuleSha1=None),而 .vpi 注入的类条目常常 ModuleSha1 为空 ⇒
三条全落空 ⇒ 实参保留裸名,与后续(类已注册时)解析出的带前缀形式分裂成两个特化名
⇒ 被"非基本类型指针不可隐式转换"拦下。现场:includes/ast/base.vp:359
  _append_child(self.children, node, self.pool)
  源 %"…list[rawptr[AST]]"* → 目标 %"…list[rawptr<定义模块SHA1>.AST]"*

- 规则 5.5 新增证据 ④(表/窗口都不可用时的**符号名真源**):结构体自身的 IR 名本就是
  "{定义模块SHA1}.{类名}"(与本仓全部 mangling 同源:ClassGenDef/ClassGenVTable/
  VpiReader 的 Stub 构造)⇒ 打印 entry.Ty 并取回其 sha1 前缀(复用
  _is_sha1_prefixed 这一唯一判据,不另写判定)。
- 同一处补取证日志:命中 struct 条目却一条 SHA1 证据都取不到时(可疑子集:
  entry.ModuleSha1 为空),把 entry.Ty / cur_def_mod / cur_def_cls /
  is_module_class / from_imports / file 一次打出(只加日志,返回值语义不变)。
This commit is contained in:
TermiNexus committed 2026-09-29 21:28:18 +08:00
1 parent bbd0cdbf62
commit df1244d6f4
1 file changed
+53
+53
View File
@@ -537,10 +537,63 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
# vs 目标 %"list[rawptr<sha1>.AST]"*,被"非基本类型指针不可
# 隐式转换"拦下)。
_def_sha1 = _def_mod
# ④ 表/窗口都不可用时的**符号名真源**:结构体自身的 IR 名就是
# "{定义模块SHA1}.{类名}"(与本仓所有 mangling 同源,见 ClassGenDef /
# ClassGenVTable / VpiReader 的 Stub 构造)⇒ 直接从类型名取回 SHA1。
# 现场:Phase A-pre 没有"类定义窗口"(CurDefModuleSha1=None),而 AST
# 只有 .vpi 注入的半条目(ModuleSha1 为空)⇒ ①②③ 全落空 ⇒
# includes/ast/base.vp 字段 `children: list[rawptr[AST]]` 的实参留裸名,
# 与后续(类已注册时)解析出的 `rawptr<SHA1>.AST` 分裂成两个特化名,
# 最终被"非基本类型指针不可隐式转换"拦下(base.vp:359)。
if _def_sha1 is None and _bare_entry is not None and _bare_entry.Ty is not None:
_tp_buf: str = pool.alloc(288)
if _tp_buf is not None:
_tp_buf[0] = '\0'
llvmlite.TypePrint(_tp_buf, 288, _bare_entry.Ty, pool)
_tp_nm: str = _tp_buf
if _tp_nm[0] == '%' and _tp_nm[1] == '"':
_tp_nm += 2
_sp_l: sizet = sizet(self._is_sha1_prefixed(_tp_nm))
if _sp_l != 0:
_sha_b: str = pool.alloc(_sp_l)
if _sha_b is not None:
string.strncpy(_sha_b, _tp_nm, _sp_l - 1)
_sha_b[_sp_l - 1] = '\0'
_def_sha1 = _sha_b
if _def_sha1 is not None:
res_d: str = self._concat_sha1_class(pool, _def_sha1, type_name)
if res_d is not None:
return res_d
# 取证(只加日志,不改返回值):命中了 struct 条目却一条 SHA1 证据都取不到
# ⇒ 本次会保留裸名,可能与本类在别处解析出的"带前缀"形式分裂。把五种证据
# 的取值一次打出,便于一轮定位是哪个来源缺失(可疑子集:entry 的 ModuleSha1
# 为空——正是 .vpi 注入的半条目形态)。
if _bare_entry is not None and _bare_entry.ModuleSha1 is None:
_w_mod: str = "None"
if _def_mod is not None: _w_mod = _def_mod
_w_cls: str = "None"
if self.Gen.StructGen.CurDefClassName is not None:
_w_cls = self.Gen.StructGen.CurDefClassName
_w_fi: str = "None"
if from_imports is not None: _w_fi = from_imports
_w_file: str = "None"
if self.CurrentFile is not None: _w_file = self.CurrentFile
_w_imc: int = 0
if _def_mod is not None:
_w_imc = self.Gen.StructGen.is_module_class(pool, _def_mod, type_name)
_w_ty: str = "None"
if _bare_entry.Ty is not None:
_w_buf: str = pool.alloc(288)
if _w_buf is not None:
_w_buf[0] = '\0'
llvmlite.TypePrint(_w_buf, 288, _bare_entry.Ty, pool)
if _w_buf[0] != '\0': _w_ty = _w_buf
VLogger.error(
f"[类型实参归属] 裸类名 '{type_name}' 命中 struct 条目但取不到定义模块 SHA1"
f"(本次保留裸名,可能与带前缀形式分裂):"
f"entry.Ty={_w_ty} cur_def_mod={_w_mod} cur_def_cls={_w_cls} "
f"is_module_class={_w_imc} from_imports={_w_fi} file={_w_file}",
"TypeGen")
# ---- 6. 查不到:保持原样(内置类型名等)----
return type_name