6 ms·
As someone newer to Rust who has been using error-chain because it was what I found at the time I'd be curious to hear what your preferred solution to errors in
by d1plo1d 6y ago
As someone newer to Rust who has been using error-chain because it was what I found at the time I'd be curious to hear what your preferred solution to errors in modern rust is.
- steveklabnik 6y agohttps://blog.yoshuawuyts.com/error-handling-survey/ https://blog.yoshuawuyts.com/error-handling-survey/ is a good summary of what's out there. I think current rough consensus is anyhow/thiserr depending on if you're writing an application or library. I haven't actually used them myself, though. You don't have to keep up with the cool new libraries.
- matklad 6y agoAgree that there’s consensus on anyhow for applications, but I think many folks now prefer vanilla std::error::Error for libraries (which itself got better as a result of all the experiments in the ecosystem).
- littlestymaar 6y agoThe good thing with this_error is that it's just a custom derive on vanilla std::error::Error.
- Arnavion 6y agoI used to maintain a custom derive crate for errors before failure came out, but these days I just use manual impls of `std::error::Error` for libraries and `Box<dyn std::error::Error>` for applications. I can't be bothered to keep up with the Rust error-library-du-jour game, even if it so happens that today's darling custom derive (thiserror) would emit the same `std::error::Error` impl that I write by hand. Manual impls may be tedious to write, but they change rarely after they've been written, enough that the con of adding one more dependency that may go away tomorrow outweighs the con of writing them manually.
- jfkebwjsbx 6y agoThis matches my experience as well. I want to write code that works for years (dependencies make this hard) and is understood by everyone. So explicit is best.
- ShorsHammer 6y agoFailure is really nice to use. Might suit some people. https://github.com/rust-lang-nursery/failure https://github.com/rust-lang-nursery/failure
- bschwindHN 6y agoI wouldn't recommend failure, its current maintainer and original author will be deprecating it: https://boats.gitlab.io/blog/post/failure-to-fehler/ https://boats.gitlab.io/blog/post/failure-to-fehler/ From the article: > The crate I would recommend to anyone who likes failure’s API is anyhow, which basically provides the failure::Error type (a fancy trait object), but based on the std Error trait instead of on.
- charliesome 6y agoAs the kind of more conservative Rust user GP references, I've had a great time with the derive_more crate's From derive [0]. This lets me write code like this: #[derive(From, Debug)] pub enum SomeSpecificError { Io(io::Error), SomeAppLevelErrorCondition, } fn do_something() -> Result<(), SomeSpecificError> { do_some_io()?; // ... } Previously I would have written: fn do_something() -> Result<(), SomeSpecificError> { do_some_io().map_err(SomeSpecificError::Io)?; } I find this approach results in clear code that continues to compile and work just fine over time, even as everything changes around it. [0] https://jeltef.github.io/derive_more/derive_more/from.html#enums https://jeltef.github.io/derive_more/derive_more/from.html#e...
- Arnavion 6y agoUnless you want all I/O errors to be indistinguishable to your callers, you should use more specific variants than a single `Io(std::io::Error)`, like `ReadConfig(std::path::PathBuf, std::io::Error)` and `ConnectToServer(std::net::SocketAddr, std::io::Error)`. And if you do so, the `From` impl becomes untenable and you have to fall back to `.map_err(...)?`. In general, I feel `?`'s automatic `From::from` conversion leads to bad errors, because the programmer is incentivized to have type-specific context via implementing `From<>` rather than operation-specific context, even though operation-specific context leads to better error messages. Consider the difference between: failed to initialize library caused by: an I/O error occurred caused by: no such file or directory (2) and failed to initialize library caused by: could not read config file at /path/to/config.toml caused by: no such file or directory (2) Edit: I should add that it is possible to use `From<>` when the type-specific contexts and operation-specific contexts form a bijection. In the above example, if there were dedicated `struct ReadConfigError(std::path::PathBuf, std::io::Error)` and `struct ConnectToServerError(std::net::SocketAddr, std::io::Error)` types, then having the higher-level `Error` impl `From<ReadConfigError>` and `From<ConnectToServerError>` would be perfectly fine. Of course, that would just shift the issue down to those types since they would not be able to impl `From<std::io::Error>`. Also, in my experience, libraries rarely bother having such individual operation-specific error types anyway.
- 6y ago