Skip to content

Commit 7e1f73b

Browse files
committed
macros: Do not match on "complex" nonterminals requiring AST comparisons
1 parent 7291829 commit 7e1f73b

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

src/libsyntax/parse/token.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ impl Token {
565565
}
566566
}
567567

568-
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
568+
#[derive(Clone, RustcEncodable, RustcDecodable, Eq, Hash)]
569569
/// For interpolation during macro expansion.
570570
pub enum Nonterminal {
571571
NtItem(P<ast::Item>),
@@ -591,6 +591,22 @@ pub enum Nonterminal {
591591
NtArg(ast::Arg),
592592
}
593593

594+
impl PartialEq for Nonterminal {
595+
fn eq(&self, rhs: &Self) -> bool {
596+
match (self, rhs) {
597+
(NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) =>
598+
ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs,
599+
(NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
600+
(NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
601+
// FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
602+
// correctly based on data from AST. This will prevent them from matching each other
603+
// in macros. The comparison will become possible only when each nonterminal has an
604+
// attached token stream from which it was parsed.
605+
_ => false,
606+
}
607+
}
608+
}
609+
594610
impl fmt::Debug for Nonterminal {
595611
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
596612
match *self {
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Check that we are refusing to match on complex nonterminals for which tokens are
12+
// unavailable and we'd have to go through AST comparisons.
13+
14+
#![feature(decl_macro, macro_lifetime_matcher)]
15+
16+
macro simple_nonterminal($nt_ident: ident, $nt_lifetime: lifetime, $nt_tt: tt) {
17+
macro n(a $nt_ident b $nt_lifetime c $nt_tt d) {
18+
struct S;
19+
}
20+
21+
n!(a $nt_ident b $nt_lifetime c $nt_tt d);
22+
}
23+
24+
macro complex_nonterminal($nt_item: item) {
25+
macro n(a $nt_item b) {
26+
struct S;
27+
}
28+
29+
n!(a $nt_item b); //~ ERROR no rules expected the token `enum E { }`
30+
}
31+
32+
simple_nonterminal!(a, 'a, (x, y, z)); // OK
33+
34+
complex_nonterminal!(enum E {});
35+
36+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: no rules expected the token `enum E { }`
2+
--> $DIR/nonterminal-matching.rs:29:10
3+
|
4+
LL | n!(a $nt_item b); //~ ERROR no rules expected the token `enum E { }`
5+
| ^^^^^^^^
6+
...
7+
LL | complex_nonterminal!(enum E {});
8+
| -------------------------------- in this macro invocation
9+
10+
error: aborting due to previous error
11+

0 commit comments

Comments
 (0)