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

时间:2016-03-26 21:00:49

标签: macros rust metaprogramming hygiene

我认为“卫生”会阻止我的宏X中定义的m!之间的冲突,但结果并非如此。我误解了什么?

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

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

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

Playpen

错误讯息:

<anon>:3:9: 3:27 error: duplicate definition of value `X` [E0428]
<anon>:3         const X: i32 = $e;
                 ^~~~~~~~~~~~~~~~~~
<anon>:8:1: 8:7 note: in this expansion of m! (defined in <anon>)
<anon>:3:9: 3:27 help: see the detailed explanation for E0428
<anon>:3:9: 3:27 note: first definition of value `X` here
<anon>:3         const X: i32 = $e;
                 ^~~~~~~~~~~~~~~~~~
<anon>:7:1: 7:7 note: in this expansion of m! (defined in <anon>)
<anon>:3:9: 3:27 error: duplicate definition of value `X` [E0428]
<anon>:3         const X: i32 = $e;
...snip...

1 个答案:

答案 0 :(得分:1)

来自https://doc.rust-lang.org/book/macros.html#hygiene

  

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

https://doc.rust-lang.org/reference.html#items

  

项目是箱子的组成部分。项目由嵌套的模块组成。每个箱子都有一个最外面的#34;匿名模块;包中的所有其他项目都在包的模块树中有路径。

     

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

     

有几种项目:

     
      
  • extern crate declarations
  •   
  • 使用声明
  •   
  • 模块
  •   
  • 功能
  •   
  • 类型定义
  •   
  • 结构
  •   
  • 枚举
  •   
  • 常量项
  •   
  • 静态物品
  •   
  • 性状
  •   
  • 实现
  •   

这是有道理的:如果你在宏中介绍一个项目,你可能想要从其他项目/模块/板条箱中实际使用它(因此在宏外面),但是如果你没有&#39,你就不能这样做。 ; t知道它的名字,所以编译器不能重命名它。