Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust macro cannot find value in scope [duplicate]

Tags:

macros

rust

I made a rust macro, that literally pastes some code to where i call it. I hardcoded some things into there, which it can't find unfortunaly.

That's how my code is structured:

macro_rules! foo {
    println!("{}", number);
}

fn bar() {
    let number: i32 = 10;
    foo!(); //--> cannot find 'number', even if it is right above here
}
like image 227
v22 Avatar asked Jul 21 '26 06:07

v22


2 Answers

This is because of macro hygiene. Local identifiers introduced inside a macro cannot be used outside and vice versa.

The reason for this design choice is so that macros can't accidentally change the behaviour of unrelated code. You don't need to study the implementation of a macro to know for sure that it isn't going to have a naming collision with your own code.

It's a bit like how local variables inside a function are not visible to calling functions. Changing the name of a local variable in a function cannot break or change the meaning of code that happens to call that function.

There are two main ways to do what you want:

  1. Pass the identifier as an argument to the macro. This way, the identifier token originates outside of the macro, so it is allowed to refer to identifiers in that scope:
    macro_rules! foo {
        ($ident: ident) => {
             println!("{}", $ident);
        }
    }
    
    fn bar() {
        let number: i32 = 10;
        foo!(number);
    }
    
  2. The other way is to define the macro so that the variable is already in scope for the macro definition to use. See user2722968's answer. The downside of this solution is that you are very limited about where you can call it.
like image 58
Peter Hall Avatar answered Jul 23 '26 13:07

Peter Hall


You need to move the macro-definition into the scope of number, so number gets captured during the macro-definition and is available in the subsequent expansion:

fn main() {
    let number: i32 = 10;
    
    macro_rules! foo {
        () => { println!("{}", number); }
    }
    
    foo!();
}
like image 44
user2722968 Avatar answered Jul 23 '26 14:07

user2722968



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!