2017-12-28 4 views
1

私は錆のマクロシステムを介してディーゼル上のORMラッパーを作成しようとしています。に属して働いて、私は錆がかなり予期しないエラーを送信していることがわかりました。次のコードを考えてみてください:錆マクロ奇妙なエラー

macro_rules! klass { 
    (
     $name:ident, 
     fields => ($(
      $field:ident : $type:ty = $default:expr, 
     )*), 
     belongs_to => ($(
      $belong_field:ident : $temp:ty [ $key:expr ], 
     )*) 
    ) => { 
     struct $name { 
      $($field: $type,)* 
     } 
     impl Default for $name { 
      fn default() -> $name { 
       $name { 
        $(
         $field : $default, 
        )* 
       } 
      } 
     } 
     impl $name { 
      $(
       fn $belong_field(&self) -> $temp { 
        let key = $key; 
        $temp { ..Default::default() } 
       } 
      )* 
     } 
    } 
} 

klass! (Neat, 
     fields => (
      id: i32 = 0, 
      name: String = String::from(""), 
     ), 
     belongs_to =>() 
    ); 

klass!(Bob, 
    fields => (
     id: i32 = 0, 
     neat_id: i32 = 0, 
    ), 
    belongs_to => (
     neat: Neat [ "neat_id" ], 
    ) 
); 

fn main() 
{ 
    let b = Bob { ..Default::default() }; 
    let mut n = b.neat(); 
} 

このコードは次のような結果が得られます:錆が、それは代わりに、ニートの発現を望んでいると言うんなぜ

error: expected expression, found `Neat` 
    --> macro.rs:27:31 
    | 
27 |      $temp { ..Default::default() } 
    | 

を?私は、次にこのコードを変更することができ、この例ではすべてがコンパイルし、実行:

Neat { ..Default::default() } 

が、これは「ニート」が期待通りのプログラムが実行される挿入されたときに与えられたコンパイラエラーか?おかげさまで、これが主にコードであることをお詫びします。

答えて

3

$tempは、マクロ展開のさまざまなコンテキストで発生します。型としてfn $belong_field(&self) -> $tempと構造体コンストラクタとして$temp { ..Default::default() }にあります。

タイプとして$tempとマークして、2度目の使用を防ぎます。

$belong_field:ident : $temp:ident [ $key:expr ], 

とライン

$belong_field:ident : $temp:ty [ $key:expr ], 

を交換

は、コードをコンパイルすることを可能にします。

+0

これはうまく機能しています。ありがとうございました! –