From 6000734704eb316856cc4d2e7a5471f92beca892 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 9 Oct 2026 22:14:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(life):=20A1=E2=80=94=E2=80=94@life=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20stores(x)/borrows(x)=EF=BC=88=E5=A4=8D?= =?UTF-8?q?=E7=94=A8=20escape/noescape=20=E5=A5=91=E7=BA=A6=E4=BD=8D?= =?UTF-8?q?=EF=BC=89=EF=BC=9Bret/owns=20=E6=98=BE=E5=BC=8F=E6=8A=A5?= =?UTF-8?q?=E6=9C=AA=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §14 路线 A 第一步(零语义变化): - stores(x) 归到"强制逃逸"位、borrows(x) 归到"强制不逃逸"位(同一对契约位,调用点已在最后套用、.vpi 已有 esce=/escn= 通道) - _WillFreeMergeTag 白名单同步扩 stores/borrows;ret/owns 显式 fail-fast "not implemented yet (planned A2/A3)",不做静默忽略 - 矛盾契约报文改为 escape/stores 与 noescape/borrows 两两对立 --- App/lib/core/Gen/GenApi.vp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/App/lib/core/Gen/GenApi.vp b/App/lib/core/Gen/GenApi.vp index e9fb474..03c1f18 100644 --- a/App/lib/core/Gen/GenApi.vp +++ b/App/lib/core/Gen/GenApi.vp @@ -367,8 +367,16 @@ def _WillFreeMergeTag(fn: ast.FunctionDef*, tag: ast.AST*, mask: int) -> int: is_wf: int = string.strcmp(tnm, "willFree") is_esc: int = string.strcmp(tnm, "escape") is_nesc: int = string.strcmp(tnm, "noescape") - if is_wf != 0 and is_esc != 0 and is_nesc != 0: - fatal_error(tag, "@life(...) accepts only `willFree()` / `escape()` / `noescape()` tags", "LifetimeError") + # A1(§14):stores ≡ escape("确定存进长命存储"的强声明)、borrows ≡ noescape(借出口径)。 + # 二者复用同一对契约位,位本身由 compute_escape_directives 收。 + is_st: int = string.strcmp(tnm, "stores") + is_bw: int = string.strcmp(tnm, "borrows") + # A2/A3 的标签(ret / owns)先**显式**报"未实现",不做静默忽略(静默 = 用户以为标注生效了)。 + if string.strcmp(tnm, "owns") == 0 or string.strcmp(tnm, "ret") == 0: + fatal_error(tag, f"@life tag `{tnm}(...)` is not implemented yet (planned A2/A3); use willFree/escape/noescape/stores/borrows for now", "LifetimeError") + return mask + if is_wf != 0 and is_esc != 0 and is_nesc != 0 and is_st != 0 and is_bw != 0: + fatal_error(tag, "@life(...) accepts only `willFree(...)` / `escape(...)` / `noescape(...)` / `stores(...)` / `borrows(...)` tags", "LifetimeError") return mask if tc.args is None or len(tc.args) == 0: fatal_error(tag, f"@life tag `{tnm}(...)` needs at least one parameter name or 0-based position", "LifetimeError") @@ -422,6 +430,9 @@ def compute_escape_directives(fd: ast.AST*, out: sizet*) -> int: if tnm2 is None: continue is_esc2: int = string.strcmp(tnm2, "escape") is_nesc2: int = string.strcmp(tnm2, "noescape") + # A1(§14):stores 归到"强制逃逸"位、borrows 归到"强制不逃逸"位(复用同一对契约位) + if string.strcmp(tnm2, "stores") == 0: is_esc2 = 0 + if string.strcmp(tnm2, "borrows") == 0: is_nesc2 = 0 if is_esc2 != 0 and is_nesc2 != 0: continue if tcl.args is None or len(tcl.args) == 0: fatal_error(tg, f"@life tag `{tnm2}(...)` needs at least one parameter name or 0-based position", "LifetimeError") @@ -434,12 +445,12 @@ def compute_escape_directives(fd: ast.AST*, out: sizet*) -> int: if idx2 < 0: continue if is_esc2 == 0: if ((int(out[1]) >> idx2) & 1) != 0: - fatal_error(tg, f"contradictory lifetime tags: parameter #{idx2} is marked both escape(...) and noescape(...)", "LifetimeError") + fatal_error(tg, f"contradictory lifetime tags: parameter #{idx2} is marked both escape/stores(...) and noescape/borrows(...)", "LifetimeError") continue out[0] = out[0] | (sizet(1) << idx2) else: if ((int(out[0]) >> idx2) & 1) != 0: - fatal_error(tg, f"contradictory lifetime tags: parameter #{idx2} is marked both escape(...) and noescape(...)", "LifetimeError") + fatal_error(tg, f"contradictory lifetime tags: parameter #{idx2} is marked both escape/stores(...) and noescape/borrows(...)", "LifetimeError") continue out[1] = out[1] | (sizet(1) << idx2) return 0