fix(generic): 特化 T 替换用 mangled 名 + operator fallback 选有 define 的特化

1. _specialize_generic_class 的 type_map 对类类型参数改用 mangled type_arg
   (如 f467978339422f32.ASTptr)替换 T,而非裸短名 type_name:模板内部嵌套
   注解(list[T].__iter__ 返回 list[T])不再被替换成裸 list[AST] 后重新特化出
   只有 declare、无方法体的错误特化 → 消除 ld.lld undefined symbol:
   7cadfe07e983fd90.list[AST].__len__/list[ClassDef].__len__。
2. _try_operator_overLoad 特化 fallback 改为优先选已编译方法体(define)的特化,
   全部只有 declare 时按需补发;dict 插入序不再导致 len() 选中错误特化。
This commit is contained in:
TermiNexus committed 2026-08-17 21:19:43 +08:00
1 parent bd0e541b74
commit fa2cfef205
2 files changed
+39 -12

No files matched your search

+22 -5
View File
@@ -89,14 +89,31 @@ class ExprUtils:
# var_struct_class 仅记录裸模板名,但方法只在特化版本中定义。
# 选择策略:优先选 obj_val.type.pointee 实际匹配的特化;否则选第一个有方法的特化。
if '[' not in ClassName:
SpecClass: str | None = None
# 先收集所有候选特化(有方法 declare 或 define 的)
best_candidates: list[str] = []
for CN in Gen.structs.keys():
if CN.startswith(f'{ClassName}[') and Gen._has_function(f'{CN}.{op_name}'):
SpecClass = CN
break
if CN.startswith(f'{ClassName}[') and Gen._has_function(f'{CN}.{op_name}__'):
if CN.startswith(f'{ClassName}[') and (Gen._has_function(f'{CN}.{op_name}') or Gen._has_function(f'{CN}.{op_name}__')):
best_candidates.append(CN)
# 优先选已编译方法体(define)的特化:dict 插入序选第一个会命中
# 只有 declare 无 define 的错误特化(如 list[AST]),生成 undefined
# symbol(ld.lld undefined symbol: list[AST].__len__ 根因)。
for CN in best_candidates:
_fn: str = f'{CN}.{op_name}' if Gen._has_function(f'{CN}.{op_name}') else f'{CN}.{op_name}__'
_f: Any = Gen._get_function(_fn)
if _f is not None and getattr(_f, 'blocks', []):
SpecClass = CN
break
if SpecClass is None and best_candidates:
# 全部只有 declare:按需补发方法体(幂等,_specialize_generic_class
# 缓存机制会从 declare_only 升级为完整特化),补发后重新检查
try:
self.Trans.ExprCallHandle._try_complete_generic_specialization(best_candidates[0], op_name, Gen)
except Exception:
pass
_fn2: str = f'{best_candidates[0]}.{op_name}' if Gen._has_function(f'{best_candidates[0]}.{op_name}') else f'{best_candidates[0]}.{op_name}__'
_f2: Any = Gen._get_function(_fn2)
if _f2 is not None and getattr(_f2, 'blocks', []):
SpecClass = best_candidates[0]
if SpecClass:
FullMethodName = f'{SpecClass}.{op_name}'
if not Gen._has_function(FullMethodName):