fix(generic): 泛型类模板类型参数名补缺 + 空上下文 fail-fast,修复特化方法体 T 变 NameError

This commit is contained in:
TermiNexus committed 2026-10-03 14:34:55 +08:00
1 parent 98ee53340f
commit 8af967db7f
1 file changed
+42 -7
+42 -7
View File
@@ -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