Here's the article -
Summary: Error Handling in Rust
- Panics are bad!
- Rust enables us to use errors as variables and types as opposed to errors as exceptions. This is better for composability.
- using
.unwrap()is almost always not a good idea, errors can be handled so much better -> this is because.unwrap()forces apanic!(). - It's good to know what
Option<T>andResult<T, E>look like internally as this knowledge allows us to handle errors so much better. - It's also good to know that
Option<T> == Result<T, ()>, and that you can convert between the two - If you're using
.unwrap()multiple times in a row, it's probably a better idea to use a special combinator type to allow composition.- These combinators (
.and_then(),.unwrap_or(),.or_else(),.map()) allow us to elide repetitive stuff from the code and make the code easier to read.
- These combinators (
- Combinators are sometimes hard to read and reason about (especially if you
don't know the underlying implementation) -> this is why it's usually more
readable (in my opinion) to stick to implicit case analysis by using things
like the
try!()macro and the?operator in conjunction with early returns - If you're combining error types, you can explore multiple options, including,
but not limited to -
- Converting every error to a
String- you lose contextual information likeio::ErrorKind - Using
Box<dyn Err [+ Send + Sync]>- same problem - because we're treating the error here as a Trait Object, we lose all other information about it.
- Converting every error to a
- The best option for library authors is to define their custom error types (see
stdlib definitions of errors as a template), which also define
std::from::From<T>on the error types that they depend on- this is so that you can easily use the
?operator to handle unwraps and result err matches - Any other error type will try to be converted to your custom return error
type, so it's good to define the
std::from::From<E: Err>trait on your custom error type.
- this is so that you can easily use the
- Lastly, levels of error handling ordered by difficulty of understandability
- TODO: Code Examples
- Combinators
- Explicit Case Analysis
- Inline implicit unwraps but top-level catch