I'd like to implement a custom enum to wrap multiple errors like the code below.
I know I can make it work with map_err
but it does not seem to be neat. And since Result
is not defined in the current crate, I can't implement its conversion.
How will you deal with it in this situation?
Looking at wrapped_fn
, it seems to implement Result<_, io::Error>
conversion. Would you kindly tell me why this can work?
use anyhow::Result;
use std::io;
use thiserror::Error;
#[derive(Debug, Error)]
enum MyError {
#[error("CustomError {0}")]
CustomError(#[from] io::Error),
}
struct MyStruct {}
fn error_fn() -> Result<(), io::Error> {
return Err(io::Error::new(io::ErrorKind::Other, "other"));
}
fn wrapped_fn() -> Result<(), MyError> {
error_fn()?; // no idea why this works because it seems like implement `Result` conversion.
Ok(())
}
fn main() {
let result: Result<(), MyError> = error_fn().into(); // I want to make this work.
// let result: Result<(), MyError> = error_fn().map_err(MyError::from); // This works.
}
// This cannot be implemented as well.
// impl<T> std::convert::From<Result<T, io::Error>> for Result<T, MyError>{
// fn from(result: io::Error) -> Self{
// result.map_err(MyError::from)
// }
// }
error[E0277]: the trait bound `Result<(), MyError>: From<Result<(), std::io::Error>>` is not satisfied
--> src/main.rs:19:50
|
19 | let result: Result<(), MyError> = error_fn().into();
| ^^^^ the trait `From<Result<(), std::io::Error>>` is not implemented for `Result<(), MyError>`
|
= note: required for `Result<(), std::io::Error>` to implement `Into<Result<(), MyError>>`
The wrapped_fn
is what you typically want to do! The ?
is actually converting From
the existing error to the wanted error type before returning it if there is an error.
If you really want to do a conversion like the one in your main
without returning the error, then I think the nice way to write it is indeed:
fn main() {
let result = error_fn().map_err(MyError::from);
}