about summary refs log tree commit diff
path: root/src/libsyntax/ext/tt/macro_rules.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax/ext/tt/macro_rules.rs')
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs52
1 files changed, 6 insertions, 46 deletions
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 54f901d095b..4503cea0f10 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -2,6 +2,7 @@ use crate::edition::Edition;
 use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
 use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
 use crate::ext::expand::{AstFragment, AstFragmentKind};
+use crate::ext::tt::macro_check;
 use crate::ext::tt::macro_parser::{parse, parse_failure_msg};
 use crate::ext::tt::macro_parser::{Error, Failure, Success};
 use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq};
@@ -18,7 +19,7 @@ use crate::{ast, attr, attr::TransparencyError};
 
 use errors::FatalError;
 use log::debug;
-use syntax_pos::{symbol::Ident, Span};
+use syntax_pos::Span;
 
 use rustc_data_structures::fx::FxHashMap;
 use std::borrow::Cow;
@@ -366,14 +367,12 @@ pub fn compile(
     // don't abort iteration early, so that errors for multiple lhses can be reported
     for lhs in &lhses {
         valid &= check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
-        valid &= check_lhs_duplicate_matcher_bindings(
-            sess,
-            slice::from_ref(lhs),
-            &mut FxHashMap::default(),
-            def.id,
-        );
     }
 
+    // We use CRATE_NODE_ID instead of `def.id` otherwise we may emit buffered lints for a node id
+    // that is not lint-checked and trigger the "failed to process buffered lint here" bug.
+    valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses);
+
     let expander: Box<_> =
         Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, lhses, rhses, valid });
 
@@ -497,45 +496,6 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool {
     true
 }
 
-/// Check that the LHS contains no duplicate matcher bindings. e.g. `$a:expr, $a:expr` would be
-/// illegal, since it would be ambiguous which `$a` to use if we ever needed to.
-fn check_lhs_duplicate_matcher_bindings(
-    sess: &ParseSess,
-    tts: &[quoted::TokenTree],
-    metavar_names: &mut FxHashMap<Ident, Span>,
-    node_id: ast::NodeId,
-) -> bool {
-    use self::quoted::TokenTree;
-    for tt in tts {
-        match *tt {
-            TokenTree::MetaVarDecl(span, name, _kind) => {
-                if let Some(&prev_span) = metavar_names.get(&name) {
-                    sess.span_diagnostic
-                        .struct_span_err(span, "duplicate matcher binding")
-                        .span_note(prev_span, "previous declaration was here")
-                        .emit();
-                    return false;
-                } else {
-                    metavar_names.insert(name, span);
-                }
-            }
-            TokenTree::Delimited(_, ref del) => {
-                if !check_lhs_duplicate_matcher_bindings(sess, &del.tts, metavar_names, node_id) {
-                    return false;
-                }
-            }
-            TokenTree::Sequence(_, ref seq) => {
-                if !check_lhs_duplicate_matcher_bindings(sess, &seq.tts, metavar_names, node_id) {
-                    return false;
-                }
-            }
-            _ => {}
-        }
-    }
-
-    true
-}
-
 fn check_rhs(sess: &ParseSess, rhs: &quoted::TokenTree) -> bool {
     match *rhs {
         quoted::TokenTree::Delimited(..) => return true,