From 8af967db7f6619c3fc0d3cd65ccf6f551a859123 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 3 Oct 2026 14:34:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(generic):=20=E6=B3=9B=E5=9E=8B=E7=B1=BB?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E7=B1=BB=E5=9E=8B=E5=8F=82=E6=95=B0=E5=90=8D?= =?UTF-8?q?=E8=A1=A5=E7=BC=BA=20+=20=E7=A9=BA=E4=B8=8A=E4=B8=8B=E6=96=87?= =?UTF-8?q?=20fail-fast=EF=BC=8C=E4=BF=AE=E5=A4=8D=E7=89=B9=E5=8C=96?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E4=BD=93=20T=20=E5=8F=98=20NameError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/Class/ClassGenGeneric.vp | 49 +++++++++++++++++++---- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/App/lib/core/Gen/Class/ClassGenGeneric.vp b/App/lib/core/Gen/Class/ClassGenGeneric.vp index d991c27..3806f5d 100644 --- a/App/lib/core/Gen/Class/ClassGenGeneric.vp +++ b/App/lib/core/Gen/Class/ClassGenGeneric.vp @@ -104,7 +104,27 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): cn: sizet = len(names_local) for i in range(cn): nm: str = names_local.get(i) - if nm is not None and string.strcmp(nm, cd.name) == 0: return + if nm is not None and string.strcmp(nm, cd.name) == 0: + # 同名条目已存在时不能直接 return:**首次注册的节点可能还没有 + # type_params**(Phase1Scan 的泛型 marker 文本预筛构造的 ClassDef + # 就是这种情况),此时 _copy_type_params_stdlib 返回 None ⇒ + # GenericClassTpParams[i] 留 0。而后续携带真实 type_params 的那次 + # 注册会被这里的同名去重拦掉 ⇒ 类型参数名永久缺失 ⇒ + # _find_generic_template_tp_params 因 buf_addr==0 返回 None ⇒ + # _specialize_generic_class 退回过期的 template_cd.type_params + # (空/已回收)⇒ 泛型上下文为空 ⇒ 模板方法体里的 `T` 变成 + # "NameError: 未定义名称 'T'"(现场:includes/vector.vp:12 + # `self.elem_size = T.__sizeof__()`)。 + # 故此处补缺:本次能拿到 tp 名就把空槽填上,并把节点换成信息更全的 + # 这一个(节点也用于 _find_generic_template 的后续读取)。 + if self.GenericClassTpParams is not None and i < GENERIC_TEMPLATE_MAX \ + and self.GenericClassTpParams[i] == 0: + back_buf: str = self._copy_type_params_stdlib(cd.type_params) + if back_buf is not None: + self.GenericClassTpParams[i] = sizet(back_buf) + if self.GenericClassNodes is not None: + self.GenericClassNodes.set(i, cd) + return # type_params stdlib 深拷贝:模板节点的 type_params 是 pool 分配的 tp_names_buf: str = self._copy_type_params_stdlib(cd.type_params) self.GenericClassNames.append(self._dup_perm_str(cd.name)) @@ -1052,6 +1072,25 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): string.strcpy(ts_buf_r, trigger_sha1) entry_rt.SpecTriggerSha1 = ts_buf_r return 1 + def _tp_names_for_spec(self, pool: memhub.MemBuddy*, class_name: str, + template_cd: ast.ClassDef*) -> list[str]*: + """取特化用的类型参数名列表(优先 stdlib 深拷贝表,退化模板节点) + + 两条来源都拿不到/为空时 fail-fast,**绝不**用空泛型上下文继续特化: + 空上下文会让模板方法体里的类型形参(如 `T.__sizeof__()`)落到普通名字 + 查找 → 报 "NameError: 未定义名称 'T'",现象与真因(元数据缺失)严重脱节。 + """ + tp: list[str]* = self._find_generic_template_tp_params(pool, class_name) + if tp is not None and len(tp) > 0: + return tp + if template_cd is not None and template_cd.type_params is not None \ + and len(template_cd.type_params) > 0: + return template_cd.type_params + self.Gen.TypeGenErr.fatal_error(None, + f"泛型类模板 '{class_name}' 的类型参数名缺失(GenericClassTpParams 对应槽为空," + f"模板节点也无 type_params)——拒绝用空泛型上下文特化", "InternalCompilerError") + return None + def _specialize_generic_class(self, trans: HT.Translator*, class_name: str, type_args: list[str]*) -> str: @@ -1126,9 +1165,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): # 方法体永不发射 → 特化方法只有 call 无 define → 链接 undefined symbol。 pre_existing.MethodsEmitted = 1 # 从 stdlib 深拷贝表取 type_params(模板节点 pool list 跨 Phase 可能失效) - tp_names_pre: list[str]* = self._find_generic_template_tp_params(pool, class_name) - if tp_names_pre is None: - tp_names_pre = template_cd.type_params + tp_names_pre: list[str]* = self._tp_names_for_spec(pool, class_name, template_cd) spec_cd_pre: ast.ClassDef* = self._clone_classdef_for_spec(pool, template_cd, spec_name, tp_names_pre, type_args) if spec_cd_pre is not None: trans.GenericTypeParamNames = tp_names_pre @@ -1203,9 +1240,7 @@ novirtual class ClassGenGeneric(ClassGenBase.ClassGenBase): # 5. 拷贝 ClassDef 节点 # 从 stdlib 深拷贝表取 type_params(模板节点 pool list 跨 Phase 可能失效) - tp_names: list[str]* = self._find_generic_template_tp_params(pool, class_name) - if tp_names is None: - tp_names = template_cd.type_params + tp_names: list[str]* = self._tp_names_for_spec(pool, class_name, template_cd) spec_cd: ast.ClassDef* = self._clone_classdef_for_spec(pool, template_cd, spec_name, tp_names, type_args) if spec_cd is None: self.GenericSpecDepth -= 1