3

X我认为“卫生”可以防止在我的宏中定义的 s之间发生冲突,m!但事实并非如此。我有什么误解?

macro_rules! m {
    ($e:expr) => {
        const X: i32 = $e;
    };
}

m!(0);
m!(1);

fn main() {
    m!(2);
    m!(3);
}

操场

错误信息:

error[E0428]: the name `X` is defined multiple times
 --> src/main.rs:3:9
  |
3 |         const X: i32 = $e;
  |         ^^^^^^^^^^^^^^^^^^
  |         |
  |         `X` redefined here
  |         previous definition of the value `X` here
...
7 | m!(0);
  | ------ in this macro invocation
  |
  = note: `X` must be defined only once in the value namespace of this module
4

1 回答 1

3

来自Rust 编程语言(第一版)关于宏卫生的部分

这[即重命名]适用于let绑定和循环标签,但不适用于项目

Rust 参考定义了items

物品是箱子的组成部分。项目由一组嵌套的模块组织在一个 crate 中。每个 crate 都有一个“最外层”的匿名模块;crate 中的所有其他项目在 crate 的模块树中都有路径。

项目在编译时完全确定,通常在执行期间保持固定,并且可能驻留在只读内存中。

有几种物品:

  • 模块
  • extern crate声明
  • use声明
  • 函数定义
  • 类型定义
  • 结构定义
  • 枚举定义
  • 联合定义
  • 常数项
  • 静态项目
  • 特征定义
  • 实现
  • extern

这是有道理的:如果你在宏中引入一个项目,你可能想从其他项目/模块/板条箱中实际使用它(因此在宏之外),但如果你不知道它的名称,你就不能,所以编译器无法重命名它。

于 2016-03-27T00:29:41.957 回答