diff --git a/App/lib/core/Gen/Class/ClassGenGeneric.vp b/App/lib/core/Gen/Class/ClassGenGeneric.vp index ebe5d9c..4a1f957 100644 --- a/App/lib/core/Gen/Class/ClassGenGeneric.vp +++ b/App/lib/core/Gen/Class/ClassGenGeneric.vp @@ -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 diff --git a/App/lib/core/Gen/Type/TypeGenResolve.vp b/App/lib/core/Gen/Type/TypeGenResolve.vp index 543c62c..f612e74 100644 --- a/App/lib/core/Gen/Type/TypeGenResolve.vp +++ b/App/lib/core/Gen/Type/TypeGenResolve.vp @@ -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