int: the values of an i64, its representation the compiler’s choice; a fixed width is exact and is written where the representation showsOpen and answer this issue on GitHub.
ready · opened 2026-10-17 · updated 2026-10-17 · 2 comments
The owner noticed confusion about when an integer type must or should be written. A read-only analysis (October 17, 2026) checked today’s rules (ADR-285), counted the annotations and compared other languages:
tools/*.nika holds 2,175 integer type tokens, almost all i64; 72% are in signatures and fields, where the grammar requires a type, 17% are casts, 10% are on lets. examples/ and guide/ already write none on a let.i64 stand outside any extern, nearly all deliberate: u32 spans, FNV/CHD hashes, the SAT solver’s layout (ADR-270 D10/D16), bytes, row ids (ADR-299), 1BRC’s 24-byte Stats.let mut total = 0 summed over text.bytes() is inferred u8 and aborts on “hello world”; a counter nothing types stays i32 and aborts past 2³¹; NK1200 suggests as where i32 → i64 needs none.The first proposal on the table, widths only at the C/Rust interfaces, a warning elsewhere, was dropped: it would fire on the deliberate widths, and no surveyed language warns about a written width.
The owner’s direction then: i32 was preferred as a fallback to keep room for optimisation (32-bit targets, SIMD lanes, smaller lists). But because an overflow aborts, a narrower type changes what a program computes. The room belongs in the representation: as with String, where the compiler chooses between borrowing and owning without changing the result, the compiler may choose an integer’s width where nothing observable changes. And a programmer who writes i64 expects exactly that; so the soft promise needs a name of its own: int.
ADR-285 D36-D39:
int holds the values of an i64 and aborts where an i64 would; int and i64 take each other without as.i64, i32, u8, u32 or u64 is exactly that width in memory and in arithmetic.extern "C", a described Rust contract), a fixed width is written; int there is refused.int is the integer ordinary code writes; a fixed width says the width is the point.Not decided here (ADR-285 §6): whether a number no use asks about falls back to int instead of i32 (D21); whether an arithmetic operand may narrow an open number (the u8 byte sum); an integer bound for generics (fn f[T: Integer]); whether len() and an index become int; a hint for an i64 where int would do; which narrower representations are built, and when.
Prerequisite: #629 (D-1 to D-3), so that no annotation change can turn an abort into a wrong value.
int (D36, D37) and the rule of thumb (D39: int for most numbers, a fixed width where the width is the point); Part I 2.4 says int and i64 take each other; Part III’s table gains a code for int in an extern "C" signature or a described contract (D38).int in tools/types.nika as a built-in type with every rule of i64; int ↔ i64 without as in both directions; the D38 refusal. Tests: fn f(a: int) -> int { return a + 5 } checks and runs; let x: i64 = f(1) checks without as; extern "C" fn g(n: int) is refused with the new code; int overflow aborts at the i64 bound (9223372036854775807 + 1 read at run time).int is emitted as i64 (D37 allows no narrowing yet). Test: the generated Rust of the program in 2 equals that of the same program written with i64.lower-std, commit package.rs.guide/ and examples/: write int where the width is not the point (no version raise).tools/*.nika: move to int when a file is next reworked; not in bulk.Vec[i32] against Vec[i64], and one SIMD kernel; then a decision round on which narrowings to build first.Step 1 (specification) is done in d0231d7 (0.0.976): Part I 2.2 gains int beside the five fixed widths, and Part III C.3 gains NK1262 for an int in an extern "C" signature or a described Rust contract. Steps 2 to 7 are still open, with #629 as the prerequisite.
Generated by Claude Code
Steps 2 to 5 are built. The prerequisite #629 (D-1 to D-3) came first:
as out of an open number is checked, and a method called on one no longer makes the function async.int is a built-in type. The checker reads it as i64 (declared::written_ty), so it follows every rule of i64 and the two convert without as in both directions.i64, so the Rust is the same as for the program written with i64.NK1262 covers extern fn, extern struct and extern { } declarations.package.rs is re-lowered.crates/nikaia/tests/integer_types.rs.guide/syntax.md and the tally and inventory examples now use int.What is still open:
NK1262 in a described Rust contract (contracts/<crate>.contracts). This is not built. When a ledger fails to parse today, the file is dropped (Ledger::read_beside returns None), and nothing reports a finding with a location. The refusal needs a way to report from a ledger first.tools/*.nika to int when each file is next reworked.int as i64, because the checker reads it as one.int parameter of an extern fn gets NK1240 (cannot cross to C) next to NK1262. The second message is redundant.Generated by Claude Code