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

Why does macro hygiene not prevent collisions between multiple const definitions?

我认为 "hygiene" 可以防止在我的宏 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

来自The Rust Programming Language(第一版)的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

这是有道理的:如果您在宏中引入一个项目,您可能想从其他 items/modules/crates 实际使用它(因此在宏之外),但如果您不这样做,则不能知道它的名字,所以编译器不能重命名它。