Files
AILang/examples/fieldtest/cut55_2b_borrow_traversal_clean.ail
Brummel e25580e3a3 test(cutover): live accept/reject corpus for the #55 ownership surface
Wires the #55-cutover fieldtest into a durable regression net. The
fieldtest exercised the post-cutover ParamMode={Own,Borrow} surface as a
downstream LLM author would and produced 12 fixtures + a report; left as
loose files they would be dead fixtures that drift. This commits them as
a protected property.

crates/ail/tests/cut55_cutover_surface.rs — one table-driven test running
each fixture through `ail check` and asserting accept (exit 0) or reject
at the right pipeline stage. Reject rows key on the bracketed diagnostic
CODE (consume-while-borrowed, borrow-over-value, borrow-return-not-permitted,
surface-parse-error), NOT message text, so the test is decoupled from the
diagnostic-wording improvement tracked separately.

examples/fieldtest/cut55_*.ail — the corpus. cut55_2c is the #58 repro
(now correctly rejected). cut55_2b was misanalysed by the fieldtest as a
consume-while-borrowed reject; in fact bump's recursive param is
(borrow List) so the tail is only borrowed, never consumed into an own
slot — `ail check` correctly accepts it. Renamed to
cut55_2b_borrow_traversal_clean and recast as the #58 false-positive
guard (a borrow-position use of a heap sub-binder must stay accepted).
cut55_1b similarly does not fire over-strict-mode (its recursive call
consumes the tail, so the lint's consume_count==0 premise fails) — comment
corrected; it is a plain accept. cut55_1c is the genuine over-strict-mode
example (accepts exit 0, emits the warning).

docs/specs/0065-eliminate-implicit-mode fieldtest report — moved 2c to
the reject set, added the 2b false-positive-guard section, marked the
double-free spec_gap RESOLVED (it shipped as the #58 fix).

Relates to #55.
2026-06-02 00:45:21 +02:00

35 lines
1.3 KiB
Plaintext

; Fieldtest cut55-2b — decision (b), false-positive GUARD for the #58 fix.
;
; This is the legitimate borrow-traverse-and-rebuild that MUST be accepted.
; `bump` borrows xs and, in the Cons arm, reads the head `h` (a value-typed
; Int, copied), passes the tail `t` to its own recursive call, and packs a
; fresh Cons. The recursive `bump`'s param is `(borrow (con List))`, so `t`
; is only BORROWED, never moved into an `(own)` slot — nothing of the
; borrowed xs is consumed. A fresh List is allocated and returned `own`.
;
; This pins that the #58 fix (inherit borrow on heap sub-binders of a
; borrowed scrutinee) does NOT over-fire: a borrow-position use of a heap
; sub-binder is fine. Contrast cut55_2c (feeds `t` to an OWN sink -> reject)
; and cut55_2d (consumes the whole borrowed xs -> reject).
;
; Expected: ail check -> ok, exit 0.
(module cut55_2b_borrow_traversal_clean
(data List
(ctor Nil)
(ctor Cons (con Int) (con List)))
(fn bump
(doc "Borrow xs and rebuild a fresh +1 list; tail t is only borrowed, not consumed.")
(type
(fn-type
(params (borrow (con List)))
(ret (own (con List)))))
(params xs)
(body
(match xs
(case (pat-ctor Nil) (term-ctor List Nil))
(case (pat-ctor Cons h t)
(term-ctor List Cons (app + h 1) (app bump t)))))))