4 ms·
Rust brings some great features to the table but the combination of them opens up a new level of challenges to deal with which is why there is so much talk in t
by epage 7y ago
Rust brings some great features to the table but the combination of them opens up a new level of challenges to deal with which is why there is so much talk in the community on error handling libraries.
Some of the competing needs that need to be dealt with to understand why include
- Quickly create errors and extend them for prototyping while scaling to programmatically reacting to them
- Easily convert errors with `?` has drawbacks. `?` wants you to implement the `From` explicit conversion trait but that becomes part of your public API, exposing implementation details (switch dependencies or one bumps major is technically a breaking change for you). Another problem is you can't both implement the `Error` trait and support `From` from anything that implements the `Error` trait because it will conflict with Rust's blanket implementation of `From` converting yourself into yourself. We need specialization to solve this.
- You can return `Result<T, E>` from main but it prints `Debug` information rather than user-friendly `Display`. So we need to deal with `Debug` printing the right thing most of the time while printing something user-friendly in `main`.
- Rust users have their errors wrap underlying errors in a giant chain. Rendering of this chain needs to be decoupled from a single `Error`'s `Display`.
- We aren't clean which errors in a chain are context and which are meant to be actual root causes to programmatically act on
- Supporting `no_std` for embedded cases.
On top of all of that are unsolved problems like process exit codes specialized for the error being returned, debug-only information (e.g. opt-in to rendering an original `errno` or `HRESULT`), error cloning (important for caching failable-operations), error serialization (important for network proxying APIs).
I think some in the Rust community are seeing Yoshua's comaprison and feeling like we are converging on a solution. While I think that is true for `derive(Error)` (code-genned trait implementations), I don't think this is true for our patterns for how to structure and communicate content in errors or how to do Dynamic errors. This post made me feel like Rust is in a rut. People have taken a pattern or two from cargo's source and refined it without branching out more into other ways of solving the problems. This ends up leaving a lot of the problems i listed above unsolved or less than ideal.
I'm toying with ideas for an alternative approach for solving most of these problems; just need to get some more time to get it in a shareable state.
- couchand 7y ago> Another problem is you can't both implement the `Error` trait and support `From` from anything that implements the `Error` trait because it will conflict with Rust's blanket implementation of `From` converting yourself into yourself. I believe this issue would only come up if you're trying: impl<T: std::error::Error> From<T> for MyError which seems like a really clumsy way to handle it. In most real cases, wouldn't you write the From impls for the specific types of errors you're expecting?
- epage 7y ago> which seems like a really clumsy way to handle it. In most real cases, wouldn't you write the From impls for the specific types of errors you're expecting? In an application, yes. The problem is in libraries because the `From`s` are public so you have put the error type for your dependency in your public API and if you change dependencies or upgrade past a major, you've broken your API. Granted, it is unlikely someone is going to use it ... but I wouldn't put it past people to take shortcuts like that.
- shepmaster 7y agoA benefit of SNAFU is that the `From` trait is implemented against the internal-by-default context selectors. Since enum variants are public if the enum is, SNAFU also offers a way to wrap an opaque newtype around the internal error, allowing the implementor to choose exactly what public API their error exposes.