fix(generic): 特化 T 替换判据修正——t 模块内建类型(裸名或 t. 前缀)仍用 type_name

上一提交对类类型参数改用 mangled type_arg 替换 T,但 type_name 为
't.CInt'(带 t. 前缀、不在 _BUILTIN_TYPE_NAMES 裸名集合)时被误判为
类类型,改用 type_arg='i32' 替换 → list[t.CInt] 特化方法体出现
'i32.__sizeof__'(源码无此名)→ [FATAL][__sizeof__] 类型 'i32' 无法
解析 + self 类型错乱(list[i32] 中找不到 CifEvalOk,StmtGenCifMixin
编译崩溃)。判据改为取裸名(去掉 t. 前缀)判断内建,内建仍用 type_name,
只有真正的类类型参数(AST/ast.AST 等)才用 mangled type_arg。
This commit is contained in:
TermiNexus committed 2026-08-17 21:44:40 +08:00
1 parent dd95bf5bd4
commit 401429ccdf
1 file changed
+13 -7
+13 -7
View File
@@ -129,13 +129,19 @@ class ClassHandle(BaseHandle):
for i, tp_name in enumerate(type_param_names):
if type_names and i < len(type_names):
tn: str = type_names[i]
# 类类型参数(非内建)用 mangled type_arg 替换 T(带 sha1 前缀 +
# ptr 后缀,如 'f467978339422f32.ASTptr'),避免模板内部嵌套注解
# (如 list[T].__iter__ 返回 list[T])被替换成裸短名('AST')后
# 重新特化出只有 declare、无方法体的错误特化(list[AST].__len__
# undefined symbol 根因)。_make_replacement_node 会把它还原为
# 'sha1.AST | t.CPtr',重新解析时拼回一致的 mangled 名。
if tn not in _BUILTIN_TYPE_NAMES and i < len(type_args):
# 判断是否为 t 模块内建类型(裸名或 't.' 前缀,如 'CInt'/'t.CInt'):
# 内建类型必须用源码名(type_name)替换 T(t.CInt → i32),否则
# 用 mangled type_arg(如 'i32')替换会产生 'i32.__sizeof__' 这类
# 源码中不存在的名称([FATAL][__sizeof__] 类型 'i32' 无法解析)。
# 真正的类类型参数(如 'AST'/'ast.AST')才用 mangled type_arg
# (带 sha1 前缀 + ptr 后缀),避免模板内部嵌套注解被替换成裸短名
# 后重新特化出只有 declare、无方法体的错误特化(list[AST].__len__
# undefined symbol 根因)。_make_replacement_node 会把 mangled 名
# 还原为 'sha1.AST | t.CPtr',重新解析时拼回一致的 mangled 名。
tn_bare: str = tn.split('.')[-1] if '.' in tn else tn
if tn_bare in _BUILTIN_TYPE_NAMES:
type_map[tp_name] = tn
elif i < len(type_args):
type_map[tp_name] = type_args[i]
else:
type_map[tp_name] = tn