OWED: signed runtime `/` and `%` emit Zig `@divTrunc` (or equivalent), not bare `/`.
Error Details
output_emitted.zig:84:22: error: division with 'i64' and 'comptime_int': signed integers must use @divTrunc, @divFloor, or @divExact
Failure Output
🎯 Compiler coordination: Passes: 20 (flow-based: elaborate, analysis, emission)
Error: output_emitted.zig:84:22: error: division with 'i64' and 'comptime_int': signed integers must use @divTrunc, @divFloor, or @divExact
return n / 2;
~~^~~
referenced by:
handler [inlined]: output_emitted.zig:78:39
__koru_handler_impl: output_emitted.zig:101:55
5 reference(s) hidden; use '-freference-trace=7' to see all references Code
// RED BY DESIGN (pinned 2026-07-25). `/` and `%` on a SIGNED runtime operand
// emit bare Zig `/` and `%`, which Zig rejects:
//
// error: division with 'i64' and 'comptime_int': signed integers must use
// @divTrunc, @divFloor, or @divExact
//
// A raw host error, not a koru diagnostic — the wall is not built here yet.
//
// SHOWN 2026-07-25, characterised: signed `/` fails, signed `%` fails, UNSIGNED
// `/` works (usize prints 5), signed `*` works. So it is specific to signed
// division and remainder, not arithmetic generally.
//
// Why it survived: koru's own COMPTIME evaluator already gets this right —
// src/comptime_eval.zig uses @divTrunc/@rem and its comment calls that "the
// C-parity choice". The runtime emitter has no matching lowering, and the
// corpus has zero tests dividing a signed runtime value (everything divides
// literals, which const-fold, or divides usize). Comptime and runtime disagree
// about the same operator.
//
// Found from the outside: building a multi-file ledger app in koru-examples,
// where `cents / 100` compiled while the entry passed a literal and broke the
// moment a second module passed the value through at runtime.
//
// Fix direction (unruled): emit @divTrunc/@rem for signed operands, matching
// comptime_eval's C-parity choice, or reject with a koru-level diagnostic that
// names the operand signedness. Either beats leaking Zig's builtin list.
import std/io
pub tor f { n: i64 } -> i64
f -> n / 2
pub tor go { n: i64 } -> i64
go = f(n): h -> h
go(n: 10): x |> std/io:print.ln("half={{ x:d }}")
Expected output
half=5
Flows
Test Configuration
Awaiting ruling:
Signed runtime `/` and `%`: lower them to `@divTrunc`/`@rem`, or refuse them with a Koru diagnostic that names the operand's signedness? Both beat what happens today, which is Zig's own error reaching the user verbatim — "signed integers must use @divTrunc, @divFloor, or @divExact" — a raw host error with Zig's builtin list in it. The asymmetry that makes this a decision and not a bug report: koru's COMPTIME evaluator already answers it one way. src/comptime_eval.zig uses `@divTrunc`/`@rem` and its own comment calls that "the C-parity choice". The runtime emitter has no matching lowering, so comptime and runtime disagree about the same operator. Characterised 2026-07-25: signed `/` fails, signed `%` fails, unsigned `/` works, signed `*` works. Options: - lower it, matching comptime_eval's C-parity choice — this test goes green as written; - refuse it in Koru, naming the signedness — this pin flips to MUST_ERROR with that diagnostic as its expectation. Blocks: this test, and the class it stands for. The corpus has zero other tests dividing a signed runtime value — everything divides literals (const-folded) or divides usize — which is how it survived. Found from outside, in a koru-examples ledger app where `cents / 100` compiled until a second module passed the value at runtime.