docs(raw-buf): refresh fixture outcomes; ratify set non-enforcement (refs #7)
- rawbuf_1_score_table / rawbuf_2_running_max: the header OUTCOME blocks described the pre-fix breakage (does-not-check / unknown-variable). Those defects are fixed (B1 #46, B2 #47, B5); update the comments to the current state — both check, build, run to their expected values and are leak-clean under AILANG_RC_STATS. The files now serve as positive regression examples, not bug repros. - design/models/0007 §RawBuf: ratify the fieldtest's B4 spec_gap. The `own -> own` signature of RawBuf.set is a threading discipline, not runtime-enforced single-use; a double-consume of the same owned buffer aliases one slab (consistent with every owned value in the language). State that single-use is the author's responsibility and full linear enforcement is Issue #22 territory. Surfaced by the raw-buf fieldtest (docs/specs/0058).
This commit is contained in:
@@ -405,6 +405,22 @@ The own/borrow signatures *are* the mutation contract. No
|
|||||||
existing memory-model — RC + uniqueness as the canonical
|
existing memory-model — RC + uniqueness as the canonical
|
||||||
mutation story.
|
mutation story.
|
||||||
|
|
||||||
|
The `own → own` signature of `RawBuf.set` is a *threading
|
||||||
|
discipline*, not runtime-enforced single-use. The mode annotations
|
||||||
|
drive the borrow/consume analysis and the in-place-vs-copy codegen
|
||||||
|
decision; they do not make a second consume of the same owned
|
||||||
|
binder a check-time error. An author who hands the same owned
|
||||||
|
buffer to two consuming calls
|
||||||
|
(`(let a (RawBuf.set buf 0 1)) (let b (RawBuf.set buf 1 2))`)
|
||||||
|
gets two bindings aliasing one slab — the second mutation is
|
||||||
|
visible through the first. This is the same non-enforcement that
|
||||||
|
holds for every owned value in the language (owned `Str`, owned
|
||||||
|
ADTs); `RawBuf`'s in-place `own → own` surface is merely the first
|
||||||
|
place the alias produces a *mutated-in-place* surprise rather than
|
||||||
|
a benign re-read. Single-use of an owned buffer is the author's
|
||||||
|
responsibility. Full linear enforcement, if wanted, is tracked
|
||||||
|
separately (Issue #22 territory).
|
||||||
|
|
||||||
Storage at the LLVM-IR level is type-specialised: the Rust
|
Storage at the LLVM-IR level is type-specialised: the Rust
|
||||||
intercept registered for `RawBuf` dispatches on the element type
|
intercept registered for `RawBuf` dispatches on the element type
|
||||||
at each call site and emits the appropriate `getelementptr` /
|
at each call site and emits the appropriate `getelementptr` /
|
||||||
|
|||||||
@@ -11,17 +11,18 @@
|
|||||||
;
|
;
|
||||||
; Expected stdout: scores 1, 2, 5, 10, 17 -> sum 35.
|
; Expected stdout: scores 1, 2, 5, 10, 17 -> sum 35.
|
||||||
;
|
;
|
||||||
; OUTCOME: does NOT check. `ail check` reports, for the `total` fn:
|
; This was the fieldtest repro for two defects, both now fixed:
|
||||||
; [consume-while-borrowed] total: `buf` is consumed while a borrow of
|
; - B1 (#46): the `total` helper, which takes `borrow (RawBuf Int)`
|
||||||
; it is still live
|
; and only calls RawBuf.size / RawBuf.get on the receiver, was
|
||||||
; even though `total` takes `borrow (RawBuf Int)` and only calls
|
; falsely rejected with [consume-while-borrowed]. The linearity
|
||||||
; RawBuf.size / RawBuf.get on it (both `borrow`-receiver ops per the
|
; pass now resolves the type-scoped borrow-receiver ops, so the
|
||||||
; ledger). A single get/size on a borrow-mode receiver triggers it.
|
; borrow helper checks clean.
|
||||||
; (The `fill` loop, if `total` were removed, would in turn fail at
|
; - B2 (#47): the `fill` loop, threading the owned buffer through a
|
||||||
; `build` with `unknown variable: b` — see rawbuf_2_running_max.ail.)
|
; `recur`, failed codegen with `unknown variable: b`. The synth
|
||||||
; First authoring attempt also hit two papercuts: a `loop` binder may
|
; type-replay now descends through `loop` with the loop binders in
|
||||||
; not carry an `own` mode ("`own` may only appear inside fn-type params
|
; scope.
|
||||||
; or ret"), and the prelude comparison is `ge`, not `gte`.
|
; OUTCOME (current): checks, builds, runs; prints 35. Leak-clean under
|
||||||
|
; AILANG_RC_STATS (the owned buffer drops at scope close, B5).
|
||||||
|
|
||||||
(module rawbuf_1_score_table
|
(module rawbuf_1_score_table
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,13 @@
|
|||||||
;
|
;
|
||||||
; Expected stdout: 16 (slots 1,4,9,16; running max ends at 16).
|
; Expected stdout: 16 (slots 1,4,9,16; running max ends at 16).
|
||||||
;
|
;
|
||||||
; OUTCOME: `ail check` passes ("ok"), but `ail build` FAILS at codegen:
|
; This was the fieldtest repro for B2 (#47): `ail check` passed but
|
||||||
; Error: module `rawbuf_2_running_max`: def `main`: unknown variable: `b`
|
; `ail build` FAILED at codegen with `unknown variable: b` — the synth
|
||||||
; The owned-RawBuf `loop` binder `b` threaded through `recur` is visible
|
; type-replay walked the `loop` body without the loop binders in scope.
|
||||||
; to the checker but not to codegen. A plain Int loop binder named `b`
|
; Now fixed: the replay descends through `loop` with its binders bound.
|
||||||
; builds fine, so it is specific to threading an owned RawBuf value
|
; OUTCOME (current): checks, builds, runs; prints 16. Leak-clean under
|
||||||
; through a loop binder. The check<->codegen agreement is broken here.
|
; AILANG_RC_STATS (the loop-threaded owned buffer drops at scope close,
|
||||||
|
; B5 — the let-bound loop result is now registered for scope-close drop).
|
||||||
|
|
||||||
(module rawbuf_2_running_max
|
(module rawbuf_2_running_max
|
||||||
(fn main
|
(fn main
|
||||||
|
|||||||
Reference in New Issue
Block a user