宏-为什么宏卫生不能阻止多个const定义之间的冲突?

我以为“卫生”可以防止宏m中定义的X之间发生冲突!但是事实并非如此.我有什么误会?

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

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

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

Playground

错误信息:

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
最佳答案
从Rust编程语言(第一版)的section on macro hygiene

This [i.e. renaming] holds for let bindings and loop labels, but not for items

Rust参考定义了items

An item is a component of a crate. Items are organized within a crate
by a nested set of modules. Every crate has a single “outermost”
anonymous module; all further items within the crate have paths within
the module tree of the crate.

Items are entirely determined at compile-time, generally remain fixed
during execution, and may reside in read-only memory.

There are several kinds of items:

  • modules
  • extern crate declarations
  • use declarations
  • function definitions
  • type definitions
  • struct definitions
  • enumeration definitions
  • union definitions
  • constant items
  • static items
  • trait definitions
  • implementations
  • extern blocks

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

转载注明原文:宏-为什么宏卫生不能阻止多个const定义之间的冲突? - 代码日志