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

Using default template type for the #[source] field #162

Open
Finomnis opened this issue Apr 24, 2022 · 2 comments
Open

Using default template type for the #[source] field #162

Finomnis opened this issue Apr 24, 2022 · 2 comments
Labels
help wanted Extra attention is needed question Further information is requested

Comments

@Finomnis
Copy link
Contributor

I currently have the source field of my error enum be Box<dyn Error + Send + Sync>.

In my project, I would like to make this source field type configurable with a generic with Box<dyn Error + Send + Sync> as the default type, but I can't seem to find the correct combination of restrictions for the generic.

So, basically the TLDR; question is: What should be written in the <???> to make this code compile?

#[derive(Debug, thiserror::Error, miette::Diagnostic)]
pub enum MyError<ErrType: <???> = Box<dyn Error + Send + Sync>> {
    #[error("Error containing another error")]
    AnError(#[source] ErrType),
}

I have a more detailed discussion about my attemps and problems I encountered here on stackoverflow.

Thanks for the great work :) <3

@zkat
Copy link
Owner

zkat commented Apr 24, 2022

Hmmm.

This seems to be a limitation of the Diagnostic macro, but I'm not sure how to work around it. To show something that works, for example:

    #[derive(Debug, Error)]
    enum MyError<ErrType = Box<dyn std::error::Error + Send + Sync>> {
        #[error("Error containing another error")]
        AnError(#[source] ErrType),
    }

    impl<ErrType: 'static + std::error::Error> Diagnostic for MyError<ErrType> {
    }

This will compile just fine! And if you feel up to implementing miette::Diagnostic by hand, this is more than good enough :) (although, I guess, it means it won't be implemented for Box<dyn Error>...)

I'm not actually sure what else can be done here, besides some clever wrapping of types that I haven't quite thought through yet, but in essence, the issue is that the Diagnostic proc macro, while it's aware of generics, doesn't magically know that you need to add that extra 'static + std::error::Error bound to it (or which type to add it to), and if you end up adding the trait bound to the original enum definition, you'll run into a conflict because Box<dyn Error> doesn't implement std::error::Error, as you pointed out.

So the immediate workaround to unblock you is to stop using the derive macro for now. As to a more robust solution that lets you use the derive macro... I have no idea, but I'm open to help/suggestions from folks who have more brain cells for this than I do haha.

@jdonszelmann
Copy link
Contributor

This could be solved with some way to explicitly give the bounds on T through an attribute, a bit like how with async_trait you can add the ?Send bound:
https://docs.rs/async-trait/latest/async_trait/#non-threadsafe-futures

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants