Not only thiserror but also the language itself kind-of endorses it, in that
combinators of Result, and ? syntax are designed to make handling a single layer of Result most ergonomic
also, the ? syntax supports From conversions for the reason of error upcasting, e.g. converting to Box<dyn Error> or similar, but alternatively also to such an enum type, conveniently, provided you give it the necessary From implementations (use the #[from] attribute of thiserror to generate such impls automatically; then you can just use ? operator on Result<_, EvalErr>, Result<_, Json_Err>, or Result<_, Network_Err>, too, inside of the remote_eval function body).
I've seen an approach of keeping two levels of Result, one for the kind of errors which should be kept private and one the public "domain" facing errors.
Well, it's entirely possible that you want to have not a single enum, but a hierarchy of them - each "layer" of the logic will have an enum, each variant of which holds inside another enum from lower layer.
I think we once discussed that a possible outcome could be that a library's functions should each return the most specific error possible and that maybe that library could define an error enum encapsulating all of its possible errors for the user's convenience.
Do you have a link to the discussion? I think I previously asked (here or elsewhere) a question regarding {anyhow, thiserror, Result} but I can't find it searching for {anyhow, thiserror, Result, @erelde, @zeroexcuses }.
I found this to be a pretty good summary of error handling in Rust. My big takeaway was that thiserror may be nice, but the extra effort to write your own full enum could be worth it to save compile time.
Compared to the previous version, our new code is a lot more specific. Users now get a lot more insight into the possible error cases that might be returned. As an added benefit, we also no longer have to Box Error because the size of WordCountError can be determined at compile time.
Where does it take about compile time of enum vs thiserror ? Compile time is very important to me.
The point is that sometimes it's better if the implementations thiserror would generate for you are written by hand, so that compiler doesn't spend its time on their generation.
I think the examples given of "internal errors" on that slide are right on the edge of where I would instead panic, depending on the kind of package I'm building and what it means that the error happened: an unexpected None probably means my crate has a bug, and a panic is better there, while invalid data probably means something else has messed with the file / DB, so a specific error saying that is more helpful. Overall, I'm not sure there's enough room between panics and semantic errors to fit internal errors.