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:
1 parent
bd0e541b74
commit
fa2cfef205
2 files changed
+39
-12
No files matched your search
@@ -115,13 +115,7 @@ class ClassHandle(BaseHandle):
|
||||
spec_name: str = self._mangle_generic_class_name(ClassName, type_args)
|
||||
# 预注册到缓存,防止特化过程中方法体引用自身类型导致无限递归
|
||||
Gen._generic_class_specializations[spec_key] = (spec_name, declare_only)
|
||||
type_map: dict[str, str] = {}
|
||||
for i, tp_name in enumerate(type_param_names):
|
||||
if type_names and i < len(type_names):
|
||||
type_map[tp_name] = type_names[i]
|
||||
else:
|
||||
type_map[tp_name] = type_args[i]
|
||||
# 内建类型名集合(必须在 cptr_params 检测之前定义)
|
||||
# 内建类型名集合(必须在 type_map/cptr_params 检测之前定义)
|
||||
_BUILTIN_TYPE_NAMES: set = {
|
||||
'CInt', 'CUInt', 'CInt8T', 'CUInt8T', 'CInt16T', 'CUInt16T',
|
||||
'CInt32T', 'CUInt32T', 'CInt64T', 'CUInt64T', 'CChar', 'CShort',
|
||||
@@ -131,6 +125,22 @@ class ClassHandle(BaseHandle):
|
||||
'int', 'double', 'float', 'i8', 'i16', 'i32', 'i64', 'void',
|
||||
'half', 'fp128', 'char', 'bool',
|
||||
}
|
||||
type_map: dict[str, str] = {}
|
||||
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):
|
||||
type_map[tp_name] = type_args[i]
|
||||
else:
|
||||
type_map[tp_name] = tn
|
||||
else:
|
||||
type_map[tp_name] = type_args[i]
|
||||
# 检测哪些类型参数在原始类型实参中带有 | t.CPtr
|
||||
# 当 type_arg 以 'ptr' 结尾(_resolve_type_arg_str 将 t.CPtr 规范化为 'ptr')
|
||||
# 且对应的 type_name 不是内建类型名时,说明调用方写了 list[AST | t.CPtr]
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in new issue
Block a user