While implementing a trait from an external library, I found my initial implementation unable to compile.
// From library
trait SomeTrait {
fn do_thing(&self) -> Result<i32, Box<dyn Error + Sync + Send + 'static>>;
}
// My code
struct Foo;
impl SomeTrait for Foo {
fn do_thing(&self) -> Result<i32, Box<dyn Error + Sync + Send + 'static>> {
i32::from_str("42").map_err(|e| Box::new(MyError))
}
}
#[derive(Debug)]
struct MyError;
impl Display for MyError {...}
impl Error for MyError {}
Error from rustc v1.55.0:
error[E0308]: mismatched types
--> src/main.rs:17:9
|
16 | fn do_thing(&self) -> Result<i32, Box<dyn Error + Sync + Send + 'static>> {
| --------------------------------------------------- expected `Result<i32, Box<(dyn std::error::Error + Send + Sync + 'static)>>` because of return type
17 | i32::from_str("42").map_err(|e| Box::new(MyError))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::error::Error`, found struct `MyError`
|
= note: expected enum `Result<_, Box<(dyn std::error::Error + Send + Sync + 'static)>>`
found enum `Result<_, Box<MyError>>`
If I change the body of do_thing to be this, the compiler is happy.
match i32::from_str("42") {
Ok(v) => Ok(v),
Err(_) => Err(Box::new(MyError)),
}
I can also do this which the compiler also accepts but is incredibly ugly.
i32::from_str("42").map_err(|e| Box::new(MyError) as Box<dyn Error + Sync + Send + 'static>)
I obviously have a working solution but I'd like to know what the differences between the implementations are to avoid pulling my hair out in the future.