3 ms·
> It would be much simpler to not think about error handling at all, and let some top-level try { } catch (...) { /* intentionally empty */ } handler deal with
by jchw 4y ago
> It would be much simpler to not think about error handling at all, and let some top-level try { } catch (...) { /* intentionally empty */ } handler deal with it:
I dislike this, as even in C++, I like expected or StatusOr better than exceptions. I don't really think the Rust semantics for Result is that bad.
That said, if I were to fantasize about potential improvements, one thing I'd really like is an overhaul of error types in results. I wish there was some magical way that the error type could be inferred to be a union of all of the errors that can be returned. Most of the time, needing to explicitly do this manually doesn't add much value, and worse, it leads to much less precise error types as people reuse the same union type for functions that return disjoint errors. Unfortunately, there's no obvious way to make this work out, especially since it breaks Rust's rule about non-local inference, since the return type would be inferred by the function itself. Also, it would make life a lot worse for not breaking your API. But it would make the code a lot simpler and lower effort, that's for sure.
Perhaps another thing would be simply not needing to write out Ok(value), and just have an implicit conversion there, but while that could actually be done, it is also ugly for other reasons.
I don't see a problem at all with the ? syntax itself.
- vore 4y agoOne thing I wish was better was block-scoped ?. I know there's https://doc.rust-lang.org/beta/unstable-book/language-features/try-blocks.html https://doc.rust-lang.org/beta/unstable-book/language-featur... so you can do e.g. let foo: Result<T, Error> = try { x()?; y()?; Ok(z) }; but it hasn't been stabilized yet. The other workaround is to make an anonymous function and invoke it immediately, but sometimes you run into janky lifetime issues with that.
- D4ckard 4y ago> I wish there was some magical way that the error type could be inferred to be a union of all of the errors that can be returned. You could use `Result<(), Box<dyn std::error::Error>` to use dynamic dispatch at runtime and allow the function to return any type that implements `std::error::Error`. Otherwise people often use the anyhow[1] or the thiserror[2] crate to easily work with errors. They allow concise error propagation and quickly creating custom error types. [1]: https://docs.rs/anyhow/latest/anyhow/ https://docs.rs/anyhow/latest/anyhow/ [2]: https://docs.rs/thiserror/latest/thiserror/ https://docs.rs/thiserror/latest/thiserror/
- jchw 4y agoI usually use thiserror. dyn Error would be fine by me performance-wise, but I do want to exhaustively know the exact possible kinds of errors a function can return statically at compile-time, and dyn Error thwarts that. It looks like anyhow Result is basically in the same boat, just with better ergonomics.