✓
Passing Passing: the compiler rejects this program as expected.
Code
// TEST: fmt:ln scratch-borrow lifetime — the produce-edge refusal.
//
// Every fmt:ln call site emits its own threadlocal 4KiB scratch and `.text`
// borrows it, so two bindings of one site's `.text` are two names over ONE
// buffer — the next execution overwrites the first. `l` therefore carries
// `string<scratch@scoped>`: a frame-bound borrow that may be read in place
// but may never occupy a produced/output position. `-> l.text` below is
// exactly that escape — refused at compile time.
//
// The legal shapes are consume-in-place (`|> std/io:print.ln(l.text)` —
// 620_002) and copy-out (`std/string:from-page` + `take`, or `fmt.blk`).
// Contract: koru_std/fmt.kz above `pub tor ln`; the `@class` grammar is
// koru_std/phantom_parser.zig.
import std/fmt
import std/io
tor render { n: i64 } -> string
render = std/fmt:ln("item {{ n:d }}"): l -> l.text
render(n: 1): a |> render(n: 2): b |> std/io:print.ln(a) |> std/io:print.ln(b)
Actual compiler output
error[KORU030]: 'l.text' is @scoped — it dies with this frame and may not be produced out. Consume it in place, or copy it out first (std/string:from-page + take / fmt.blk)
--> tests/regression/600_STDLIB/620_FMT/620_011_fmt_ln_scratch_borrow_overwrites/input.k:20:1Must fail at runtime:
Program must error when executed.
Error output must contain
'l.text' is @scopedFlows
subflow ~render click a branch to expand · @labels scroll to their anchor
ln ("item {{ n:d }}")
flow ~render click a branch to expand · @labels scroll to their anchor
render (n: 1)
Test Configuration
MUST_ERROR