]> git.lizzy.rs Git - rust.git/commitdiff
macros: Do not match on "complex" nonterminals requiring AST comparisons
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 24 Mar 2018 13:00:44 +0000 (16:00 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Fri, 13 Apr 2018 23:28:39 +0000 (02:28 +0300)
src/libsyntax/parse/token.rs
src/test/ui/macros/nonterminal-matching.rs [new file with mode: 0644]
src/test/ui/macros/nonterminal-matching.stderr [new file with mode: 0644]

index 8da79f92768a1c31e3658f7a6b4654301f2ebada..35a745ccdee32f2e48ba3e2b31829226e39416f0 100644 (file)
@@ -565,7 +565,7 @@ pub fn interpolated_to_tokenstream(&self, sess: &ParseSess, span: Span)
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Eq, Hash)]
 /// For interpolation during macro expansion.
 pub enum Nonterminal {
     NtItem(P<ast::Item>),
@@ -591,6 +591,22 @@ pub enum Nonterminal {
     NtArg(ast::Arg),
 }
 
+impl PartialEq for Nonterminal {
+    fn eq(&self, rhs: &Self) -> bool {
+        match (self, rhs) {
+            (NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) =>
+                ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs,
+            (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
+            (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
+            // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
+            // correctly based on data from AST. This will prevent them from matching each other
+            // in macros. The comparison will become possible only when each nonterminal has an
+            // attached token stream from which it was parsed.
+            _ => false,
+        }
+    }
+}
+
 impl fmt::Debug for Nonterminal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
diff --git a/src/test/ui/macros/nonterminal-matching.rs b/src/test/ui/macros/nonterminal-matching.rs
new file mode 100644 (file)
index 0000000..4dcb8af
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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_lifetime_matcher)]
+
+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 {});
+
+fn main() {}
diff --git a/src/test/ui/macros/nonterminal-matching.stderr b/src/test/ui/macros/nonterminal-matching.stderr
new file mode 100644 (file)
index 0000000..bf2221d
--- /dev/null
@@ -0,0 +1,11 @@
+error: no rules expected the token `enum E { }`
+  --> $DIR/nonterminal-matching.rs:29:10
+   |
+LL |     n!(a $nt_item b); //~ ERROR no rules expected the token `enum E { }`
+   |          ^^^^^^^^
+...
+LL | complex_nonterminal!(enum E {});
+   | -------------------------------- in this macro invocation
+
+error: aborting due to previous error
+