为什么宏卫生不能防止多个 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);
}
错误信息:
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 实际使用它(因此在宏之外),但如果您不这样做,则不能知道它的名字,所以编译器不能重命名它。
我认为 "hygiene" 可以防止在我的宏 m!
中定义的 X
之间发生冲突,但事实并非如此。我误会了什么?
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
来自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
declarationsuse
declarations- function definitions
- type definitions
- struct definitions
- enumeration definitions
- union definitions
- constant items
- static items
- trait definitions
- implementations
extern
blocks
这是有道理的:如果您在宏中引入一个项目,您可能想从其他 items/modules/crates 实际使用它(因此在宏之外),但如果您不这样做,则不能知道它的名字,所以编译器不能重命名它。