bca5cd3a9d
To involve `macro_rules!` macros, and also a mix of fragment specifiers, some of which feature the forwaring limitation and some of which don't.
57 lines
1.6 KiB
Rust
57 lines
1.6 KiB
Rust
// 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() {}
|