✓
Passing This code compiles and runs correctly.
Code
// BOUNDARY (MUST_ERROR): you may NOT discharge an outer-scope obligation inside a
// scope. `h0 <owned!>` is owned OUTSIDE the `for`; `take(h: h0)` consumes it
// INSIDE the @scope. Correctly rejected with KORU032.
//
// THE RULE — obligations and scopes, in full (this test pins clause 1):
// 1. Inside a scope you may NOT discharge an obligation owned OUTSIDE the scope.
// (This test — rejected.)
// 2. Inside a scope you MAY issue obligations and discharge them locally.
// 3. From an effect branch OR a continuation branch you MAY let an issued
// obligation ESCAPE the scope — but then the event owning that branch must
// handle it: discharge it in its own implementation, or pass it on to
// another continuation/effect branch.
//
// WHY THIS MUST BE REJECTED (it is NOT a checker gap — see 330_072 history):
// A `for`/effect body is a 0-to-N scope. Consuming the OUTER `h0` "once" only
// type-checks if the scope runs exactly once; on any re-fire it is a
// double-consume of an already-poisoned binding. Re-issuing `<owned!>` on the
// popped `v` does NOT rehabilitate `h0` — `v` is a DIFFERENT obligation on a
// DIFFERENT binding. There is no "conservation" that licenses the outer
// consume; the earlier conserved-move reading was simply wrong.
//
// THE SOUND WAY to carry an obligation through a loop is GREEN 330_074: ISSUE it
// from a leaf inside the scope and let it ESCAPE to an outside disposer (clause 3)
// — never consume an outer binding in-scope. GREEN 330_083 shuttles by issuing
// FRESH handles each lap. Both honor the rule; this test deliberately breaks it.
//
// EXPECTED: KORU032 "Cannot discharge outer-scope resource ... inside @scope".
const std = @import("std");
const Handle = struct { n: i32 };
~tor make {} -> *Handle<owned!>
~proc make|zig {
const h = std.heap.page_allocator.create(Handle) catch unreachable;
h.* = .{ .n = 7 };
return h;
}
// Take the owned handle "out of A": consume the incoming hold, reissue it on the
// popped value (the collection-memory pop-reissue move, hand-rolled).
~tor take { h: *Handle<!owned> } -> *Handle<owned!>
~proc take|zig {
return h;
}
// Put the owned handle "into B": consume the obligation.
~tor put { h: *Handle<!owned> }
~proc put|zig {
std.debug.print("moved n={}\n", .{h.n});
std.heap.page_allocator.destroy(h);
}
~make(): h0 |> for(0..1)
! each _ |> take(h: h0): v |> put(h: v)
| done |> _
Must contain:
Cannot discharge outer-scope resourceFlows
flow ~make click a branch to expand · @labels scroll to their anchor
make