Issue #470: A written usize, i16, u128 or str is NK1135 outside extern "C" (ADR-286 D36); f32 joins the language in #552

Open and answer this issue on GitHub.

language, compiler, ready · opened 2026-10-05 · updated 2026-10-08 · 1 comment

How it came up

While checking #467’s remaining limit (a use that asks for another width — i16, usize — still reads the const), the following program reached rustc:

fn small() -> i64 {
    return 7
}

fn take_usize(x: usize) -> usize {
    return x
}

fn take_i16(x: i16) -> i16 {
    return x
}

comptime S = small()

fn main() {
    println(f"{take_usize(S)} {take_i16(S)}")
}

nikaia run reports rustc’s Mismatched types … You can convert an i64 to an i16. The checker said nothing. The same happens without any comptime: fn take(x: i16) with let y: i16 = 3 passes the checker for usize, i16, i8 and f32. A made-up name (Foo) gets NK1135.

What is decided today

So the specification does not offer these types but does not say that writing one is refused. Only as is refused, and the test expects the opposite. Today the program goes on to rustc and fails there on a file nobody wrote.

Question for the deciding session

Outside an extern "C" declaration, is a written usize, isize, i8, i16, u16, i128, u128 or f32 refused by the checker?

(a) matches what 2.2 says now. Under (a), undeclared_type.rs’s case flips, and the extern tests stay as they are.

Comments

keywan-ghadami, 2026-10-08

Decided (owner, 2026-10-08): (a) refused with NK1135, except f32, which joins the language

How it was answered. #509 was decided first, as ADR-286 D36: what is written down is what can be called, and a name Rust has and Nikaia does not is refused. D36 speaks of members (methods, functions, fields), so it did not cover a written type’s name. The owner confirmed that the same principle holds there. f32 is the exception: in the owner’s words it is “clearly an issue”, a type the language should have. It is not a Rust-only name to refuse.

Checked (develop, 0.0.700). fn take(x: T) -> T passes the checker for usize, i16, i8, f32 and u128, while Foo is NK1135. The cause is types.nika’s BUILT_IN, which lists every Rust primitive and also str.

Where it is written (0.0.701)

To build

  1. BUILT_IN in crates/nikaia-std/src/tools/types.nika keeps only the language’s types. usize, isize, i8, i16, u16, i128, u128 and str leave it. f32 stays, for #552.
  2. NK1135 for those names, with the help i64 (integers) or String (str), and a note naming the language’s number types. Inside an extern "C" declaration nothing changes.
    • Tests: fn take(x: usize), let y: i16 = 3 and fn f(s: str) are each NK1135 with the help.
    • tests/foreign_pointers.rs stays green.
    • tests/undeclared_type.rs::every_kind_of_declared_name_is_left_alone flips for usize and i128; u8 stays accepted.
  3. #467’s remaining limit (a use that asks for another width) disappears with step 2, since no such width can be written. Note this on #467.

Generated by Claude Code

Back to Open Issues