fix(gen): ret(borrows=...) 支持 0 起序号写法(原来只认形参名)

现场:@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) 等价可用。
This commit is contained in:
TermiNexus committed 2026-10-10 13:27:24 +08:00
1 parent 5ec75b2d38
commit c1d3f62bf0
1 file changed
+12 -6
+12 -6
View File
@@ -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=<param>` / `borrows=none`", "LifetimeError")