Given the following two error types and functions to illustrate their usage (Rust Playground link):
#[derive(std::fmt::Debug)]
struct MyError;
#[derive(std::fmt::Debug)]
struct OtherError;
impl std::error::Error for MyError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
impl std::fmt::Display for MyError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MyError")
}
}
impl std::fmt::Display for OtherError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "OtherError")
}
}
impl std::error::Error for OtherError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
impl From<OtherError> for MyError {
fn from(_: OtherError) -> Self {
MyError {}
}
}
fn my_error() -> Result<(), MyError> { Ok(()) }
fn other_error() -> Result<(), OtherError> { Ok(()) }
If I am in a function that returns Result
with MyError
as its Error
type, I can call both functions returning MyError
and OtherError
because there's a From
converting between them.
However, I cannot simply return the Result
for the "other" type, I need to use ?
followed by Ok(())
instead. This looks inconsistent to me.
For example, this works fine:
fn main() -> Result<(), MyError> {
my_error()
}
This also does:
fn main() -> Result<(), MyError> {
my_error()?;
other_error()?;
my_error()
}
But this fails:
fn main() -> Result<(), MyError> {
my_error()?;
other_error()
}
Error:
error[E0308]: mismatched types
--> src/main.rs:43:5
|
41 | fn main() -> Result<(), MyError> {
| ------------------- expected `std::result::Result<(), MyError>` because of return type
42 | my_error()?;
43 | other_error()
| ^^^^^^^^^^^^^ expected struct `MyError`, found struct `OtherError`
|
= note: expected enum `std::result::Result<_, MyError>`
found enum `std::result::Result<_, OtherError>`
Why is that?
This makes some of my code more verbose, as I found out I need to do this to get it to work:
fn main() -> Result<(), MyError> {
my_error()?;
other_error()?;
Ok(())
}
Is this the only solution? I am more interested in understanding the reason it works this way, but if I am doing something silly feel free to point out what could be done better.