4 ms·
For anyone interested in what this would look like in Rust now, there's two ways. For libraries, people tend to recommend the thiserror crate. Code sample[0]:
by martijnarts 4y ago
For anyone interested in what this would look like in Rust now, there's two ways. For libraries, people tend to recommend the thiserror crate. Code sample[0]:
#[derive(thiserror::Error, Debug)]
enum Error {
#[error("One")]
One(#[from] Error1),
#[error("Two")]
Two(#[from] Error2),
}
fn foo(r1: Result<i32, Error1>, r2: Result<i32, Error2>) -> Result<..., Error> {
let i1 = r1?;
let i2 = r2?;
// ...
}
Whereas for binaries, people usually recommend anyhow. Code sample[1]:
fn foo(r1: Result<i32, Error1>, r2: Result<i32, Error2>) -> anyhow::Result<...> {
let i1 = r1?;
let i2 = r2?;
// ...
}
[0]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b6636bd945cfee7312e49a8c8c0a821f https://play.rust-lang.org/?version=stable&mode=debug&editio...
[1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=55afee0d797e1139e5f90726a5b54d16 https://play.rust-lang.org/?version=stable&mode=debug&editio...
- exDM69 4y agoFor simple tasks you can get away without any external crates by using `Result<T, Box<dyn Error>>`. But it's much more comfortable to use thiserror or anyhow in the long run. fn read_string() -> std::io::Result<String> { Ok("123".to_owned()) } fn main() -> Result<(), Box<dyn std::error::Error>> { let s = read_string()?; // io::Error let n = i32::from_str_radix(&s, 10)?; // num::ParseIntError println!("read number: {n}"); Ok(()) }
- xedrac 4y agoExcept you often need `Result<T, Box<dyn Error + Send + 'static>>` if you go that route. At the very least, you should create a type alias for it. I very much prefer the use of `anyhow` and/or `thiserror` depending on if I need typed errors.
- WirelessGigabit 4y agoAnd the reason it works in anyhow is ... They have those conversions: https://docs.rs/anyhow/latest/anyhow/struct.Error.html#impl-From%3CError%3E-for-Box%3Cdyn%20StdError%20+%20%27static%3E https://docs.rs/anyhow/latest/anyhow/struct.Error.html#impl-...
- icambron 4y agoThe binary vs library thing seems like an oversimplification to me. I think it's more like: do you need callers to handle this error specifically? With a library the answer is "I don't know, better let them do it", so you don't want anyhow. But in a binary, you may or may not, and it depends on the error. The pattern I use in my app is to use thiserror, and then just have an anyhow catch-all. That lets me do specific stuff where I know I'm going to need specific handling, and an easy-to-use fallback for just saying "this bad thing happened" with the anyhow! macro. #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Not logged in")] NotLoggedIn, #[error(transparent)] Api(#[from] ApiError), // etc #[error(transparent)] Other(#[from] anyhow::Error), } I don't know if this is the best pattern but it's worked really well for me.
- ithkuil 4y agowhat is the TL;DR difference between anyhow and Box<dyn Error> ?
- mcronce 4y agoIt's detailed here - https://docs.rs/anyhow/1.0.66/anyhow/struct.Error.html https://docs.rs/anyhow/1.0.66/anyhow/struct.Error.html - the list is short but IMO significant