✗
Failing This test is currently failing.
Failed: backend-exec
Failure Output
error[KORU161]: std/store:new(batch): `! discharge` binds the column itself - spell it `! discharge item |> ...(<param>: item)`
--> tests/regression/600_STDLIB/690_STORE/690_109_bare_drain_arm_threads_its_column/input.k:33:0 Code
// The drain arm names nothing, and its column threads into the drain call.
//
// ! discharge |> app/lib/pend:cancel()
//
// At ONE owned column the arm's payload IS the value (arity picks the payload
// shape), and the drain call has exactly one unfilled parameter of exactly that
// type — so there is one candidate for one slot, and the by-type fill
// (210_191/192/194) has one reading. Naming a binder buys nothing here: it exists
// only to be written twice, once to bind and once to pass.
//
// This is the last position in the one-column arc still holding a name. The
// declaration spells the column bare, `| item` and `| full` hand back the value,
// and a one-column store's watch arm IS the store (690_102/103). The drain arm's
// binder is the same shape one step further in.
//
// The column carries <open!> and `cancel` consumes <!open>, so the fill IS the
// disposal — there is no separate binding left over to auto-discharge.
//
// BOUNDARY: this is a one-column rule. At two columns the payload is a record and
// the name is how a column is reached, which 690_097 pins with
// `! discharge item |> commit(item.tx)`.
//
// 690_106 is this program with a binder and a written label; 690_107 is the
// halfway spelling that binds and then omits the label. Whether a binder stays
// LEGAL-but-unnecessary at one column or becomes refused the way a named column
// is refused on a watch arm is a separate ruling; this pin only says the bare
// form threads.
import std/io
import std/store
import app/lib/pend
std/store:new(batch, capacity: 2) { *app/lib/pend:Pending<open!> }
! discharge |> app/lib/pend:cancel(): n |> std/io:print.ln("cancelled {{ n:d }}")
app/lib/pend:start(): p |> std/store:insert(batch) { p }
| row _ |> _
std/io:print.ln("inserted")
Must contain:
insertedFlows
flow ~new click a branch to expand · @labels scroll to their anchor
new (expr: batch, capacity: 2, source: *app/lib/pend:Pending<open!>)
flow ~start click a branch to expand · @labels scroll to their anchor
start
flow ~print.ln click a branch to expand · @labels scroll to their anchor
print.ln (expr: "inserted")
Imported Files
// An owned resource with ZERO dischargers a store can fire: *Pending<open!> is
// consumed only by `cancel`, and `cancel` hands back a value. A store tears its
// elements down unattended, where there is nobody to take a return — so the
// column cannot be auto-discharged at any count, and must be DRAINED by a
// `! discharge` arm bolted onto the declaration.
//
// This is the shape koru/curl:Pending has in koru-examples/downloads, where
// `~pub tor cancel { p: *Pending<!open> } -> *Multi<owned!>` returns the batch.
// An i64 return carries the same property without a second obligation.
//
// The contrast is app/lib/tx (690_057/058/097): TWO void dischargers, so the
// store could fire either and refuses because it cannot pick. Here there is
// nothing to pick from.
const std = @import("std");
const Pending = struct { id: i32 };
~pub tor start { } -> *Pending<open!>
~proc start|zig {
const p = std.heap.page_allocator.create(Pending) catch unreachable;
p.* = .{ .id = 3 };
return p;
}
~pub tor cancel { p: *Pending<!open> } -> i64
~proc cancel|zig {
const id = p.id;
std.heap.page_allocator.destroy(p);
return id;
}