Type Conversions (From, Into, as, TryFrom)
Type conversion is how you turn a value of one type into another in Rust — always explicitly, using as casts, the From / Into traits for infallible changes, and TryFrom / TryInto for ones that can fail.
Learn Type Conversions (From, Into, as, TryFrom) in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise…
Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll learn as casts and their truncation, the From / Into pair, fallible TryFrom with Result , parse , and why Rust never coerces implicitly.
What You'll Learn in This Lesson
1️⃣ The Cast (and Its Pitfalls)
The as keyword is a low-level numeric cast that always compiles and always succeeds — which is exactly why it's risky. Casting a float to an integer truncates toward zero, and casting to a smaller integer type can wrap the bits and lose information.
2️⃣ From & Into: Infallible Conversions
For conversions that can never fail, implement the From trait. The payoff is automatic: implementing From<A> for B gives you Into for free, so a.into() just works. The standard library uses this pattern everywhere, from String::from to integer widening.
Notice you only wrote impl From<Celsius> for Fahrenheit , yet c.into() compiled. That's the blanket implementation in the standard library handing you Into automatically.
3️⃣ TryFrom, parse, and to_string
When a conversion might fail, use TryFrom / TryInto , which return a Result . The same idea powers str::parse , which turns text into a number and reports invalid input. Going the other way, to_string renders any Display value as a String .
Your turn. Fill in the blanks marked ___ , then run it.
Parse a mix of valid and invalid strings, sum the good ones, and count the failures — handling each Result gracefully. Run it with cargo run and check the output.
📋 Quick Reference — Conversions
Practice quiz
What does 3.99_f64 as i32 evaluate to?
- 4
- 5
- 3
- 0
Answer: 3. Casting a float to an integer truncates toward zero, so 3.99 becomes 3.
What does 300_i32 as u8 produce?
- 44
- 300
- 255
- 0
Answer: 44. 300 does not fit in a u8, so the bits wrap and the result is 44.
Implementing From<A> for B automatically gives you what?
- TryFrom for free
- Display for free
- Clone for free
- Into for free
Answer: Into for free. A blanket impl in std means implementing From gives the matching Into automatically.
Which trait is for conversions that MIGHT fail?
- From
- TryFrom
- Into
- AsRef
Answer: TryFrom. TryFrom and TryInto return a Result so failure is explicit.
What does u8::try_from(300_i32) return?
- Err(...)
- Ok(44)
- Ok(300)
- None
Answer: Err(...). 300 does not fit in a u8, so try_from returns an Err instead of wrapping.
How do you convert a &str into a number?
- Call .into()
- Use as i32
- Call .parse()
- Call .to_string()
Answer: Call .parse(). .parse() returns a Result because the text might not be a valid number.
What does "42".parse::<i32>() return on success?
- 42
- Ok(42)
- Some(42)
- Err(42)
Answer: Ok(42). parse returns a Result, so a valid parse yields Ok(42).
Why does Rust have no implicit numeric coercion?
- Because it is slow
- Because of the borrow checker
- It actually does coerce
- To keep every conversion visible and intentional
Answer: To keep every conversion visible and intentional. Requiring explicit conversions avoids silent precision loss and surprising types.
Which is infallible and lossless for widening an i32 to i64?
- x as u8
- i64::from(x)
- i64::try_from(x)
- x.parse()
Answer: i64::from(x). Widening always succeeds, so From (i64::from) models it with no Result needed.
How do you turn a number like 255 into a String?
- 255 as String
- String::parse(255)
- 255.to_string()
- 255.into_str()
Answer: 255.to_string(). .to_string() renders any Display value as a String.