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

E0425 deriving Error for an enum declared in a macro #86

Closed
ghost opened this issue May 15, 2020 · 2 comments · Fixed by #87
Closed

E0425 deriving Error for an enum declared in a macro #86

ghost opened this issue May 15, 2020 · 2 comments · Fixed by #87

Comments

@ghost
Copy link

ghost commented May 15, 2020

On rustc 1.43.1 stable, the following code results in error[E0425]: cannot find value `_0` in this scope:

use thiserror::Error;

macro_rules! decl_error {
    ($($Variant:ident($Value:ident)),*) => {
        #[derive(Debug, Error)] // <- E0425 here
        pub enum Foo {
            $(
                #[error("{0:?}")]
                $Variant($Value),
            )*
        }
    };
}

decl_error!(
    Foo(u8),
    Bar(u16),
    Baz(u32)
);

// For comparison, normal usage does not result in errors.
#[derive(Debug, Error)]
pub enum Bar {
    #[error("{0:?}")]
    Foo(u8),
    #[error("{0:?}")]
    Bar(u16),
    #[error("{0:?}")]
    Baz(u32)
}

Curiously, the output of cargo-expand seems fine. Any possibility of a bug in rustc?

Output of cargo-expand

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std;
use thiserror::Error;
pub enum Foo {
    #[error("{0:?}")]
    Foo(u8),
    #[error("{0:?}")]
    Bar(u16),
    #[error("{0:?}")]
    Baz(u32),
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for Foo {
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match (&*self,) {
            (&Foo::Foo(ref __self_0),) => {
                let mut debug_trait_builder = f.debug_tuple("Foo");
                let _ = debug_trait_builder.field(&&(*__self_0));
                debug_trait_builder.finish()
            }
            (&Foo::Bar(ref __self_0),) => {
                let mut debug_trait_builder = f.debug_tuple("Bar");
                let _ = debug_trait_builder.field(&&(*__self_0));
                debug_trait_builder.finish()
            }
            (&Foo::Baz(ref __self_0),) => {
                let mut debug_trait_builder = f.debug_tuple("Baz");
                let _ = debug_trait_builder.field(&&(*__self_0));
                debug_trait_builder.finish()
            }
        }
    }
}
impl std::error::Error for Foo {}
impl std::fmt::Display for Foo {
    fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        #[allow(unused_variables, deprecated)]
        match self {
            Foo::Foo(_0) => __formatter.write_fmt(::core::fmt::Arguments::new_v1(
                &[""],
                &match (&_0,) {
                    (arg0,) => [::core::fmt::ArgumentV1::new(arg0, ::core::fmt::Debug::fmt)],
                },
            )),
            Foo::Bar(_0) => __formatter.write_fmt(::core::fmt::Arguments::new_v1(
                &[""],
                &match (&_0,) {
                    (arg0,) => [::core::fmt::ArgumentV1::new(arg0, ::core::fmt::Debug::fmt)],
                },
            )),
            Foo::Baz(_0) => __formatter.write_fmt(::core::fmt::Arguments::new_v1(
                &[""],
                &match (&_0,) {
                    (arg0,) => [::core::fmt::ArgumentV1::new(arg0, ::core::fmt::Debug::fmt)],
                },
            )),
        }
    }
}
pub enum Bar {
    #[error("{0:?}")]
    Foo(u8),
    #[error("{0:?}")]
    Bar(u16),
    #[error("{0:?}")]
    Baz(u32),
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::fmt::Debug for Bar {
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match (&*self,) {
            (&Bar::Foo(ref __self_0),) => {
                let mut debug_trait_builder = f.debug_tuple("Foo");
                let _ = debug_trait_builder.field(&&(*__self_0));
                debug_trait_builder.finish()
            }
            (&Bar::Bar(ref __self_0),) => {
                let mut debug_trait_builder = f.debug_tuple("Bar");
                let _ = debug_trait_builder.field(&&(*__self_0));
                debug_trait_builder.finish()
            }
            (&Bar::Baz(ref __self_0),) => {
                let mut debug_trait_builder = f.debug_tuple("Baz");
                let _ = debug_trait_builder.field(&&(*__self_0));
                debug_trait_builder.finish()
            }
        }
    }
}
impl std::error::Error for Bar {}
impl std::fmt::Display for Bar {
    fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        #[allow(unused_variables, deprecated)]
        match self {
            Bar::Foo(_0) => __formatter.write_fmt(::core::fmt::Arguments::new_v1(
                &[""],
                &match (&_0,) {
                    (arg0,) => [::core::fmt::ArgumentV1::new(arg0, ::core::fmt::Debug::fmt)],
                },
            )),
            Bar::Bar(_0) => __formatter.write_fmt(::core::fmt::Arguments::new_v1(
                &[""],
                &match (&_0,) {
                    (arg0,) => [::core::fmt::ArgumentV1::new(arg0, ::core::fmt::Debug::fmt)],
                },
            )),
            Bar::Baz(_0) => __formatter.write_fmt(::core::fmt::Arguments::new_v1(
                &[""],
                &match (&_0,) {
                    (arg0,) => [::core::fmt::ArgumentV1::new(arg0, ::core::fmt::Debug::fmt)],
                },
            )),
        }
    }
}

@dtolnay
Copy link
Owner

dtolnay commented May 15, 2020

Thanks for the nice repro. You are right that this is due to a compiler bug (rust-lang/rust#43081) but I've published a workaround in thiserror 1.0.18.

@ghost
Copy link
Author

ghost commented May 16, 2020

Thanks for the information and swift workaround!

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 a pull request may close this issue.

1 participant