mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
dd2b027d5d
Much like the previous commit. I think the removal of "the token" in each message is fine here. There are many more error messages that mention tokens without saying "the token" than those that do say it.
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 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() {}
|