✓
Passing This code compiles and runs correctly.
Code
// WALL (spec): once a field's obligation is discharged, discharging it again is a
// use-after-discharge — the field vanished from s's type. Target diagnostic is the
// existing use-after-discharge message ('already discharged', phantom_semantic_
// checker.zig:2597), NOT 'carries no obligation'. The distinction is the whole
// point: 'already discharged' names a debt that was paid, 'carries no obligation'
// names a debt the checker cannot see — one is the user's error, the other is
// the compiler's, and they must never be spelled the same way.
~import std/io
const std = @import("std");
const Handle = struct { n: i32 };
~tor dispose { x: *Handle<!owned> }
~proc dispose|zig { std.heap.page_allocator.destroy(x); }
~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 }; }
~make2(id: 1): s |> dispose(x: s.h): _ |> dispose(x: s.h): _ |> std/io:print.ln("double")
Backend must reject with:
CONTAINS error[KORU030]
CONTAINS already dischargedFlows
flow ~make2 click a branch to expand · @labels scroll to their anchor
make2 (id: 1)