2017-06-08 15 views
0

fn a() {}は、fnを期待する解析ルールを満たしているようです。 itemは関数定義でなければなりません。そう、彼らはうまくいくはずですよね?マクロ展開内で特性を実装しようとしたときにマクロエラーが発生しました

macro_rules! multi_impl { 
    (for $base:ty : 
     $($t:ty { 
      $($i:item);* 
     }),+) => 
    { 
     $(
      impl $t for $base 
      { 
       $($i)* 
      } 
     )+ 
    } 
} 

trait A { 
    fn a(); 
} 

trait B { 
    fn b(); 
} 

struct S; 

multi_impl! { 
    for S: 
    A { 
     fn a() {} 
    }, B { 
     fn b() {} 
    } 
} 

fn main() { 
    S::a(); 
    S::b(); 
} 

playground

問題のエラー:それ$(fn $i)*作る

error: expected one of `const`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `fn a() { }` 
    --> <anon>:11:20 
    | 
11 |     $($i)* 
    |     ^^ 

だけ理にかなっている、fn後の識別子を期待して文句を言うために、エラーを変更しますが、最初のエラーはありません(少なくとも私にとっては)。

マクロによってソースに配置されたソースコードとコードの間にパーサーとの違いはありますか?

答えて

3

問題はfnが項目ではありません、それはimplのボディは項目が含まれていないことだということではありません。それは "インプルートアイテム"を含んでいます。それは、ブロックが間違った色ではなく、丸い穴に四角形のブロックを入れようとしていることです。

はい、これは2つの異なるものです。いいえ、あなたはできませんマクロで "インプルアイテム"をキャプチャできません。いいえ、アイテムをインプルアイテムにすることはできません。マクロはトークンではなくASTノードを取得するためです。メソッドにはself引数があり、正規関数には引数がありません。おそらく、当時は良いアイデアのように思えた。余談架空の前後を置く

、この場合の解決策は特にには何も一致し、ちょうどに一致するようにしようと気にしないことです。

macro_rules! multi_impl 
{ 
    (for $base:ty : 
     $($t:ty { 
      $($body:tt)* 
     }),+) => 
    { 
     $(
      impl $t for $base 
      { 
       $($body)* 
      } 
     )+ 
    } 
} 
関連する問題