2016-03-26 8 views
2

私はXのマクロ内で定義されたm!の間で "衛生"が衝突するのを防ぐと思っていましたが、そうでないことが判明しました。私は何を誤解していますか?なぜマクロ衛生は複数のconst定義間の衝突を防ぎませんか?

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

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

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

Playpen

エラーメッセージ:https://doc.rust-lang.org/book/macros.html#hygieneから

<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

この[すなわち名前変更は】LETバインディングとループラベルの保持はなく、アイテム

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

アイテムはクレートの構成要素です。アイテムは、モジュールのネストされたセットによってクレート内に編成されます。すべての箱には、一番外側の匿名モジュールが1つあります。クレート内の他のすべてのアイテムは、クレートのモジュールツリー内にパスを持ちます。

項目はコンパイル時にすべて決定され、一般に実行中は固定されたままであり、読み取り専用メモリに存在する可能性があります。

は、アイテムのいくつかの種類がある:

  • のexternクレート宣言
  • 使用宣言
  • モジュール
  • 機能
  • 型定義
  • 構造体
  • 列挙
  • 一定の項目
  • 静的項目
  • 特徴
  • 実装

これは理にかなって:あなたは、マクロ内のアイテムを紹介している場合、あなたはおそらく、実際に他の項目から、それを使用したいです/ modules/crates(したがってマクロの外に)、名前を知らないとコンパイラは名前を変更できません。

+0

ありがとうございました。それは設計によるものです。 "あなたが実際にそれを使用したいと思うマクロに商品を紹介したら、"さて、それは衛生的なマクロシステムとして宣伝されているものを使う方法ではないと思います... – nodakai

+0

@nodakai申し訳ありませんが、私は "外でしたマクロ "があります。あなたの場合、 'println!(" X = {} "、X);を最後の' m!(3) 'の後に置けば、何を印刷すると思いますか? –

+0

私はRustマクロが衛生的であると聞いたとき、私は "未知の変数X"のエラーを予想します。 – nodakai

関連する問題