From 1f3c83cb6d8e1a9ae920e45893ce4cefa2bb0038 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 17 Aug 2026 19:11:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(handles):=20MRO=20=E6=9F=A5=E6=89=BE?= =?UTF-8?q?=E5=BD=92=E4=B8=80=E5=8C=96=E5=B8=A6=20sha1=20=E5=89=8D?= =?UTF-8?q?=E7=BC=80=E7=B1=BB=E5=90=8D=EF=BC=8C=E4=BF=AE=E5=A4=8D=E7=BB=A7?= =?UTF-8?q?=E6=89=BF=E6=96=B9=E6=B3=95=20Undefined=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TPC 编译 TPV 报 "Undefined method 'find_func_in_module' in class 'c9b44d17cd621a75.CallGenLib'":跨模块 ObjVal 类型反查 Gen.structs 得到带 sha1 前缀的类名,而 class_parents / ModuleSha1Map / _struct_sha1_map 键为裸类名 → _get_mro_chain 查不到父类 → MRO 回退失效 → fail-fast。 - BaseGen._get_mro_chain:查 class_parents 前剥离 "16位hex." 前缀(父类名带前缀时同样处理) - HandlesExprCall._EnsureClassParentsLoaded:归一化后再查 class_parents / 按需加载父类信息 --- lib/core/Handles/HandlesExprCall.py | 15 ++++++++++++--- lib/core/LLVMCG/BaseGen.py | 11 ++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 5088b33..729e7bd 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -2516,13 +2516,22 @@ class ExprCallHandle(BaseHandle): return if Gen.class_parents.get(ClassName): return - sha1_cls = Gen.ModuleSha1Map.get(ClassName) + # 归一化:ClassName 可能带 sha1 前缀(如 "c9b44d17cd621a75.CallGenLib", + # 跨模块 structs 表键),而 class_parents / ModuleSha1Map / _struct_sha1_map + # 的键是裸类名。不剥离则查不到父类 → 继承方法 MRO 回退失效 → fail-fast + # "Undefined method 'find_func_in_module' in class '...CallGenLib'"。 + lookup_cls: str = ClassName + if len(ClassName) > 17 and ClassName[16] == '.': + lookup_cls = ClassName[17:] + if Gen.class_parents.get(lookup_cls): + return + sha1_cls = Gen.ModuleSha1Map.get(lookup_cls) if not sha1_cls: - sha1_cls = getattr(Gen, '_struct_sha1_map', {}).get(ClassName) + sha1_cls = getattr(Gen, '_struct_sha1_map', {}).get(lookup_cls) if not sha1_cls: return try: - self.Trans.ImportHandler._TryLoadClassMembersFromPyi(ClassName, f"{sha1_cls}.stub.ll", Gen) + self.Trans.ImportHandler._TryLoadClassMembersFromPyi(lookup_cls, f"{sha1_cls}.stub.ll", Gen) except Exception: pass diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py index 3a172e4..25c9931 100644 --- a/lib/core/LLVMCG/BaseGen.py +++ b/lib/core/LLVMCG/BaseGen.py @@ -601,6 +601,11 @@ class BaseGenMixin: 顺序: 自身 → 父类1 及祖先 → 父类2 及祖先(先声明父类优先,菱形去重)。 与 TPV HandlesStruct.get_mro_chain 的语义一致。 + + 支持带 sha1 前缀的类名(如 "c9b44d17cd621a75.CallGenLib",跨模块 + structs 表键):查 class_parents 前剥离前缀,否则表键(裸类名)不匹配 + → MRO 链只剩自身 → 继承方法调用 fail-fast "Undefined method + 'find_func_in_module' in class '...CallGenLib'"(CallGenLib 根因)。 """ chain: list[str] = [] visited: set[str] = set() @@ -612,7 +617,11 @@ class BaseGenMixin: continue visited.add(cur) chain.append(cur) - parents: list[str] = parents_map.get(cur, []) + # 归一化:剥离 "16位hex." 前缀后用裸类名查父类表 + lookup: str = cur + if len(cur) > 17 and cur[16] == '.': + lookup = cur[17:] + parents: list[str] = parents_map.get(lookup, parents_map.get(cur, [])) # 父类逆序压栈,保证声明顺序弹出(先访问父类1 的整条链) for p in reversed(parents): if p and p not in visited: