| // Check that we are refusing to match on complex nonterminals for which tokens are |
| // unavailable and we'd have to go through AST comparisons. |
| |
| #![feature(decl_macro)] |
| |
| macro simple_nonterminal($nt_ident: ident, $nt_lifetime: lifetime, $nt_tt: tt) { |
| macro n(a $nt_ident b $nt_lifetime c $nt_tt d) { |
| struct S; |
| } |
| |
| n!(a $nt_ident b $nt_lifetime c $nt_tt d); |
| } |
| |
| macro complex_nonterminal($nt_item: item) { |
| macro n(a $nt_item b) { |
| struct S; |
| } |
| |
| n!(a $nt_item b); //~ ERROR no rules expected the token `enum E {}` |
| } |
| |
| simple_nonterminal!(a, 'a, (x, y, z)); // OK |
| |
| complex_nonterminal!(enum E {}); |
| |
| // `ident`, `lifetime`, and `tt` all work. Other fragments do not. See |
| // https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment |
| macro_rules! foo { |
| (ident $x:ident) => { bar!(ident $x); }; |
| (lifetime $x:lifetime) => { bar!(lifetime $x); }; |
| (tt $x:tt) => { bar!(tt $x); }; |
| (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected the token `3` |
| (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected the token `4` |
| (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected the token `a::b::c` |
| (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected the token `let abc = 0` |
| } |
| |
| macro_rules! bar { |
| (ident abc) => {}; |
| (lifetime 'abc) => {}; |
| (tt 2) => {}; |
| (expr 3) => {}; |
| (literal 4) => {}; |
| (path a::b::c) => {}; |
| (stmt let abc = 0) => {}; |
| } |
| |
| foo!(ident abc); |
| foo!(lifetime 'abc); |
| foo!(tt 2); |
| foo!(expr 3); |
| foo!(literal 4); |
| foo!(path a::b::c); |
| foo!(stmt let abc = 0); |
| |
| fn main() {} |