diff --git a/App/lib/core/Gen/CallGenCall.vp b/App/lib/core/Gen/CallGenCall.vp index b2984d3..411cb00 100644 --- a/App/lib/core/Gen/CallGenCall.vp +++ b/App/lib/core/Gen/CallGenCall.vp @@ -640,10 +640,17 @@ class CallGenCall(CallGenBase.CallGenBase): # 普通方法调用在 found_func 未命中时会误绑定到 list 特化函数, # this 按 list 布局前移 sizeof(list) → 运行期读 -1 崩溃 # (Config.vp Load_project_config root.__getitem__ 根因)。 + # 跨模块兄弟 Mixin 兜底命中记录:方法定义类在另一文件(如 + # FuncGenBase._mangle_name——调用类 ClassGenVTable 不继承它), + # 本地 IR 无 define,需经候选类模块 sha1 查 text.ll 返回类型。 + mixin_hit: int = 0 + mixin_ret_ty: llvmlite.LLVMType | t.CPtr = None + mixin_anc_name: str = None + mixin_anc_sha1: str = None if found_func is None: sc_i: int = 0 sc_n: int = self.Gen.StructGen.get_struct_count() - while sc_i < sc_n and found_func is None: + while sc_i < sc_n and found_func is None and mixin_hit == 0: cand_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen._get_struct_entry(sc_i) if cand_entry is not None and cand_entry.Name is not None: cand_name: str = cand_entry.Name @@ -661,6 +668,24 @@ class CallGenCall(CallGenBase.CallGenBase): if cand_func is not None: found_func = cand_func mc_anc = cand_name + else: + # 跨模块 Mixin(定义类在另一文件,本地 IR 无 define): + # 用候选类模块 sha1 查 text.ll 返回类型,命中即锁定定义类, + # 后续 ret_anc_* 据此构造 {sha1}.{class}.{method} 调用名。 + # 否则 ret_anc_sha1 停在调用类自身 sha1,_dep_text_ll_exists + # 查自身 text.ll(Phase A 翻译中未生成)→ 永久 pending 死锁 + # (ClassGenVTable._mangle_name → 7871cc1aabebfc33 根因)。 + if mixin_hit == 0: + cand_sha1_cx: str = self.Gen.StructGen.get_struct_sha1(cand_name) + if cand_sha1_cx is not None \ + and self._dep_text_ll_exists(pool, cand_sha1_cx) != 0: + cand_ret_cx: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL( + pool, cand_sha1_cx, cand_name, method_name) + if cand_ret_cx is not None: + mixin_hit = 1 + mixin_ret_ty = cand_ret_cx + mixin_anc_name = cand_name + mixin_anc_sha1 = cand_sha1_cx sc_i += 1 # 确定调用名(默认 "ClassName.method";found_func 未命中时沿 MRO 用 @@ -725,6 +750,13 @@ class CallGenCall(CallGenBase.CallGenBase): ret_anc_sha1 = mc_entry.ModuleSha1 else: ret_anc_sha1 = self.Gen.StructGen.get_struct_sha1(class_name) + # 跨模块兄弟 Mixin 兜底命中:定义类锁定为候选类(如 FuncGenBase), + # 返回类型与调用名前缀以其模块 sha1 为准,避免 ret_anc_sha1 停在 + # 调用类自身 sha1 → 查自身 text.ll(未生成)→ 永久 pending 死锁 + if mixin_hit != 0: + ret_anc_name = mixin_anc_name + ret_anc_sha1 = mixin_anc_sha1 + call_ret_ty = mixin_ret_ty if ret_anc_sha1 is None: # 沿 MRO 找第一个有 SHA1 的类 mro_s0: t.CSizeT | t.CPtr = self.Gen.StructGen.get_mro_chain(pool, class_name) @@ -810,7 +842,9 @@ class CallGenCall(CallGenBase.CallGenBase): call_ret_ty = frt_g found_func = spec_found_g gen_done = 1 - if gen_done == 0: + # mixin_hit:跨模块 Mixin 兜底已锁定定义类与返回类型,跳过 + # text.ll/vpi/pending 重查段,直接构造 {sha1}.{class}.{method} 调用名 + if gen_done == 0 and mixin_hit == 0: # 尝试从 text.ll 查找实际返回类型 # 避免指针返回值被默认 i32 导致 inttoptr 截断 looked_up_ty = self._LookupMethodRetTyFromTextLL(