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/Intofor conversions intended to be infallible. - Use
TryFrom/TryIntowhen the conversion can fail — it returns aResult. - Use
asonly 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
asconverts 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 aResult.- Prefer
From, thenTryFrom, and only thenas.