Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

impl trait for multiple errors handling

Tags:

rust

Is it possible to do something like this? If not why?

use std::error::Error;
use std::io::{self, Read};

fn main() {
    if let Err(e) = foo() {
        println!("Error: {}", e);
    }
}

fn foo() -> Result<(), impl Error> {
    let mut buffer = String::new();
    io::stdin().read_to_string(&mut buffer)?;
    let _: i32 = buffer.parse()?;
    Ok(())
}

I get this error:

error[E0282]: type annotations needed
  --> src/main.rs:10:24
   |
10 | fn foo() -> Result<(), impl Error> {
   |                        ^^^^^^^^^^ cannot infer type for `_`
like image 204
Boiethios Avatar asked Jan 29 '23 15:01

Boiethios


1 Answers

There are two issues here:

  1. impl Traits are resolved to a concrete type statically, at compile-time. Here you are trying to return two different types which implement Error: std::io::Error and std::num::ParseIntError. Since the impl Trait has to be resolved to only one type during compilation, there is no way this can be done.

  2. The ? operator calls From::from to convert between error types, which means it is flexible with regard to the target type. Here, the target type is an impl Trait, so the compiler does not have enough information to know which exact type to choose.

For these reasons, impl Traits are not really the right tool to use here. You can solve this by one of:

  • Use Box<dyn Error> as the return type. This implements From<E> for Error types so the conversion will work automatically. But it will require a dynamic allocation.
  • Implement a new error type as an enum which can contain any of the error types returned by the function, and implement From<ErrType> for each of those types.
like image 147
interjay Avatar answered Feb 03 '23 14:02

interjay