Summary
An integer literal is typed i32 with no implicit widening and no cast operator, so literals fail to combine with i64 values in most expression positions. Yet the same literals coerce fine in let-with-annotation and struct/array field initializers. The result is that nearly every i64 constant must be hoisted into its own let, which is heavy boilerplate for any fixed-point / i64-centric code.
Where literals do NOT coerce (all fail with i64 vs i32)
pub fn f(a: i64) -> i64 { return a << 16; } // Shl operands differ: i64 vs i32
pub fn g(a: i64) -> i64 { return a + 65536; } // Add operands differ
pub fn h(a: i64) -> i64 { if a < 65536 { ... } } // Lt operands differ
pub fn k(a: i64) -> i64 { return id(a, 65536); } // arg 2 expected i64, found i32
pub fn m() -> i64 { return 65536; } // return: expected i64, found i32
pub fn n() -> i64 { return -42; } // unary minus literal: i32
Where they DO coerce
let x: i64 = 65536; // ok (let annotation)
let v: Vec3 = Vec3 { x: 65536 }; // ok (struct field init)
let a: [i64; 2] = [1, 2]; // ok (array element init)
Also: no integer-literal suffix parses
pub fn f(a: i64) -> i64 { return a << 16i64; } // parse error
pub fn g(a: i64) -> i64 { return a << 16_i64; } // parse error
Impact
The only way to get an i64 constant into an operator/argument/return is to bind it first:
// instead of (a * b) >> 16
let sh: i64 = 16;
return (a * b) >> sh;
In fixed-point code (Q16.16, everything i64) this means a let n: i64 = …; preamble for essentially every numeric constant — a large, repetitive tax that also hurts readability.
Suggested directions
- Propagate the expected type into operands of binary ops, call arguments, and return expressions (bidirectional checking), so a literal unifies with the
i64 it's used against — the same coercion already applied at let/field initializers.
- And/or support typed integer-literal suffixes (
16i64, 16_i64).
Environment: infc 0.0.1 (commit df45600, ABI 1.0), Inferara/inference @ d82d935 (wasm-linker). Found while implementing a fixed-point ray tracer entirely in Inference (scratch/raytracing-in-one-weekend).
Summary
An integer literal is typed
i32with no implicit widening and no cast operator, so literals fail to combine withi64values in most expression positions. Yet the same literals coerce fine inlet-with-annotation and struct/array field initializers. The result is that nearly everyi64constant must be hoisted into its ownlet, which is heavy boilerplate for any fixed-point /i64-centric code.Where literals do NOT coerce (all fail with
i64vsi32)Where they DO coerce
Also: no integer-literal suffix parses
Impact
The only way to get an
i64constant into an operator/argument/return is to bind it first:In fixed-point code (Q16.16, everything
i64) this means alet n: i64 = …;preamble for essentially every numeric constant — a large, repetitive tax that also hurts readability.Suggested directions
i64it's used against — the same coercion already applied atlet/field initializers.16i64,16_i64).Environment:
infc0.0.1 (commitdf45600, ABI 1.0),Inferara/inference@d82d935(wasm-linker). Found while implementing a fixed-point ray tracer entirely in Inference (scratch/raytracing-in-one-weekend).