✓
Passing This code compiles and runs correctly.
Code
// FEATURE SPEC (field-granular obligation narrowing): a record with two
// obligation fields {h!, g!} must be dischargeable field-by-field. dispose(x: s.h)
// consumes h and narrows s to {g}, which collapses to the scalar (210_149),
// poisoning the base s while s.g stays projectable; dispose(x: s.g) clears the
// last one. All obligations paid -> clean run. Same surface as 610_001's
// `| ok s |> ... |> free(s)` (bound name referenced down-chain), field-projected.
//
// This is the family's positive spec and its control: the producer sits at the
// HEAD of the chain, which is the only position the 330_101-109 family covers.
// 330_116 is this same program with one void call prepended, and the two must
// agree — position in a chain says nothing about whether a field carries a debt.
~import std/io
const std = @import("std");
const Handle = struct { n: i32 };
~tor make2 { id: usize } -> { h: *Handle<owned!>, g: *Handle<owned!> }
~proc make2|zig {
const h = std.heap.page_allocator.create(Handle) catch unreachable;
const g = std.heap.page_allocator.create(Handle) catch unreachable;
h.* = .{ .n = 1 }; g.* = .{ .n = 2 };
return .{ .h = h, .g = g };
}
~tor dispose { x: *Handle<!owned> }
~proc dispose|zig { std.heap.page_allocator.destroy(x); }
~make2(id: 1): s |> dispose(x: s.h): _ |> dispose(x: s.g): _ |> std/io:print.ln("clean")
Actual
clean
Expected output
clean
Flows
flow ~make2 click a branch to expand · @labels scroll to their anchor
make2 (id: 1)
Test Configuration
MUST_RUN