CodeBlanks Logo Icon CodeBlanks

Error conversion

Convert between error types with the From trait.

Error conversion

Before returning an error, ? calls From::from. If you implement From for your own error type, lower-level errors convert automatically:

use std::num::ParseIntError;

#[derive(Debug)]
enum UygHata {
    Sayi(ParseIntError),
    Bos,
}

impl From<ParseIntError> for UygHata {
    fn from(e: ParseIntError) -> Self {
        UygHata::Sayi(e)
    }
}

Now in a function returning Result<_, UygHata>, s.parse::<i32>()? works directly.

Using it

Thanks to the conversion, the function body stays simple, and the caller can act by error kind:

fn ikile(s: &str) -> Result<i32, UygHata> {
    if s.is_empty() {
        return Err(UygHata::Bos);
    }
    Ok(s.parse::<i32>()? * 2)   // ParseIntError → UygHata::Sayi
}

match ikile("") {
    Err(UygHata::Bos) => println!("girdi boş"),
    Err(UygHata::Sayi(e)) => println!("sayı değil: {e}"),
    Ok(n) => println!("{n}"),
}

Practice Automatic conversion

Write UygHata, the From implementation and the ikile function above. Print the results of ikile("21"), ikile("") and ikile("x") with {:?} on separate lines.

Starter code

main.rs
use std::num::ParseIntError;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::num::ParseIntError;

#[derive(Debug)]
enum UygHata {
    Sayi(ParseIntError),
    Bos,
}

impl From<ParseIntError> for UygHata {
    fn from(e: ParseIntError) -> Self {
        UygHata::Sayi(e)
    }
}

fn ikile(s: &str) -> Result<i32, UygHata> {
    if s.is_empty() {
        return Err(UygHata::Bos);
    }
    Ok(s.parse::<i32>()? * 2)
}

fn main() {
    println!("{:?}", ikile("21"));
    println!("{:?}", ikile(""));
    println!("{:?}", ikile("x"));
}

Expected output

Ok(42)
Err(Bos)
Err(Sayi(ParseIntError { kind: InvalidDigit }))

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Implementing <code>From&lt;A&gt; for B</code> also gives which for free?

  • Into<B> for A Correct answer
  • From<B> for A
  • Display for B
  • Clone for A

Explanation: The standard library has a blanket impl: Into is provided automatically for every pair implementing From. That's why writing From is preferred.

2 Conversion trait

Question
impl ____<ParseIntError> for UygHata {
    fn from(e: ParseIntError) -> Self {
        UygHata::Sayi(e)
    }
}
Answer
impl From<ParseIntError> for UygHata {
    fn from(e: ParseIntError) -> Self {
        UygHata::Sayi(e)
    }
}

Explanation: The ? operator uses From for conversion.

3 Call and result

Term Meaning
ikile("21") Ok(42)
ikile("") Err(Bos)
ikile("x") Err(Sayi(..))
ikile("-3") Ok(-6)

All lessons in Intermediate