I think it's hard to do robustly, though that particular footgun may be removed through other means eventually. In the meanwhile, I believe that if you're going to drop any part of the payload you should use another catch_unwind! (or leak the payload). But doing this is rare. As it turns out, reasoning about panics is hard, even in code explicitly about catching panics, because of their often-invisible nature.
That said, you're also getting push-back because it's not idiomatic Rust and it's (excuse the pun) an exceptional code pattern, not an expected one. It is not what you should reach for as part of normal error handling, and it makes addressing the error cases invisible and forgettable -- anti-patterns in Rust.
So when an Rustacean reads "[As I Rust beginner I recently learned that panics] may be worth considering an an alternative to Result", they're probably going to jump in and correct you. Not just to be pedantic, but also to guide you toward idiomatic Rust and away from footguns.
More generally, this feels like one of those mid-level issues, like self-referential structures or falling back to raw pointers (or falling back to unsafe generally). Are they possible? Yes. Should you learn them and should we have better material about them? Eventually you should and we definitely could use some better or centralized material on some topics. Are they what you should be reaching for in your first projects and while you're still getting a feel for the language? Almost certainly not.
Yes, but I feel the beginners mistake I made was to use Result when Panic was a superior solution for my use case ( more readable code, less chance of coding mistakes ). I have a bad memory, so I am not sure what I believed originally, but I don't think I knew panics could be caught, or didn't consider that as a solution. My mistake!
Before you get too confident about your apparently-uncommon skill at safely handling Panic, I suggest that you read the preprint of the just-announced on IRLO paper RUDRA: Finding Memory Safety Bugs in Rust at the Ecosystem Scale. Figure 3 in that paper is an example of a panic safety bug in String::retain() that RUDRA found in stable Rust's standard library.
Also see Table 4, "Details of the new bugs found in the 30 most popular packages on crates.io", which includes three more panic-handling safety bugs. As the rest of that table title states,
The RUDRA paper provides quite-convincing evidence that safely handling panics is extremely difficult, even for very experienced Rust programmers, including those who maintain rustc and std.
Note that this bug relates to panic handling in the context of writing unsafe codeâmodifying the bytes of a strâwhich has many more pitfalls than panic handling in safe application code (which I assume is the context @geebee22 is operating in).
That is true. However, if the Rust ecosystem contains so many potentially-flawed responses when a panic does occur, then it might be wise to avoid that exposure by not deliberately inducing panics as a programming strategy. (Of course that exposure only occurs when one expects to recover from the panic.)
There is no special skill involved. It's necessary to make sure everything is in a consistent state before continuing (after reporting the error), ( "panic::AssertUnwindSafe" ) but that's not difficult in my situation. I am only writing in safe Rust, not venturing into truly dangerous waters!
You can catch panics, but you can't assume your panics can be caught, especially if you're writing libraries. Danger of double panics are already mentioned, and it's not that rare people compile their binaries in panic = "abort" mode, which abort the process immediately after the panic without stack unwinding.
Note: The same author posted a separate thread all about panic and catch_unwind. Some of this commentary might fit better in that thread, or has already been covered there.
I'd like to add to your list std::mem::take() which, given a type that implements default replaces mut ref with default and gives you the referenced value. Much like Option::take(). I use that a lot in situations with asyncSync and Send implementations. Not sure if this is in the book
I'm also fond of async traits and figured I don't really need to depend on async-trait crate for that (and the bunch of proc macro deps). This is my typical use case. On top of async-trait, it allows me to achieve a Sync future, or do some preparation before the async code. It is a bit verbose, but with a bit of practice it actually helps one really understand and get the knack for lifetimes.