rust-lang / project-error-handling

Error handling project group
Apache License 2.0
268 stars 18 forks source link

Dynamic Error Wrapper Like anyhow::Error in std #30

Open theduke opened 3 years ago

theduke commented 3 years ago

Has there been any discussion of getting something like anyhow::Error into std?

The adoption of anyhow shows how popular that approach is, and especially with Backtrace capturing I consider it the best strategy for non-library code with the current language feature set.

The benefit of having this in std instead of a third party library would be two-fold.

Coherence

One drawback is that types like anyhow::Error can not implement std::error::Error themselves without specialization due to coherence rules and the required From<T: Error> for WrapperError. In std this should be solvable with specialization.

This is quite important for usability in certain circumstances, since these types don't compose well. Thankfully most libraries have their own custom Error types, which lessens the impact, but there are still many circumstances where libraries wrap a user-provided fallible operation.

Examples would be a database transaction function like Db::transaction<E, T, F>(&self, f) where F: Fn(&tx) -> Result<T, E> or a fallible stream like it is required for hyper::Body.

failure used to mitigate this with a Compat wrapper that could implement std::error::Error, but it's still a rather awkward solution.

Standardization

The second benefit would be standardizing the ecosystem around a common solution. cargo add anyhow is the first thing I do in pretty much every (non-library) crate I start. Having it built in would also be very beneficial for new users, so they don't need to go hunting for solutions and read blog posts on how to handle errors.

Drawbacks

The obvious drawback is that Rust is still evolving. If new patterns emerge, std might be stuck with a sub-optimal implementation and cause some ecosystem churn.

But considering the current state of Rust, I personally feel like the risk is acceptable and is outweighed by the benefits.

For bikeshedding purposes: I would probably name this type AnyError, with DynError as a second idea.

BurntSushi commented 3 years ago

In std this should be solvable with specialization.

Please double check this. Even if it is technically possible, we still may not do it. I don't recall the details of the current situation, but I had thought there was some hesitation to stabilize new APIs that require specialization.

theduke commented 3 years ago

I also read something along those lines in a discussion, but it wasn't quite clear what constraints are currently imposed.

Who would be a good person to ask? The libs team on Zulip?

BurntSushi commented 3 years ago

Maybe libs and lang.

yaahc commented 3 years ago

In std this should be solvable with specialization.

I've never gotten a confirmation on this but my research into this seems to imply that we will not be able to solve this with specialization. We would need support for lattice specialization, which according to the RFC at least is not something we plan on supporting. That plus the fact that specialization is still struggling with soundness issues makes me less interested in relying on it for a solution here.

I do think there are some promising uses of the new Try proposal that might allow us to get automatic conversions without needing to impl From<E: Error>, thus avoiding overlapping impls, which would let us use a type like anyhow::Error conveniently while still implementing Error. I haven't tested this yet though so it might fall flat on its face as soon as I try it so, don't quote me on this.

To go back to your original question though, yes we are planning on adding something like anyhow to std. This is still an area of open research though, and it will probably look fairly different. The current plan is to separate the reporting mechanisms built into anyhow into their own independent reporting infrastructure that mirrors / maybe is part of the panic reporting infrastructure, and then add a type like anyhow, or more accurately, like eyre, which can be used to bundle user defined context with errors which then integrates with the reporting mechanism to create error reports that are consistent between panics and recoverable errors.

Also, fwiw I'm currently writing a blog post explaining our plans in much more detail.

theduke commented 3 years ago

Nice to hear, looking forward to that blog post. I'm especially interested in how an out of band error reporting mechanism would interact with/support async.

Sadly that probably means that any of this will also take years to hit stable.