fix(generic): 泛型类模板类型参数名补缺 + 空上下文 fail-fast,修复特化方法体 T 变 NameError
This commit is contained in:
1 parent
98ee53340f
commit
8af967db7f
1 file changed
+42
-7
@@ -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
|
||||
|
||||
Reference in new issue
Block a user