Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#[implicit] fields for automatic data collection when building errors using From<source> #402

Closed
wants to merge 3 commits into from

Conversation

carlsverre
Copy link

@carlsverre carlsverre commented Dec 19, 2024

This PR adds a new field attribute called #[implicit]. When applied to a field, this attribute causes the derived From implementation to initialize the field using a new ImplicitField trait. This trait and attribute is inspiried by the snafu crate. It can be used to automatically derive details such as a backtrace or the location of the error.

Using this field is easy. First implement ImplicitField for your type:

#[derive(Debug)]
pub struct Location(pub &'static core::panic::Location<'static>);

impl ImplicitField for Location {
    #[track_caller]
    fn generate() -> Self {
        Self(core::panic::Location::caller())
    }
}

Then simply add the field to your Error struct or enum variant along with the #[implicit] attribute:

#[derive(Error, Debug)]
#[error("...")]
pub struct ErrorStruct {
    #[from]
    source: Inner,
    #[implicit]
    location: Location,
}

Two important notes:

  1. #[implicit] fields require a sibling #[from] field.
  2. #[implicit] fields are only auto-generated in the derived From implementation. If you create your error another way you will have to initialize the field yourself.

For more comprehensive usage examples including generating Location and Backtrace see this test: https://github.com/carlsverre/thiserror/blob/5195f7ccfa403af3741fd7381ceabd68705426b7/src/implicit.rs

The motivation behind this PR is this blog post https://greptime.com/blogs/2024-05-07-error-rust along with the other feature requests for Location and non-nightly Backtrace support. While snafu can be used for this, it has a much larger surface area than thiserror and may not be suitable for all projects. This PR shows that with a small change to thiserror we can make the library more flexible without too much additional specialization.

If @dtolnay is interested in this feature being polished and landed, I'm happy to put in additional work to make it happen. In addition to more testing and documentation, I suggest that this feature could eventually replace the existing Backtrace/provides code:

  1. The existing backtrace logic could be replaced with the more generic implicit system
  2. When error_generic_member_access is available (currently only in nightly) we could provide #[implicit] fields by type. If multiple fields match, we could raise an error and have an explicit option on the implicit field.
  3. I think the crate could make the above changes in a backwards compatible way by continuing to support the previous field attributes (and implicit Backtrace type detection) and transparently converting them into implicit fields under the hood.

@carlsverre
Copy link
Author

This PR provides a more generic solution to both #401 and #291.
It also would provide a path to resolution for #390 and #321.

Copy link
Owner

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

I would prefer not to support this feature in this crate. I would leave this to a different crate, either a stripped-down variation of snafu that someone else can maintain, or a general-purpose derive(From) that can be used in combination with any derive(Error). Or: handwritten From impls would also often work, depending on how many distinct error types the user's crate needs to define.

@dtolnay dtolnay closed this Dec 21, 2024
@carlsverre
Copy link
Author

Thanks for getting back to me so quickly. Totally understand. Will think about what solution would work for me. Appreciate all the awesome projects you've released and maintain! Cheers

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

Successfully merging this pull request may close these issues.

2 participants