diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 7591632..3ec3f1b 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -614,12 +614,15 @@ novirtual class AssignGenMixin: return sname # _CallArgNodeForParam - `@life(ret(borrows=<形参 pi>))` 在调用点对应的实参节点。 - # 方法调用的形参表含 self(pi=0 即接收者),故方法分支要偏移一格。 - def _CallArgNodeForParam(self, cl: ast.Call*, pi: int) -> ast.AST*: + # **方法**调用的形参表含 self(pi=0 即接收者),故 is_method=1 时偏移一格; + # **模块限定函数**(`m.f(...)`:callee 也是 Attribute,但不是方法)形参 0 就是第一个实参, + # 不能偏移 —— 否则 pi=0 会被解析成"模块名"这个非实参节点(现场:本函数把 + # `retdep2.IdentBorrow(l)` 的形参 0 取成了 `retdep2` → life=STATIC → 跨模块 ret 契约静默失效)。 + def _CallArgNodeForParam(self, cl: ast.Call*, pi: int, is_method: int) -> ast.AST*: """第 pi 号形参对应的实参表达式;越界/判不定返回 None""" if cl is None or pi < 0: return None cargs: list[ast.AST*]* = cl.args - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: + if is_method != 0: if pi == 0: at: ast.Attribute* = ast.Attribute*(cl.func) return at.value @@ -628,6 +631,15 @@ novirtual class AssignGenMixin: if cargs is None or sizet(pi) >= len(cargs): return None return cargs.get(sizet(pi)) + # _CallIsMethod - 该调用是否"接收者是对象变量"的方法调用(决定形参表是否含 self)。 + def _CallIsMethod(self, trans: HT.Translator*, cl: ast.Call*) -> int: + """1 = 方法调用(形参表含 self);0 = 模块限定函数 / 裸函数""" + if cl is None or cl.func is None: return 0 + if cl.func.kind() != ast.ASTKind.Attribute: return 0 + at: ast.Attribute* = ast.Attribute*(cl.func) + if self._RecvClassName(trans, at.value) is None: return 0 + return 1 + # _CallRetKind - 解析被调者的 `@life(ret(...))` 契约(本文件表 → 跨模块 .vpi);-1 = 无声明/判不定。 def _CallRetKind(self, trans: HT.Translator*, cl: ast.Call*) -> int: """被调者 ret_kind 编码(GenApi.RET_KIND_*);-1 = 无声明/判不定""" @@ -722,7 +734,9 @@ novirtual class AssignGenMixin: if rk == GenApi.RET_KIND_NONFRAME: return GenTypes.LIFE_UNKNOWN if rk >= GenApi.RET_KIND_BORROW_BASE: pi: int = rk - GenApi.RET_KIND_BORROW_BASE - bn: ast.AST* = self._CallArgNodeForParam(cl, pi) + # 形参位 → 实参位:**方法**调用的形参表含 self(pi=0 = 接收者); + # 模块限定函数(`m.f(...)`)不含,pi 直接就是实参下标。 + bn: ast.AST* = self._CallArgNodeForParam(cl, pi, self._CallIsMethod(trans, cl)) if bn is None: return GenTypes.LIFE_UNKNOWN return self.life_of_expr(trans, bn, None) # 分配类调用 → 堆;其余调用 → 未知(函数摘要落地前保守放行)