fix(call): pass the class segment when resolving a cross-module method return type

The cross-module return-type resolution derived only {sha} and the last segment from {sha}.Class.method, then queried the vpi cache and the dependency text.ll with no class name. Both key methods by class, so a class-level function without a return annotation (Scheduler._yield) missed both lookups and hit the fail-fast 'Cannot obtain the cross-module function return type precisely' path. Derive the middle segment and pass it as the class when it names a registered class; module functions ({sha}.submod.func) keep the bare-name lookup.
This commit is contained in:
TermiNexus committed 2026-10-29 17:48:59 +08:00
1 parent f5c5e068ae
commit ffe31cc6e3
1 file changed
+19 -2
+19 -2
View File
@@ -1641,10 +1641,26 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
local_fn: mlirlite.Function* = self.find_func_in_module(mod, call_name)
if local_fn is not None and local_fn.RetTy is not None: call_ret_ty = local_fn.RetTy
else:
cf_vpi: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cf_sha1, None, cf_bare)
# {sha}.Class.method: the vpi return-annotation cache and the dependency
# text.ll both key methods by class, so the class segment must be passed
# through. Only when it names a registered class: `{sha}.submod.func` has
# the same shape but its symbol is the bare module function.
cf_cls: str = None
cf_mid: str = cf_dot + 1
if uint64(cf_last) > uint64(cf_mid):
cf_mid_len: sizet = sizet(uint64(cf_last) - uint64(cf_mid))
cf_cls_buf: bytes = stdlib.malloc(cf_mid_len + 1)
if cf_cls_buf is not None:
string.strncpy(cf_cls_buf, cf_mid, cf_mid_len)
cf_cls_buf[cf_mid_len] = '\0'
if self.Gen.StructGen.get_struct_type(cf_cls_buf) is not None: cf_cls = cf_cls_buf
else: stdlib.free(cf_cls_buf)
cf_use_bare: int = 1
if cf_cls is not None: cf_use_bare = 0
cf_vpi: mlirlite.LLVMType* = self._lookup_method_ret_ty_via_vpi(pool, cf_sha1, cf_cls, cf_bare)
if cf_vpi is not None: call_ret_ty = cf_vpi
else:
cf_ret: mlirlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cf_sha1, None, cf_bare, 1)
cf_ret: mlirlite.LLVMType* = self._LookupMethodRetTyFromTextLL(pool, cf_sha1, cf_cls, cf_bare, cf_use_bare)
if cf_ret is not None: call_ret_ty = cf_ret
else:
# 编译器内置(ord/chr/min/max):builtins.vp 只是注释桩,没有任何声明,
@@ -1659,6 +1675,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
# Dependency text.ll does not exist (module not yet translated): Phase A translates files
# in order (main.vp before its imported mbuddytest.vp), so keep the default type without fail-fast.
if bi_synth == 0 and self._dep_text_ll_exists(pool, cf_sha1) != 0: self.Gen.TypeGenErr.fatal_error(node, f"Cannot obtain the cross-module function return type precisely (neither vpi nor text.ll hit); the default i32 will truncate pointers: {call_name}", "TypeError")
if cf_cls is not None: stdlib.free(cf_cls)
stdlib.free(cf_sha1)
stdlib.free(cf_bare)
# 迟到的补参:call_name 此时已带定义模块 SHA1 前缀(权威键),补上早期因链式接收者