Skip to content
AgileLogics
5 min read

Type Conversion

Prerequisites: Scalar data types

Rust never converts between number types automatically — not even from i32 to i64. You always convert explicitly.

Syntax

let n = 3.99_f64 as i32;             // cast with `as`
let wide = i64::from(42_i32);        // lossless conversion with `from`
let parsed: i32 = "42".parse().expect("not a number");

as casts convert between number types, and between numbers and characters:

  • Float to integer truncates toward zero: 3.99 as i32 is 3.
  • Casting to a smaller integer type keeps only the low bits, which can change the value: 300 as u8 is 44. Be careful with this.
  • 'A' as u32 is 65, and 97_u8 as char is 'a'.

T::from(value) only exists for conversions that can never lose information (like i32 to i64), so it's the safer choice when available.

Parsing text uses .parse(). Parsing can fail — "abc" isn't a number — so parse returns a Result: either Ok(value) or Err(error). Rust needs to know what type you want, so give the variable a type (let n: i32 = ...) or use the "turbofish" syntax "42".parse::<i32>().

At this stage, there are two simple ways to handle the Result:

  • .expect("message") — gives you the value, or stops the program with your message if parsing failed.
  • match — runs different code for Ok and Err. (The Enums & match lesson explains match fully.)

Example

fn main() {
    let price = 19.99_f64;
    let whole = price as i32;
    println!("{price} as i32 = {whole}");

    let big = 300_i32;
    println!("{big} as u8 = {}", big as u8);

    println!("'A' as u32 = {}", 'A' as u32);
    println!("97 as char = {}", 97_u8 as char);

    let small: i32 = 42;
    let wide = i64::from(small);
    println!("i64::from = {wide}");

    let count: i32 = "42".parse().expect("not a number");
    println!("parsed + 1 = {}", count + 1);

    let result = "abc".parse::<i32>();
    match result {
        Ok(n) => println!("Parsed {n}"),
        Err(e) => println!("Could not parse: {e}"),
    }
}

Expected output

19.99 as i32 = 19
300 as u8 = 44
'A' as u32 = 65
97 as char = a
i64::from = 42
parsed + 1 = 43
Could not parse: invalid digit found in string

Common mistakes

  • Mixing number types in arithmetic.
let count: i32 = 3;
let price: f64 = 2.5;
let total = count * price;
error[E0277]: cannot multiply `i32` by `f64`

Convert one side first: count as f64 * price.

  • Not saying which type to parse into. let n = "5".parse().unwrap(); fails with:
error[E0284]: type annotations needed
  • Parsing text that has spaces or a newline around it. " 42".parse::<i32>() is an error — call .trim() first (you'll need this when reading user input).
  • Assuming as rounds. It truncates; use price.round() as i32 to round to the nearest whole number.

Practice

Parse the text "19" into an i32 and "3.5" into an f64, multiply them (converting the i32 first), and print Total: 66.5.

Show solution
fn main() {
    let quantity: i32 = "19".parse().expect("not an integer");
    let price: f64 = "3.5".parse().expect("not a number");
    let total = quantity as f64 * price;
    println!("Total: {total}");
}