ADR-249: A Number Without an Annotation Is Typed by Its Uses, and This Compiler Decides It

Status: Superseded by ADR-285 — its D1-D3 are D23-D25, D4 is D27, D5 is D30 there Date: September 28, 2026 Target Version: Nikaia 0.0.251 Supersedes: ADR-060 D3 (“there is no second answer for a use to ask for, and nothing to find out”) Narrows: ADR-063 D2 (“a bare let pins the type its own value took” - the type its uses decide, and the first that holds its value only where none does) Related: ADR-048 D1 (a length and an index are i64), ADR-248 (u64 and u32), ADR-135 D2 (an empty list’s element type comes from its use, asked once the body is walked), Part I 2.4, #176 and #177

1. Context

Part I 2.4 says it already: a number takes the type its use asks for, and the first type that holds it where nothing asks. ADR-060 D1 kept the first half and said how - it was the language below’s inference, “inherited and working”: the let was written bare, and rustc looked at the uses. D3 then argued that nothing more was needed, because “a literal that does not hold in an i32 can only be an i64“.

Both halves of that have stopped holding.

A program’s author does not see either failure as theirs, and neither is: the line says what it means, and the answer is in the uses. The uses are this compiler’s to read.

2. Decisions

D1 - A let without an annotation whose value is only numbers is an open number.

A literal, a sum of literals, or an operation over other open numbers: let i = 0, let big = 3000000000, let c = a + b over two open a and b. An operation joins its sides: a + b, a < b and c = a + b make one number of all of them, because one operation has one type. A shift’s count is any integer and joins nothing.

D2 - Its uses ask for its type, and every use in the function is read before it is decided.

A use asks where a type stands beside the number:

An index asks for an i64, and only where nothing else asks: a length and an index are i64 (ADR-048 D1), and the language below takes any integer through index::at - so an index is a preference, never a conflict.

Two uses that ask for two types are refused (NK1200), naming both, with the annotation to write. It is the program rustc refused as mismatched types about the generated file.

D3 - Where no use asks, what it is given decides.

Its own value and every one assigned to it: the first type that holds all of them, i32, else i64 - ADR-060 D2, over every value rather than the first. let mut n = 1 then n = 3000000000 is an i64.

Every value it is given has to fit the type decided, and one that does not is NK1116 at that value, with a note that the type came from the uses. What an operation over it comes to is held to the type too, and never decides it: a name is still where the widening stops (ADR-063 D2), so let a = 2000000000 then let c = a + a is refused where nothing asks and an i64 where a use asks for one.

D4 - The type decided is written into the generated let.

let i: i64 = 0; - so the language below infers nothing this compiler decided, and a literal the emitter would give an i64’s suffix carries the decided type’s instead. A number no use asked for is written as before: the language below’s default is D3’s, and a bare let stays bare.

D5 - A constant operation that overflows is refused where it stands.

Not only at a let, a return and an argument (ADR-043 D5): in an f"…" hole, a condition, a list, a receiver - once, at the innermost operation that overflows, and not again by the statement around it. An operation over an open number is measured once that number’s type is decided (D3).

3. Consequences

4. Considered and rejected

The first type that holds the value, full stop (Kotlin’s rule, and ADR-060 §4’s alternative). Simpler, and let a = 1 beside an i64 b would be NK1199 - a program that compiles today, and that Part I 2.4’s own example (wide(small)) is.

index::at::<i64>(i) where the index has no type. Mends #177 at the one site and collides with the first use that asks for anything else.

An index as a use like any other. It would make let i = 0 handed to an i32 and used as an index a conflict, where the language below converts either.

5. What is built

Built at 0.0.251.

This site is open source. Improve this page.