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.