Which is exactly what Rust does -- if the error returned by the function does not match the error type of `?` expression, but the error can be converted using the `From` trait, then the conversion is automatically performed. You can write out the conversion implementation manually, or derive it with a crate like thiserror:
#[derive(Error)]
enum MyError {
#[error("Failed to read file")
IoError(#[from] std::io::Error)
// ...
}
fn foo() -> Result<(), MyError> {
let data = std::fs::read("/some/file")?;
// ...
}
You can also use helper methods on Result (like `map_err`) for inserting explicit conversions between error types: fn foo() -> Result<(), MyError> {
let data = std::fs::read("/some/file").map_err(MyError::IoError)?;
// ...
}