From fa2cfef205540cd311231f80c0a7c8751c2b9b25 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 17 Aug 2026 21:19:43 +0800 Subject: [PATCH] =?UTF-8?q?fix(generic):=20=E7=89=B9=E5=8C=96=20T=20?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E7=94=A8=20mangled=20=E5=90=8D=20+=20operato?= =?UTF-8?q?r=20fallback=20=E9=80=89=E6=9C=89=20define=20=E7=9A=84=E7=89=B9?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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() 选中错误特化。 --- lib/core/Handles/HandlesClassDef.py | 24 +++++++++++++++++------- lib/core/Handles/HandlesExprUtils.py | 27 ++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/lib/core/Handles/HandlesClassDef.py b/lib/core/Handles/HandlesClassDef.py index 2608592..c4ac825 100644 --- a/lib/core/Handles/HandlesClassDef.py +++ b/lib/core/Handles/HandlesClassDef.py @@ -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] diff --git a/lib/core/Handles/HandlesExprUtils.py b/lib/core/Handles/HandlesExprUtils.py index b2fd047..6f9da6c 100644 --- a/lib/core/Handles/HandlesExprUtils.py +++ b/lib/core/Handles/HandlesExprUtils.py @@ -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):