Skip to content
This repository has been archived by the owner on Aug 16, 2021. It is now read-only.

Towards 0.2 and Beyond #287

Open
davidbarsky opened this issue Dec 29, 2018 · 15 comments
Open

Towards 0.2 and Beyond #287

davidbarsky opened this issue Dec 29, 2018 · 15 comments
Assignees

Comments

@davidbarsky
Copy link
Contributor

With most of RFC 2504 being implemented in stable, I wanted to share my idea of how Failure should evolve towards. For preserving context, I'll briefly re-iterate what RFC 2504 entails:

  • Error::cause is being replaced by Error::source in Rust 1.33, which supports downcasting of inner errors.
  • std::error::Error requires a Display and Debug, which provides a string-based representation of the error.
  • std provides a Backtrace module, which provides a minimal API for just printing a backtrace for end-users. This is not implemented yet, but @mitsuhiko indicated on December 28th, 2018 that he's working on the Backtrace implementation for std 1.

As @withoutboats indicated in RFC 2504, the Fail trait in Failure would become an extension trait to std:error::Error along the lines of:

trait ErrorExt: Error + Send + Sync + 'static {
    // various provided helper methods
}

The Failure crate would then provide a derive for the standard library's error akin to:

#[derive(Debug, Display, Error)]
#[display = "My display message."]
struct MyError {
    #[error(source)]
    underlying: std::io::Error,
    backtrace: Backtrace,
}

This new derive will be introduced in Failure 0.2. The corresponding derive of Fail can be removed with the release of 0.2, or more conservatively, marked as deprecated and removed entirely in Failure 0.3. The release of Failure 0.2 will come with a corresponding minimum Rust version bump to at least 1.31.

Additionally, while the following are not strictly bound to the release of Failure 0.2, we can also provide:

  • Additional convenience macros and methods for chaining errors.
  • More documentation and examples around different error-handling strategies.

Additionally, with Rust's increasing use in the network services space, a pain point that's emerged is best practices around error reporting to instrumentation systems. While the type_name intrinsic would be a great solution for this problem , it's currently nightly-only and blocked on specialization. Failure could patch this gap by introducing an associated const ERROR_TYPE: &'static str to ErrorExt for error-reporting purposes. This const can subsequently be removed and deprecated once specialization is available.

Feedback on this proposal is welcome and encouraged.


[1]: See the rust-lang Discord, the general channel. Relevant conversation reproduced below:

i was actually (sadly not on the machine i'm on holidays with right now) working on trying to make a patch for rust core that provides a backtrace api
that's the missing piece right now to have stdlib provide what failure needs

@vorner
Copy link

vorner commented Dec 29, 2018

Just for the record, this is probably related: https://users.rust-lang.org/t/announcing-err-derive-yet-another-error-handling-library/23594

  • torkleyy tried to extract the derive macro
  • Inspired by him, I tried how far could one get with std only (and got to the similar conclusion that everything except backtraces would work nicely, but there's not any reasonable way to get to the backtrace of some cause-of-cause error).

@mitsuhiko
Copy link
Contributor

To be honest it's not very hard to come up with something better than failure soon given the pending changes to the stdlib. Once backtraces work I hope we will find a good path for failure and std error to converge.

@torkleyy
Copy link

torkleyy commented Jan 4, 2019

Well, I think this issue is good news!

The only thing that concerns me is

The release of Failure 0.2 will come with a corresponding minimum Rust version bump to at least 1.31.

Does this also apply to the derive macro? I'm wondering whether it still makes sense to work on err-derive or if I can drop it in case failure can replace it.

@davidbarsky
Copy link
Contributor Author

@torkleyy Apologies for the delay. Yes, I think this should also apply to the derive macro.

@vorner
Copy link

vorner commented Jan 12, 2019

Once backtraces work I hope we will find a good path for failure and std error to converge.

Related to this:

  • Do you think it makes sense to wait for backtraces to land in std first, or start working on failure 0.2 without them (and either not release, release as -pre*/-alpha*, or maybe decide to do 0.3 if need be with backtraces)?
  • Is there some rough time estimate for that?

I kind of feel there's a demand (is that the right word?) for something like failure::Error + derive, but on top of std::error::Error already. I (or someone else) could certainly release that as another separate crate, but that smells like fragmentation, which would be great to avoid.

@davidbarsky
Copy link
Contributor Author

@vorner

I think it’ll be okay to release a 0.2 without support for backtraces in std. At the very latest, I’d like to release Failure 0.2 before 1.33, which is February 28th, if I recall correctly. This allows for a coherent story around error-handling either regard to Error::cause’s deprecation.

@davidbarsky
Copy link
Contributor Author

With regard to deriving Error, I agree about the minimization of fragmentation ecosystem-wide.

As a single data point, @sapessi ran into a lot of issues with the current Fail derive in the AWS Lambda Runtime and replacing it with an Error derive would make things easier for library authors implementing error extensions, never-mind end users.

(sorry for not editing this comment more clearly; I’m short on time this afternoon and want to get my thoughts out.)

@spinda
Copy link

spinda commented Jan 18, 2019

What would this mean for failure's Error struct?

@davidbarsky davidbarsky mentioned this issue Jan 20, 2019
7 tasks
@davidbarsky
Copy link
Contributor Author

@spinda: I was thinking of renaming it to DefaultError with suggestions in the documentation to rename failure::DefaultError to failure::Error when Error is the application's catch-all. Feel free to take a look at #296!

@yoshuawuyts
Copy link

yoshuawuyts commented Jan 21, 2019

@davidbarsky If error handling is expressed as a graph, I currently use Failure's Fail trait to define "leaf node" errors, and Failure's Error struct to define "parent node" errors. Failure's Error struct essentially fills a similar role as Box<std::error::Error + Sync + Send> would do using just stdlib.

I don't feel the name DefaultError maps well to this use. I think it's because it's perfectly possible to create a specialized error type in one place, only for it to be converted back into the default later on. Reverting back to a "default" feels kind of odd.

For example: I think something like BoxedError, GenericError, or AnyError might hit closer to the mark (though ideally less verbose / not using already meaningful terms). I think it'd be nice if we could find a name that worked well for all uses.

@davidbarsky
Copy link
Contributor Author

@yoshuawuyts I responded to your comment on: #296 (comment)!

@mitsuhiko
Copy link
Contributor

I ran into some roadblocks with the backtrace for std but I will try to get this done now. However I think failure in the meantime evolved a bit and there is probably more we would need on the stdlib error. In particular the name method is super useful for what we do at Sentry and I would love to see that appear on the std error as well.

@vorner
Copy link

vorner commented Aug 9, 2019

Hello

Is there any progress? Is there anything people could do to help it move forward, or is it blocked on something external?

@davidbarsky
Copy link
Contributor Author

@vorner I haven't had the time to work on this, I'm sorry—a lot of life happened. This is something that others can/should pick up, as I think the initial issue described a path forward for the implementation.

Additionally, with the stabilization of core::any::type_name in 1.38, I think that the Fail::name method could be removed as well.

@vorner
Copy link

vorner commented Aug 9, 2019

Hmm. I have quite a long queue of things I want to write myself, but maybe I could get to it sooner than you. No promises yet, though.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants