Files
Viper_RegressionTesting/NewLifetimeRetOkTest/App/main.vp
T
TermiNexus 66ebd75dec test(lifetime): 补齐 A2 @life(ret(...)) 的正/负向回归工程
新增 3 个工程(均登记进 regression_test.py / SequentialRegressionTest.py /
run_lifetime_negative_tests.py 的 escape/负向清单):
- NewLifetimeRetOkTest(正向):ret(heap)/ret(static)/ret(borrows=none) 的结果
  可存进堆对象字段;ret(frame)/ret(borrows=x) 的结果只在本帧内使用;
  同模块契约表与跨模块 .vpi(escr=) 两条取用路径都覆盖 → 编译通过 + 退出码 0。
- NewLifetimeRetEscapeTest(负向):同模块 @life(ret(frame)) 的返回值写进堆对象
  字段 → LifetimeError(隔离性:FrameRet 摘要为 0,唯一报错源是 ret 契约)。
- NewLifetimeRetXmodTest(负向):跨模块 @life(noescape(x), ret(borrows=x)) 的结果
  写进堆对象字段 → LifetimeError(契约经对方 .vpi 的 escr= 传来;noescape 清掉了
  实参逃逸路径,判据收敛到 ret 契约)。
README.md 的 escape 测试表与负向清单同步。
2026-10-10 09:03:05 +08:00

65 lines
2.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from stdint import *
import stdio
import retdep
# =============================================================================
# 正向工程:A2 `@life(ret(...))` 契约**不得误报**(编译必须成功、运行退出码 0)
#
# 对照负向工程:
# · NewLifetimeRetEscapeTest —— 同模块 `ret(frame)` 的结果存进长命存储 → 必须报;
# · NewLifetimeRetXmodTest —— 跨模块 `ret(borrows=x)`(经 .vpi 的 escr=)→ 必须报。
#
# 本工程覆盖:
# (1) 非帧契约(heap / static / borrows=none)→ 结果可存进**堆对象字段**(长命左值);
# (2) ret(frame) → 结果只在本帧内使用 → 合法(不是"无害",而是调用点按声明**放行**);
# (3) ret(borrows=x) → 结果的生命期 = 实参 x 的生命期(本帧实参 → 帧内使用合法);
# (4) 同模块(本文件契约表)与跨模块(retdep.vp,经 .vpi 的 escr=)两条取用路径都走一遍。
#
# 注意:本文件**不得**把 `ret(frame)` / `ret(borrows=x)` 的结果写进堆对象字段
# (`h.p = …`)——那是负向工程负责证明会被拒的写法。
# =============================================================================
novirtual class Holder:
p: int*
c: char*
# ---- 同模块契约(走本文件 EscDirTable,不经 .vpi)----
@life(ret(heap))
def LocalHeap() -> int*:
return new heap hlife int
@life(ret(frame))
def LocalFrame() -> int*:
l: int* = new stack int
return l
export def main() -> int:
h: Holder* = new heap hlife Holder()
# (1) 非帧契约 → 存进堆对象字段(左值长命、右值非帧)→ 放行
h.p = retdep.MkHeap() # 跨模块 ret(heap)
h.c = retdep.MkStatic() # 跨模块 ret(static)
h.p = retdep.Fresh() # 跨模块 ret(borrows=none)
h.p = LocalHeap() # 同模块 ret(heap)
# (2) ret(frame):结果只在本帧内使用 → 放行
pf: int* = retdep.FrameRet() # 跨模块 ret(frame)
pl: int* = LocalFrame() # 同模块 ret(frame)
# (3) ret(borrows=x):结果生命期 = 实参生命期;实参在本帧 → 结果只在本帧用 → 放行
base: int* = new stack int
pb: int* = retdep.IdentBorrow(base)
if pf is None: return 1
if pl is None: return 2
if pb is None: return 3
stdio.printf("RetOkTest OK: @life(ret(...)) contracts accepted\n")
return 0