Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Type Conversion with as

Goal of This Episode

Learn to convert between numeric types with as, and the safer alternatives.

Concept

Basic Usage

In Chapter 1 we learned that Rust doesn’t convert types automatically. When you need a conversion, use as:

fn main() {
    let x: i32 = 42;
    let y: f64 = x as f64;

    let a: f64 = 3.99;
    let b: i32 = a as i32; // 3 — the decimal part is truncated, not rounded
}

Between Integers

Small to large — the value is unchanged:

fn main() {
    let x: u8 = 200;
    let y: u32 = x as u32; // 200
}

Large to small — silent truncation, no error:

fn main() {
    let x: u32 = 300;
    let y: u8 = x as u8; // 44! 300 = 256 + 44; only the lowest 8 bits are kept
}

Between signed and unsigned there can also be surprises:

fn main() {
    let x: i32 = -1;
    let y: u32 = x as u32; // 4294967295
}

From / Into: The Safer Choice

Chapter 5 covered From and Into. By convention, these traits should only be implemented for infallible conversions:

fn main() {
    let x: i32 = 42;
    let y: f64 = f64::from(x); // OK
    let z: i32 = i32::from(3.14_f64); // compile error! conversion may lose information
}

TryFrom / TryInto

For conversions that can fail, use TryFrom — it returns a Result:

use std::convert::TryFrom;

fn main() {
    let x: u32 = 300;
    let result = u8::try_from(x); // Err
    let y: u32 = 42;
    let result = u8::try_from(y); // Ok(42)
}

Which One to Use When

  • Use From / Into for conversions intended to be infallible.
  • Use TryFrom / TryInto when the conversion can fail — it returns a Result.
  • Use as only when you truly know what you’re doing.

Example Code

use std::convert::TryFrom;

fn main() {
    // basic as conversion
    let x: i32 = 42;
    let y: f64 = x as f64;
    println!("i32 {} → f64 {}", x, y);

    let a: f64 = 3.99;
    let b: i32 = a as i32;
    println!("f64 {} → i32 {} (truncated, not rounded)", a, b);

    // dangerous silent truncation
    let big: u32 = 300;
    let small: u8 = big as u8;
    println!("u32 {} → u8 {} (silent truncation!)", big, small);

    // From: safe
    let safe: f64 = f64::from(42_i32);
    println!("From: {}", safe);

    // TryFrom: can fail
    match u8::try_from(300_u32) {
        Ok(v) => println!("TryFrom succeeded: {}", v),
        Err(e) => println!("TryFrom failed: {}", e),
    }

    match u8::try_from(42_u32) {
        Ok(v) => println!("TryFrom succeeded: {}", v),
        Err(e) => println!("TryFrom failed: {}", e),
    }
}

Recap

  • as converts between numeric types: float to integer truncates the decimals; large integer to small integer silently truncates.
  • From / Into: by convention, for infallible conversions.
  • TryFrom / TryInto: for conversions that can fail; they return a Result.
  • Prefer From, then TryFrom, and only then as.