2017-06-08 2 views
0

fn a() {} scheint eine Parsing-Regel zu erfüllen, die eine fn erwartet, dann einige andere Sachen. item s sollte Funktionsdefinitionen sein können, oder? Also sollten sie arbeiten, oder?Makrofehler beim Versuch, ein Merkmal innerhalb einer Makroerweiterung zu implementieren

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

Der Fehler in Frage:

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

es machen $(fn $i)* ändert nur die Fehler zu erwarten eine Kennung nach dem fn zu beschweren, was Sinn macht, aber die anfängliche Fehler tut nicht (zumindest für mich).

Gibt es einen Unterschied zum Parser bezüglich Code, der in der Quell-vs-Code ist, die von einem Makro in der Quelle platziert wird?

Antwort

3

Das Problem ist nicht, dass ein fn kein Element ist, dann ist es, dass der Körper eines implnicht Elemente enthalten. Es enthält "Impl-Elemente". Worüber sie sich beschweren, ist, dass du versuchst, einen quadratischen Block in ein rundes Loch zu stecken, nicht dass der Block die falsche Farbe hat.

Ja, das sind zwei verschiedene Dinge. Nein, Sie kann nicht erfassen "impl Elemente" in einem Makro. Nein, du kannst einen Gegenstand nicht zu einem Impl-Gegenstand machen. Weil Makros AST-Knoten erfassen, nicht die Token. Nun, Methoden können ein self Argument haben und normale Funktion nicht. Ich weiß es nicht, vermutlich schien es zu dieser Zeit eine gute Idee zu sein.

beiseite die hypothetische zurück und nach vorne Einlochen, ist die Lösung in diesem Fall nicht versuchen, die Mühe machen, in insbesondere passen und passen nur etwas.

macro_rules! multi_impl 
{ 
    (for $base:ty : 
     $($t:ty { 
      $($body:tt)* 
     }),+) => 
    { 
     $(
      impl $t for $base 
      { 
       $($body)* 
      } 
     )+ 
    } 
} 
Verwandte Themen