fix(handles): MRO 查找归一化带 sha1 前缀类名,修复继承方法 Undefined method

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 / 按需加载父类信息
This commit is contained in:
TermiNexus committed 2026-08-17 19:11:48 +08:00
1 parent 3aebf402bb
commit 1f3c83cb6d
2 files changed
+22 -4

No files matched your search

+12 -3
View File
@@ -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
+10 -1
View File
@@ -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: