Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

destructured items not found when destructuring an enum inside a macro

macro_rules! declare_types {
    ($($token:ident -> $inner:ty, $to_string:expr,)*) => {
        enum Value {
            $($token($inner),)*
        }

        impl Display for Value {
            fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> {
                match self {
                    $(
                        Self::$token(inner)=>write!(fmt,"{}",$to_string)?,
                    )*
                };
                Ok(())
            }
        }
    }
}

declare_types!(
    String -> String, inner,
);

However, the code results in a compiler error:

cannot find value `inner` in this scope
not found in this scope

When I hover onto inner, IDE shows it properly:

ide hover

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Also, by expanding the macro and pasting it back, it works without any errors.

>Solution :

Because of macro hygiene, identifiers created inside the macro (like inner in Self::$token (inner)) are different from identifiers created in the calling code (like inner in declare_types!(String -> String, inner);). If you want to be able to use an identifier in the displayed expression, you will need to pass this identifier to the macro from the caller:

macro_rules! declare_types {
    ($($token:ident -> $inner:ty, $id: ident, $to_string:expr,)*) => {
        enum Value {
            $($token($inner),)*
        }

        impl std::fmt::Display for Value {
            fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
                match self {
                    $(
                        Self::$token($id)=>write!(fmt,"{}",$to_string)?,
                    )*
                };
                Ok(())
            }
        }
    }
}

declare_types!(
    String -> String, inner, inner,
);

Playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading