Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The as operator in Rust is a binary operator used for explicit, compile-time type casting of primitive types, raw pointers, and non-capturing closures. It performs infallible, mechanical conversions that do not require runtime type checking or trait implementations (such as From or Into).
expression as TargetType

Mechanical Behavior

The as operator operates strictly on the bit-level representation or predefined primitive mappings. Its behavior depends on the source and target types:

Numeric Casting

  • Widening: Casting to a larger integer type zero-extends unsigned integers and sign-extends signed integers.
  • Narrowing (Truncation): Casting to a smaller integer type truncates the higher-order bits. This can result in a completely different numeric value.
  • Signedness Reinterpretation: Casting between signed and unsigned integers of the exact same bit-width is a no-op at the machine level. It reinterprets the existing two’s complement bit pattern.
  • Float to Float: Widening (f32 to f64) is exact. Narrowing (f64 to f32) rounds to the nearest representable value, or to infinity if the value exceeds the maximum finite f32 bounds.
  • Float to Integer: Truncates the fractional part towards zero. If the floating-point value exceeds the maximum or minimum bounds of the target integer type, the result saturates to the boundary value of that integer type. NaN values cast to 0.
  • Integer to Float: Produces the closest representable floating-point value. If the integer requires more precision than the float provides, it rounds according to IEEE 754 rules.

Primitive Casting

  • bool to Integer: false casts to 0, and true casts to 1. (Note: Rust does not allow casting integers back to bool via as).
  • char to Integer: Casts the Unicode scalar value to an integer (u8, u16, u32, u64, etc.). If cast to a type smaller than u32, the value is truncated.
  • Integer to char: Only u8 can be cast directly to char using the as operator. Larger integer types cannot be cast to char via as because they might not represent valid Unicode scalar values.
  • enum to Integer: Fieldless enums (C-like enums) can be cast to integers matching their discriminant values.

Closure Casting

  • Closures to Function Pointers: Non-capturing closures can be cast to function pointers (fn types) that match their parameter and return type signatures. Closures that capture environment variables cannot be cast this way.

Pointer Casting

Pointer casting rules strictly depend on the distinction between sized (thin) pointers and unsized (fat) pointers. Thin pointers point to sized types (T: Sized). Fat pointers point to dynamically sized types (DSTs) like slices ([T]) or trait objects (dyn Trait) and carry additional metadata (a length or a vtable).
  • References to Raw Pointers: &T casts to *const T, and &mut T casts to *mut T.
  • Raw Pointer Mutability: *const T casts to *mut T (casting away constness strictly requires the as operator). Conversely, *mut T casts to *const T.
  • Raw Pointer Type Changes: *const T casts to *const U (and similarly for mutable pointers) only if both T and U are sized (thin pointers), or if both are unsized (fat pointers) and share the exact same metadata type (e.g., casting between two slice pointers). You cannot cast a thin pointer to a fat pointer using as because the compiler lacks the metadata required to construct the unsized type.
  • Pointers to Integers: Thin raw pointers and function pointers cast to integer types (typically usize to match the architecture’s pointer width). Fat pointers cannot be cast directly to integers.
  • Integers to Pointers: Integers cast to thin raw pointers, interpreting the integer value as a memory address. Integers cannot be cast to fat pointers.

Syntax Visualization

// Numeric & Primitive Conversions
let a: u16 = 255u8 as u16;           // Zero-extension: 255
let b: u8 = 256u16 as u8;            // Truncation: 0
let c: u8 = 300.0f32 as u8;          // Saturates to MAX: 255
let d: u32 = 'A' as u32;             // Unicode scalar: 65
let e: char = 65u8 as char;          // u8 to char: 'A'

// Closure to Function Pointer
let closure = |x: i32| x + 1;
let func_ptr: fn(i32) -> i32 = closure as fn(i32) -> i32;

// Pointer Conversions (Thin Pointers)
let val: i32 = 42;
let ptr_const: *const i32 = &val as *const i32;
let ptr_mut: *mut i32 = ptr_const as *mut i32;       // Casts away constness
let ptr_other: *const f32 = ptr_const as *const f32; // Thin to Thin type change
let addr: usize = ptr_mut as usize;                  // Thin pointer to integer
let new_ptr: *const i32 = addr as *const i32;        // Integer to thin pointer

// Pointer Conversions (Fat Pointers)
let slice: &[i32] = &[1, 2, 3];
let fat_ptr: *const [i32] = slice as *const [i32];
let fat_other: *const [u32] = fat_ptr as *const [u32]; // Fat to Fat (same metadata)

// INVALID CASTS (Will not compile):
// let invalid_fat = ptr_const as *const [i32];      // ERROR: Thin to Fat
// let invalid_int = fat_ptr as usize;               // ERROR: Fat to Integer

Limitations

The as operator cannot be used for:
  1. Complex Type Conversions: It cannot cast between structs, tuples, or non-C-like enums.
  2. Transitive Pointer Casts: It cannot chain implicit conversions. For example, casting a reference directly to an integer (&val as usize) is invalid; it must be explicitly routed through a raw pointer (&val as *const i32 as usize).
  3. Fat Pointer Metadata Manipulation: It cannot cast thin pointers to fat pointers, nor can it cast fat pointers to or from integers, as as cannot synthesize or strip pointer metadata.
Master Rust with Deep Grasping Methodology!Learn More