I'm normally not a guy for rants but recently I started to write small PRs for some Rust crates and this is something that bothers me very often.
tl;dr
Don't:
type Result<T> = std::resutl::Result<T, MyError>;
Do:
type Result<T, E = MyError> = std::result::Result<T, E>;
Long version
With crates like thiserror
, snafu
and so on it is common to use a custom error type. This is good practice and I support it. However, what usually comes along with a custom error type is a convenient type alias for Result
. Often this looks like the following:
type Result<T> = std::resutl::Result<T, MyError>;
This works most of the time but when someone has to implement a trait with fallible methods or wants to use a different error type somewhere the usual -> Result<T, OtherError>
results in a compiler error, e.g. here (playground):
struct MyError;
type Result<T> = std::result::Result<T, MyError>;
struct Foo;
struct ParseFooError;
impl FromStr for Foo {
type Err = ParseFooError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Err(ParseFooError) // ^^^^^^^^^ unexpected type argument
}
}
Now we can either use a fully qualified name in this one case std::result::Result
or create a new type alias ParseFooResult
. Instead, I strongly recomment the more convenient to use alias:
type Result<T, E = MyError> = std::result::Result<T, E>;
This version sets MyError
as the default parameter which still allows to override the parameter if required (like in the example, go try it out and replace the type alias in the playground).
That's it. If someone has a different opinion on this matter I'll be happy to read the reasons.