○
Planned This feature is planned but not yet implemented.
Cascading auto-discharge: discharge creates new obligations that also need discharging
Failure Output
Showing last 10 of 49 lines
--> auto_discharge:48:0
❌ Compiler coordination error: Auto-discharge failed (multiple disposal options or no disposal event)
error: CompilerCoordinationFailed
/Users/larsde/src/koru/tests/regression/300_ADVANCED_FEATURES/330_PHANTOM_TYPES/330_055_auto_discharge_cascade/backend.zig:9584:17: 0x102d82433 in emit (backend)
return error.CompilerCoordinationFailed;
^
/Users/larsde/src/koru/tests/regression/300_ADVANCED_FEATURES/330_PHANTOM_TYPES/330_055_auto_discharge_cascade/backend.zig:9668:28: 0x102d831bf in main (backend)
const generated_code = try RuntimeEmitter.emit(compile_allocator, final_ast);
^ Code
~import app/db
const std = @import("std");
~app/db:connect(host: "localhost")
| connected _ |> app/db:begin(_.conn)
| begun _ |> app/db:do-work(_.tx)
pub fn main() void {
std.debug.print("Cascading auto-discharge test\n", .{});
}
Imported Files
// Database module with cascading phantom obligations
//
// connect() → Connection[connected!]
// begin() → Transaction[in_transaction!] (consumes connected)
// commit() → Connection[connected!] (consumes in_transaction, CREATES connected!)
// close() → void (consumes connected)
const std = @import("std");
const Connection = struct { handle: i32 };
const Transaction = struct { conn: *Connection };
// connect: creates connection obligation
~pub event connect { host: []const u8 }
| connected *Connection<connected!>
~proc connect|zig {
const c = std.heap.page_allocator.create(Connection) catch unreachable;
c.* = Connection{ .handle = 42 };
return .{ .connected = c };
}
// begin: consumes connection, creates transaction obligation
~pub event begin { conn: *Connection<!connected> }
| begun *Transaction<in_transaction!>
~proc begin|zig {
const tx = std.heap.page_allocator.create(Transaction) catch unreachable;
tx.* = Transaction{ .conn = conn };
return .{ .begun = tx };
}
// commit: consumes transaction, CREATES connection obligation
// Marked [!] as default discharge for transactions
~[!]pub event commit { tx: *Transaction<!in_transaction> }
| committed *Connection<connected!>
~proc commit|zig {
const c = tx.conn;
std.heap.page_allocator.destroy(tx);
return .{ .committed = c };
}
// close: consumes connection obligation, returns void
// Marked [!] as default discharge for connections
~[!]pub event close { conn: *Connection<!connected> }
~proc close|zig {
std.heap.page_allocator.destroy(conn);
return .closed;
}
// do-work: uses transaction without consuming it
~pub event do-work { tx: *Transaction<in_transaction> }
| done *Transaction<in_transaction>
~proc do-work|zig {
std.debug.print("Working with transaction...\n", .{});
return .{ .done = tx };
}