Skip to content

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