Macro_rules compilation error: cannot find value `X` in this scope

I have a macro that allow me to generate dynamic struct with dynamic methods. What I want to achieve: I need to generate dynamic methods for returned struct in format get_<prop_name> (for example, get_size).

But on compile I got an error:

error[E0425]: cannot find value `size` in this scope
   --> src/main.rs:103:13
    |
103 |             size: u16;
    |             ^^^^ not found in this scope

For more information about this error, try `rustc --explain E0425`.
error: could not compile `playground` due to previous error

this is my code:

macro_rules! packet {
    // first rule
    (
        properties {
            $(opcode $opcode_value:expr;)?
        }
        
        $(#[$outer:meta])*
        $vis:vis struct $PacketStruct:ident {
            $($field_name:ident: $field_type:ty),*$(,)?
        }
        
        $($StructImpl: item)*
    ) => {
        $(#[$outer])*
        #[derive(Clone)]
        $vis struct $PacketStruct {
            $($field_name: $field_type),*
        }
        
        $($StructImpl)*
        
        $(
            impl $PacketStruct {
                pub fn get_opcode() -> u32 {
                    $opcode_value
                }
            }
        )?
    };
    // eof first rule
    // second rule
    (
        properties {
            opcode $opcode_value:expr;
            $($prop_name:ident: $prop_type:ty;)*
        }
        
        $(#[$outer:meta])*
        $vis:vis struct $PacketStruct:ident {
            $($field_name:ident: $field_type:ty),*$(,)?
        }
        
        $($StructImpl: item)*
    ) => {
        packet! {
            properties {
                $($prop_name: $prop_type;)*
            }
            $(#[$outer])*
            $vis struct $PacketStruct {
                $($field_name: $field_type),*
            }
            
            $($StructImpl)*
            
            impl $PacketStruct {
                pub fn get_opcode() -> u32 {
                    $opcode_value
                }
            }
        }
    };
    // eof of second rule
    // third rule
    (
        properties {
            $($prop_name:ident: $prop_type:ty;)*
        }
        
        $(#[$outer:meta])*
        $vis:vis struct $PacketStruct:ident {
            $($field_name:ident: $field_type:ty),*$(,)?
        }
        
        $($StructImpl: item)*
    ) => {
        $(#[$outer])*
        #[derive(Clone)]
        $vis struct $PacketStruct {
            $($field_name: $field_type),*
        }
        
        $($StructImpl)*
        
        $(
            paste::item! {
                impl $PacketStruct {
                    pub fn [< get_ $prop_name >]() -> $prop_type {
                        $prop_name
                    }
                }
            }
        )*
    };
}


fn main() {
    packet! {
        properties {
            opcode 100;
            size: u16;
        }
        
        #[derive(Hash)]
        pub struct Outcome {
            name: String,
            os: u8,
            game_name: String,
        }
        
        impl Outcome {
            pub fn one() {
                println!("TEST")
            }
        }
        
        impl Outcome {
            pub fn two() {
                println!("TEST2")
            }
        }
    }
    
    // println!("{:?}", Outcome::get_opcode());
    // Outcome::one();
    // Outcome::two();
}

Sandbox.

Could somebody explain why this not compile ?

It looks like you're generating a function like

pub fn get_size() -> u16 {
    size 
}

but there's nothing called size defined anywhere, so the compiler complains that it cannot find it.

1 Like