// 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 item `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 expression `3` (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4` (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected path `a::b::c` (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected statement `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() {}