Integer Types

Signed Integer Types

A signed integer type is one of: i8, i16, i32, i64, or isize.

The type i8 represents signed integers in the range [-128, 127].

The type i16 represents signed integers in the range [-32768, 32767].

The type i32 represents signed integers in the range [-2147483648, 2147483647].

The type i64 represents signed integers in the range [-9223372036854775808, 9223372036854775807].

The type isize is a signed integer type whose size equals the target platform's pointer size. On 64-bit targets, isize has the same range as i64.

Signed integer arithmetic that would overflow the representable range of the result type MUST wrap around modulo 2^N, where N is the bit width of the type. The result is the unique value in the type's range that is congruent to the mathematical result modulo 2^N.

fn main() -> i32 {
    let a: i8 = 127;
    let b: i16 = 32767;
    let c: i32 = 2147483647;
    let d: i64 = 9223372036854775807;
    0
}

Unsigned Integer Types

An unsigned integer type is one of: u8, u16, u32, u64, or usize.

The type u8 represents unsigned integers in the range [0, 255].

The type u16 represents unsigned integers in the range [0, 65535].

The type u32 represents unsigned integers in the range [0, 4294967295].

The type u64 represents unsigned integers in the range [0, 18446744073709551615].

The type usize is an unsigned integer type whose size equals the target platform's pointer size. On 64-bit targets, usize has the same range as u64.

Unsigned integer arithmetic that would overflow the representable range of the result type MUST wrap around modulo 2^N, where N is the bit width of the type.

Integer Literal Type Inference

An integer literal without explicit type annotation defaults to type i32.

When an integer literal appears in a context where the expected type is known (e.g., assignment to a typed variable), the literal is inferred to have that type.

fn main() -> i32 {
    let x = 42;           // x has type i32 (default)
    let y: i64 = 100;     // 100 is inferred as i64
    0
}

Integer Literal Range Validation

A compiler MUST reject programs where an integer literal value exceeds the representable range of its target type.

When an integer literal is the operand of a unary negation operator, and the negated value would be representable in the target signed integer type, the expression is valid even if the literal value itself exceeds the positive range of that type. This allows the minimum value of each signed integer type to be written as a negated literal.

fn main() -> i32 {
    let a: i8 = -128;                       // valid: -128 is in i8 range
    let b: i8 = 128;                        // error: 128 exceeds i8 range
    let c: i32 = -2147483648;               // valid: i32 minimum value
    let d: i64 = -9223372036854775808;      // valid: i64 minimum value
    0
}
fn main() -> i32 {
    let x: i8 = 128;           // error: literal out of range for i8
    let y: u8 = 256;           // error: literal out of range for u8
    let z: i32 = 9999999999;   // error: literal out of range for i32
    0
}