✓
Passing This code compiles and runs correctly.
Code
// TEST: pass a Transaction where a Connection is expected — refused by Koru's
// own front end, with no flag.
//
// close() expects: *Connection<!active>
// this passes: *Transaction<active!>
//
// The phantom STATE matches on both sides (active), so state checking alone
// waves it through; what refuses it is the base-type check, comparing the
// type's own name and seeing Connection against Transaction.
//
// Until 2026-08-10 this pinned a ZIG error naming Koru's generated module
// paths, because the base-type check sat behind --strict-base-types and was off
// by default. It pins a Koru diagnostic now, and the flag no longer exists.
import app/db
// The handler below passes t (*Transaction) to close(), which takes a
// *Connection.
app/db:connect(host: "localhost")
| ok c |> app/db:begin(conn: c)
| ok t |> app/db:close(conn: t)
| err _ |> _
| err _ |> _
Flows
flow ~connect click a branch to expand · @labels scroll to their anchor
connect (host: "localhost")
Imported Files
// Database module with Connection and Transaction as IDENTICAL struct layout
// Both have phantom states with the SAME NAME
// The ONLY difference is the semantic TYPE NAME
const std = @import("std");
// BOTH are structurally identical - just an i32 handle!
const Connection = struct { handle: i32 };
const Transaction = struct { handle: i32 }; // Same layout as Connection!
// connect: produces *Connection<active!>
~pub tor connect { host: string }
| ok *Connection<active!>
| err string
~proc connect|zig {
const c = std.heap.page_allocator.create(Connection) catch unreachable;
c.* = Connection{ .handle = 42 };
return .{ .ok = c };
}
// begin: consumes *Connection<!active>, produces *Transaction<active!>
// NOTE: Transaction also has <active!> - same state name as Connection!
~pub tor begin { conn: *Connection<!active> }
| ok *Transaction<active!>
| err string
~proc begin|zig {
const tx = std.heap.page_allocator.create(Transaction) catch unreachable;
tx.* = Transaction{ .handle = conn.handle };
std.heap.page_allocator.destroy(conn);
return .{ .ok = tx };
}
// close: consumes *Connection<!active>
// This should ONLY accept Connection, NOT Transaction!
~pub tor close { conn: *Connection<!active> }
~proc close|zig {
std.debug.print("Connection closed (handle={})\n", .{conn.handle});
std.heap.page_allocator.destroy(conn);
}
// commit: consumes *Transaction<!active>
// This should ONLY accept Transaction, NOT Connection!
~[!]pub tor commit { tx: *Transaction<!active> }
~proc commit|zig {
std.debug.print("COMMIT (handle={})\n", .{tx.handle});
std.heap.page_allocator.destroy(tx);
}
Test Configuration
Expected Error:
error[KORU030]: Type mismatch: expected 'app.db:*Connection<!active>' but got 'app.db:*Transaction<app.db:active!>' for argument 'conn'