From c1d3f62bf0a565f64ebe6a8d45b5cd8d44213ef6 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 10 Oct 2026 13:27:24 +0800 Subject: [PATCH] =?UTF-8?q?fix(gen):=20ret(borrows=3D...)=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=200=20=E8=B5=B7=E5=BA=8F=E5=8F=B7=E5=86=99=E6=B3=95?= =?UTF-8?q?=EF=BC=88=E5=8E=9F=E6=9D=A5=E5=8F=AA=E8=AE=A4=E5=BD=A2=E5=8F=82?= =?UTF-8?q?=E5=90=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现场:@life(noescape(a, b), ret(borrows=1)) 报 LifetimeError: @life(ret(borrows=...)) accepts only a parameter name or `none` —— _RetKindFromTag 的关键字分支只处理 Name(形参名)与 CONST_NONE,遇到整数常量 (形参位置序号)就落到 fail-fast。 修法:Name(形参名 / none)与 Constant(CONST_NONE = 非本帧)先分流, 其余一律交给 _WillFreeArgIndex —— 它本来就同时认"形参名"与"0 起序号" (与 willFree(...) 同口径,见 includes/stdlib.vp 注释),非法实参在那边 fail-fast。 于是 ret(borrows=x) 与 ret(borrows=0) 等价可用。 --- App/lib/core/Gen/GenApi.vp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index 990be0f..b60f47e 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -555,18 +555,24 @@ def _RetKindFromTag(fn: ast.FunctionDef*, tcl: ast.Call*) -> int: if val is None: fatal_error(tcl, "@life(ret(borrows=...)) requires a parameter name or `none`", "LifetimeError") return -1 + # `borrows=none`:返回值不借用任何形参(非本帧)。 + # 其余一律交给 _WillFreeArgIndex:它同时认**形参名**与**0 起序号**(与 willFree(...) 同口径, + # 见 includes/stdlib.vp 的注释:"写法二选一:形参名 willFree(p) 或形参位置序号 willFree(0)"), + # 非法实参(非名非整数/越界/不是形参名)在那边 fail-fast。 if val.kind() == ast.ASTKind.Name: vn: ast.Name* = ast.Name*(val) if vn.id is None: return -1 if string.strcmp(vn.id, "none") == 0: return RET_KIND_NONFRAME - idx: int = _WillFreeArgIndex(fn, val) - if idx < 0: return -1 # 已 fail-fast - return RET_KIND_BORROW_BASE + idx - if val.kind() == ast.ASTKind.Constant: + elif val.kind() == ast.ASTKind.Constant: vc: ast.Constant* = ast.Constant*(val) if vc is not None and vc.const_kind == ast.CONST_NONE: return RET_KIND_NONFRAME - fatal_error(tcl, "@life(ret(borrows=...)) accepts only a parameter name or `none`", "LifetimeError") - return -1 + else: + fatal_error(tcl, "@life(ret(borrows=...)) accepts only a parameter name (or its 0-based position) or `none`", "LifetimeError") + return -1 + idx: int = _WillFreeArgIndex(fn, val) + if idx < 0: return -1 # 已 fail-fast + return RET_KIND_BORROW_BASE + idx + # 形式二:ret(frame) / ret(heap) / ret(static) if tcl.args is None or len(tcl.args) != 1: fatal_error(tcl, "@life(ret(...)) expects exactly one of `frame` / `heap` / `static`, or `borrows=` / `borrows=none`", "LifetimeError")