有没有办法在Rust宏中引用局部变量?

问题描述

我想使用宏来生成函数的主体,但要这样做,它们需要访问局部作用域中的变量:

macro_rules! generate_func {
    ($name:ident) => {
        fn $name(param: i32) {
            generate_body!()
        }
    };
}

macro_rules! generate_body {
    () => {
        println!("{}",&param);
    }
}

generate_func!(foo);
error[E0425]: cannot find value `param` in this scope
  --> src/lib.rs:11:25
   |
11 |         println!("{}",&param);
   |                         ^^^^^ not found in this scope
...
15 | generate_func!(foo);
   | -------------------- in this macro invocation
   |
   = note: this error originates in a macro (in Nightly builds,run with -Z macro-backtrace for more info)

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0341ce89736b620af9143a4e3d41a5a4

令人沮丧的是,这不起作用,因为我可以运行cargo-expand并看到生成的代码是有效的:

fn foo(param: i32) {

    {
        ::std::io::_print(::core::fmt::Arguments::new_v1(&["","\n"],&match (&&param,) {
                                                              (arg0,) =>
                                                              [::core::fmt::ArgumentV1::new(arg0,::core::fmt::Display::fmt)],}));
    }
}

(由于println!有点混乱,但是您可以在其中看到有效的引用)

我什至可以将扩展复制并粘贴到我的源代码中,编译器会接受它。当然有某种方法可以达到预期的结果?

似乎与以下内容有关:

但是我不确定我是否有完全相同的问题;我的情况似乎更基本。

解决方法

Rust宏为hygienic,可防止标识符从一个作用域泄漏到另一个作用域并引起各种混乱。但是您可以通过将paramgenerate_func传递到generate_body来解决这个特定问题:

macro_rules! generate_func {
    ($name:ident) => {
        fn $name(param: i32) {
            generate_body!(param)
        }
    };
}

macro_rules! generate_body {
    ($param:ident) => {
        println!("{}",&$param);
    }
}

generate_func!(foo);

Playground上看到它。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...