4 ms·
This is a nice overview of Rust's available error-handling crates, and some improvements to the language that are error-related. But I'd like to quickly point o
by cytzol 7y ago
This is a nice overview of Rust's available error-handling crates, and some improvements to the language that are error-related. But I'd like to quickly point out that you do not have to pick a library from this list! I don't want anybody to read this article and go away thinking "I need to learn nine libraries in order to use Rust effectively". In the majority of cases, I've found what the language and std offer is enough for me.
(In fact, it leaves my favourite solution out: using the derive_more crate to auto-generate From implementations for the ? operator to use. From is a general trait, useful for far more than error handling, which is probably why it's omitted here.)
- pornel 7y agoYeah, it does seem overwhelming from the outside. But all these libraries are just variations of boilerplate needed for the `std::error::Error` trait. And the variety exists, because there are different needs and trade-offs: • You may want an error type that takes 0 bytes, so that `Result` is cheap for trivial high-performance functions (e.g. parsing libraries that may fail on every byte). • You may want your error type specify exact cause of failure in your library in a programmatic way, so that callers can turn it into a precise, localized error message for the end user. • You may want to have a super rich detailed error object with all the context, e.g. an entire HTTP response for a 5xx status. • And some application developers prefer having an "I don't care, just give me the backtrace" error wrapper for everything, to speed up the development and not spend time on micro-managing error types. All of this works nicely and uniformly in `Result<Ok, Err>` with some `Err` type written (or generated) by you.
- asdkhadsj 7y ago> And some application developers prefer having an "I don't care, just give me the backtrace" error wrapper for everything, to speed up the development and not spend time on micro-managing error types. That's me tbh. I actually love Rust's error story atm, I always use an Error enum and I have made it do everything I want.. except one thing: Low (no?) cost backtraces. My error enums give me all the API-level specifics I want, but often I make the variants grouped by general code area. It's guided by my program flow, not debug introspection. So if I don't need to branch a codepath from an error object, it typically just goes into a single variant and I shove some message in there. What I'd love is to be able to easily and quickly just bake backtraces into this "non-program flow defining type". Bonus points if it could be done at compile time. I've thought about using a macro at error creation time to make it a compile-time poor mans backtrace, but I'm unsure if just one level of stack trace is all that beneficial. Either way I know I want something that's no more costly than: foreign_err.map(|foreign_err| MyError::Dump(format!("some description: {}", foreign_err))) edit: I should add, internally my perspective is coming from Go, so wrapping repeatedly in strings is fairly welcome to me. Just adding some low-cost default context to this would be a huge help.
- shepmaster 7y agoAn unstable `std::backtrace::Backtrace` (https://doc.rust-lang.org/nightly/std/backtrace/struct.Backtrace.html https://doc.rust-lang.org/nightly/std/backtrace/struct.Backt...) exists in nightly Rust. If you cannot require nightly, you can use the backtrace crate (https://docs.rs/backtrace/0.3.40/backtrace/ https://docs.rs/backtrace/0.3.40/backtrace/) on stable. Crates like my SNAFU (https://docs.rs/snafu/0.6.0/snafu/ https://docs.rs/snafu/0.6.0/snafu/) help abstract this away. Whenever the standard library implementation stabilizes, you will likely see many more errors including backtraces.
- asdkhadsj 7y agoAre you familiar with how costly backtrace is? I fear bubbling an error up and repeatedly adding a stack trace or some junk like that. Admittedly I have not looked too much into Backtrace, but I hope my concern makes sense.
- shepmaster 7y agoI do believe it's non-zero, as the stack has to be walked and potentially symbols are looked up. The symbols can be delayed until display time, but the stalk walk is "now or never", as I understand it. SNAFU addresses this by allowing `Option<Backtrace>` in the error struct. The backtrace is only captured when an environment variable is set by the end user.
- amluto 7y agoIt would be interesting for someone to port the Linux kernel’s ORC to user code. ORC backtraces are exact and more than an order of magnitude faster than DWARF.
- DarthGhandi 7y ago> Are you familiar with how costly... Checks the username of who you responded too: I'll blindly bet yes to that question for any amount you desire.
- weberc2 7y agoPlease forgive the tangent, but I'm curious about how people are using Rust if it's not in their primary day job? My impression is that there aren't yet many Rust jobs, but many practitioners. What are people building with it? For Rust enthusiasts, how do you use it? Are you contributing to an open source project or do you have your own pet projects? In either case, what are the projects? I'm asking because I might have some time to play around with it over break.
- TheDong 7y agoHere's a list of applications written in rust: https://github.com/rust-unofficial/awesome-rust#applications https://github.com/rust-unofficial/awesome-rust#applications People are using rust as they do other general purpose programming languages that have somewhat of a focus on systems programming: to write code. Your question isn't really easy to answer in the same way that someone asking "what are people building with python?" isn't useful. The answer is everything from webpages to text editors to operating systems, and everything in between.
- weberc2 7y agoProgramming languages lend themselves to different applications and the kinds of projects one contributes to in one's hobby time are different than those one contributes to in one's professional time. As such, I wouldn't expect hobbyist Rust users to work on the same distribution of projects as professional Python developers. In any case, I just want to know what people are inspired to work on with Rust; it's an open ended question, and it's okay that this question has no single easy answer. (Also, "what are people building with Python?" is a very interesting question to me; it's pretty much why https://github.com/trending?l=python https://github.com/trending?l=python and similar exist--and note, the kinds of projects that trend for Python are very different from those that trend for Rust).
- asdkhadsj 7y agoWe're using Rust for general purpose APIs. What would normally be written in Python or Go, for us. We just prefer it. We're also using it for a couple memory/generic intensive applications that were previously written in Go, but the lack of Generics made some API design awkward. I use it for all my personal projects as well. Which are basically the same types of things I wrote in Go. Though, I also am experimenting with WASM DOM UIs, something I've not yet used in Go.
- cerebellum42 7y agoI tried out a few of the error handling libraries, but these days I reverted to just defining a simple Enum with the types of errors that occur in my library, for most use cases that seems to be the simplest thing to do. I implement `std::error::Error` and `std::fmt::Display` for that enum and add `From` implementations as I need them to tidy up my code. It's usually not much more code than I would have written with an error handling library and it's fully transparent, understandable for anyone with a rudimentary understanding of Rust. And I get to have one less dependency.
- nemothekid 7y agoI used to do this as well, but I came across thiserror (which is featured in the article), which is just macros that do exactly this and nothing more. It's certainly less transparent, but I prefer this method of error handling, and writing out the Impls manually can get out of hand (as well as having to adding new fields to the enum).
- vaylian 7y agoIn the early days of Rust 1.0 the `Error` trait was rather cubersome (error messages needed a static lifetime). That is what caused people to reach for crates like quick-error and error-chain. But then the `Error` trait got extended and the old methods (description and cause) got deprecated and replaced with default implementations. It is much nicer now :-)