fix(ClassGenGeneric): 泛型特化不再平移"类定义窗口",裸类名实参不再冻结成裸名
类别:a 编译器缺陷(TPV 侧) 现象(反复出现 4 轮):编译 includes/ast/base.vp 时 :359 `_append_child(self.children, node, self.pool)` 报 「指针隐式转指针已禁止(被指类型是非基本类型…):源类型 %"…list[rawptr[AST]]"* → 目标类型 %"…list[rawptr<定义模块SHA1>.AST]]"*」——同一泛型特化被写成两种拼名(实参一侧 裸类名 `AST`、另一侧带定义模块 SHA1 前缀)。 判据(结构缺陷,代码级可证): · `_norm_type_arg_name` 规则 5.5 判定"裸类名归属"依赖两个**全局窗口变量** `StructGen.CurDefModuleSha1` / `CurDefClassName`(证据 ② `is_module_class`、 ③ `CurDefClassName` 逐字相同),入口闸门是 `_def_mod is not None`。 · `ClassGenGeneric._specialize_generic_class` 在 :715-720 把 `trans.ModuleSha1` 临时切到 **泛型模板定义模块**,再于 :729 调 `ClassGenDef.translate_class_def`;后者在 `ClassGenDef.vp:50` 会 `mark_module_class(pool, trans.ModuleSha1, class_name)` ⇒ **窗口被覆盖成"模板模块 + 特化类名"**。原实现返回时只恢复 `trans.ModuleSha1` 与 `_imported_modules`(:733-735),**没有恢复这两个窗口变量**。 · 后果:调用方文件在此之后解析任何裸类名时,证据 ②③ 都在对着"模板模块 / 特化类"判 ⇒ 全落空 ⇒ 该实参以**裸名**形式被首次注册并被后续复用(首写者胜:`StructGenMixin.vp:455` 按 Ty 指针去重、`ClassGenDef.vp:100-150` existing 早退不重算)⇒ 与同一特化在别处解析出的 带 SHA1 形式分裂成两个名字 ⇒ 被"非基本类型指针不可隐式转换"拦下。 修法: 1. `ClassGenGeneric.vp`:窗口与 `ModuleSha1` **同进同出** —— 在切 ModuleSha1 之前保存 `CurDefModuleSha1`/`CurDefClassName`,:744 之后一并恢复(嵌套特化不再污染调用方窗口)。 2. `TypeGenResolve.vp` 规则 5.5 的取证日志扩展:除原有"命中 struct 条目但 entry.ModuleSha1 为空"外,**新增触发条件"窗口存在却属于另一个类"**(`_def_mod` 有值且 `CurDefClassName` 与裸名不同)——正是"窗口被特化平移/污染"或"前向引用未登记类"的签名; 报文补出 `entry_present` 与 `find_struct_by_module` 两项事实,一轮即可定位来源是否缺失。 验证:TPV 侧改动需重新自举 TransPyV.exe 后生效;本次以静态证据链(上述行号)与取证日志 自证。注:TransPyV 仓另有 7 个他人未提交文件,本次只提交本文件与 TypeGenResolve.vp。
This commit is contained in:
1 parent
31f341cf6f
commit
e1bb42fade
2 files changed
+43
-12
No files matched your search
@@ -714,6 +714,18 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
# 避免模板方法体内的跨模块调用被误报"模块未导入"。
|
||||
saved_module_sha1: str = trans.ModuleSha1
|
||||
saved_imported: str = trans._imported_modules
|
||||
# 【窗口同进同出】类定义窗口(CurDefModuleSha1/CurDefClassName)必须与
|
||||
# ModuleSha1 一起保存/恢复:下方 translate_class_def(:729)内部会按
|
||||
# **模板模块 sha1 + 特化类名** 调 mark_module_class(ClassGenDef.vp:50),
|
||||
# 覆盖这两个窗口变量。原实现只恢复 trans.ModuleSha1 ⇒ 调用方文件在此之后
|
||||
# 解析任何裸类名时,规则 5.5 的归属判据(证据 ② is_module_class /
|
||||
# ③ CurDefClassName 逐字相同)全都在对着"模板模块 / 特化类"判 ⇒ 判不到
|
||||
# ⇒ 该实参以**裸名**形式被首次注册并永久复用,与同一特化在别处解析出的
|
||||
# 带 SHA1 形式分裂成两个名字,最终以"被指类型是非基本类型……不可隐式转换"
|
||||
# 报出(现场:includes/ast/base.vp:359 `_append_child(self.children, ...)`
|
||||
# 源 list[rawptr[AST]] vs 目标 list[rawptr<定义模块SHA1>.AST])。
|
||||
saved_def_mod: str = self.Gen.StructGen.CurDefModuleSha1
|
||||
saved_def_cls: str = self.Gen.StructGen.CurDefClassName
|
||||
template_sha1: str = self._find_generic_template_sha1(class_name)
|
||||
if template_sha1 is not None:
|
||||
trans.ModuleSha1 = template_sha1
|
||||
@@ -730,9 +742,11 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase):
|
||||
if tpl_file_full is not None:
|
||||
self.Gen.TypeGenBase.pop_trace()
|
||||
self.Gen.TypeGenResolve.set_current_file(saved_cur_full)
|
||||
# 恢复原始 ModuleSha1 与 imports
|
||||
# 恢复原始 ModuleSha1 / imports / **类定义窗口**(窗口不平移,见上方说明)
|
||||
trans.ModuleSha1 = saved_module_sha1
|
||||
trans._imported_modules = saved_imported
|
||||
self.Gen.StructGen.CurDefModuleSha1 = saved_def_mod
|
||||
self.Gen.StructGen.CurDefClassName = saved_def_cls
|
||||
|
||||
# 8. 清除 type_map 上下文
|
||||
trans.GenericTypeParamNames = None
|
||||
|
||||
@@ -564,35 +564,52 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
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 注入的半条目形态)。
|
||||
# 取证(只加日志,不改返回值):一条 SHA1 证据都取不到 ⇒ 本次会保留裸名,
|
||||
# 可能与本类在别处解析出的"带前缀"形式分裂。把各处证据一次打出,便于一轮
|
||||
# 定位是哪个来源缺失。两个触发条件:
|
||||
# ① 命中 struct 条目但 entry.ModuleSha1 为空(.vpi 注入的半条目形态);
|
||||
# ② **类定义窗口存在却属于另一个类**(_def_mod 有值、CurDefClassName 与
|
||||
# 裸名不同):这是"窗口被泛型特化平移/污染"(某次
|
||||
# _specialize_generic_class 内部 translate_class_def 覆盖了窗口且未恢复)
|
||||
# 或"前向引用尚未登记的类"的签名 —— 证据 ②③ 都在对着别的类判,
|
||||
# 裸名一旦被首次注册就会被永久复用。
|
||||
_w_cls_cur: str = self.Gen.StructGen.CurDefClassName
|
||||
_w_need_log: int = 0
|
||||
if _bare_entry is not None and _bare_entry.ModuleSha1 is None:
|
||||
_w_need_log = 1
|
||||
if _def_mod is not None and _w_cls_cur is not None:
|
||||
if string.strcmp(_w_cls_cur, type_name) != 0:
|
||||
_w_need_log = 1
|
||||
if _w_need_log != 0:
|
||||
_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
|
||||
if _w_cls_cur is not None:
|
||||
_w_cls = _w_cls_cur
|
||||
_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
|
||||
_w_fbm: int = 0
|
||||
if _def_mod is not None:
|
||||
_w_imc = self.Gen.StructGen.is_module_class(pool, _def_mod, type_name)
|
||||
if self.Gen.StructGen.find_struct_by_module(type_name, _def_mod) is not None:
|
||||
_w_fbm = 1
|
||||
_w_ep: int = 0
|
||||
if _bare_entry is not None: _w_ep = 1
|
||||
_w_ty: str = "None"
|
||||
if _bare_entry.Ty is not None:
|
||||
if _bare_entry is not None and _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}",
|
||||
f"[类型实参归属] 裸类名 '{type_name}' 本次保留裸名(可能与带前缀形式分裂):"
|
||||
f"entry_present={_w_ep} entry.Ty={_w_ty} cur_def_mod={_w_mod} cur_def_cls={_w_cls} "
|
||||
f"is_module_class={_w_imc} find_struct_by_module={_w_fbm} "
|
||||
f"from_imports={_w_fi} file={_w_file}",
|
||||
"TypeGen")
|
||||
# ---- 6. 查不到:保持原样(内置类型名等)----
|
||||
return type_name
|
||||
|
||||
Reference in new issue
Block a user