diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 0e20e0970f401..02169a5082fab 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -110,7 +110,7 @@ use rustc_ast::token::{DelimToken, Token, TokenKind}; use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::MultiSpan; -use rustc_session::lint::builtin::META_VARIABLE_MISUSE; +use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER}; use rustc_session::parse::ParseSess; use rustc_span::symbol::kw; use rustc_span::{symbol::MacroRulesNormalizedIdent, Span}; @@ -261,7 +261,16 @@ fn check_binders( } } // Similarly, this can only happen when checking a toplevel macro. - TokenTree::MetaVarDecl(span, name, _kind) => { + TokenTree::MetaVarDecl(span, name, kind) => { + if kind.is_none() { + sess.buffer_lint( + MISSING_FRAGMENT_SPECIFIER, + span, + node_id, + &format!("missing fragment specifier"), + ); + *valid = false; + } if !macros.is_empty() { sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in nested lhs"); } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index ffe8b10e6877a..779aaed7299f9 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -131,7 +131,7 @@ pub(super) enum MatcherLoc { MetaVarDecl { span: Span, bind: Ident, - kind: Option, + kind: NonterminalKind, next_metavar: usize, seq_depth: usize, }, @@ -189,7 +189,7 @@ pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec Option { @@ -508,20 +507,12 @@ impl TtParser { mp.idx = idx_first; self.cur_mps.push(mp); } - &MatcherLoc::MetaVarDecl { span, kind, .. } => { + &MatcherLoc::MetaVarDecl { kind, .. } => { // Built-in nonterminals never start with these tokens, so we can eliminate // them from consideration. We use the span of the metavariable declaration // to determine any edition-specific matching behavior for non-terminals. - if let Some(kind) = kind { - if Parser::nonterminal_may_begin_with(kind, token) { - self.bb_mps.push(mp); - } - } else { - // Both this check and the one in `nameize` are necessary, surprisingly. - if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { - // E.g. `$e` instead of `$e:expr`. - return Some(Error(span, "missing fragment specifier".to_string())); - } + if Parser::nonterminal_may_begin_with(kind, token) { + self.bb_mps.push(mp); } } MatcherLoc::Eof => { @@ -547,7 +538,7 @@ impl TtParser { // Need to take ownership of the matches from within the `Lrc`. Lrc::make_mut(&mut eof_mp.matches); let matches = Lrc::try_unwrap(eof_mp.matches).unwrap().into_iter(); - self.nameize(sess, matcher, matches) + self.nameize(matcher, matches) } EofMatcherPositions::Multiple => { Error(token.span, "ambiguity: multiple successful parses".to_string()) @@ -585,7 +576,7 @@ impl TtParser { // Process `cur_mps` until either we have finished the input or we need to get some // parsing from the black-box parser done. - if let Some(res) = self.parse_tt_inner(&parser.sess, matcher, &parser.token) { + if let Some(res) = self.parse_tt_inner(matcher, &parser.token) { return res; } @@ -615,11 +606,7 @@ impl TtParser { let mut mp = self.bb_mps.pop().unwrap(); let loc = &matcher[mp.idx]; if let &MatcherLoc::MetaVarDecl { - span, - kind: Some(kind), - next_metavar, - seq_depth, - .. + span, kind, next_metavar, seq_depth, .. } = loc { // We use the span of the metavariable declaration to determine any @@ -668,7 +655,7 @@ impl TtParser { .bb_mps .iter() .map(|mp| match &matcher[mp.idx] { - MatcherLoc::MetaVarDecl { bind, kind: Some(kind), .. } => { + MatcherLoc::MetaVarDecl { bind, kind, .. } => { format!("{} ('{}')", kind, bind) } _ => unreachable!(), @@ -692,7 +679,6 @@ impl TtParser { fn nameize>( &self, - sess: &ParseSess, matcher: &[MatcherLoc], mut res: I, ) -> NamedParseResult { @@ -700,21 +686,13 @@ impl TtParser { // `NamedParseResult`. Otherwise, it's an error. let mut ret_val = FxHashMap::default(); for loc in matcher { - if let &MatcherLoc::MetaVarDecl { span, bind, kind, .. } = loc { - if kind.is_some() { - match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) { - Vacant(spot) => spot.insert(res.next().unwrap()), - Occupied(..) => { - return Error(span, format!("duplicated bind name: {}", bind)); - } - }; - } else { - // Both this check and the one in `parse_tt_inner` are necessary, surprisingly. - if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { - // E.g. `$e` instead of `$e:expr`. - return Error(span, "missing fragment specifier".to_string()); + if let &MatcherLoc::MetaVarDecl { span, bind, .. } = loc { + match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) { + Vacant(spot) => spot.insert(res.next().unwrap()), + Occupied(..) => { + return Error(span, format!("duplicated bind name: {}", bind)); } - } + }; } } Success(ret_val) diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 48abbd7c18e14..9417b6ba1929a 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -3,7 +3,7 @@ use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetiti use rustc_ast::token::{self, Token}; use rustc_ast::tokenstream; -use rustc_ast::{NodeId, DUMMY_NODE_ID}; +use rustc_ast::NodeId; use rustc_ast_pretty::pprust; use rustc_feature::Features; use rustc_session::parse::{feature_err, ParseSess}; @@ -102,10 +102,6 @@ pub(super) fn parse( } tree => tree.as_ref().map_or(start_sp, tokenstream::TokenTree::span), }; - if node_id != DUMMY_NODE_ID { - // Macros loaded from other crates have dummy node ids. - sess.missing_fragment_specifiers.borrow_mut().insert(span, node_id); - } result.push(TokenTree::MetaVarDecl(span, ident, None)); } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index eac6a33cf2298..2a01b677e33bf 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -30,7 +30,6 @@ use rustc_resolve::{Resolver, ResolverArenas}; use rustc_serialize::json; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; -use rustc_session::lint; use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; @@ -349,23 +348,8 @@ pub fn configure_and_expand( ecx.check_unused_macros(); }); - let mut missing_fragment_specifiers: Vec<_> = ecx - .sess - .parse_sess - .missing_fragment_specifiers - .borrow() - .iter() - .map(|(span, node_id)| (*span, *node_id)) - .collect(); - missing_fragment_specifiers.sort_unstable_by_key(|(span, _)| *span); - let recursion_limit_hit = ecx.reduced_recursion_limit.is_some(); - for (span, node_id) in missing_fragment_specifiers { - let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; - let msg = "missing fragment specifier"; - resolver.lint_buffer().buffer_lint(lint, node_id, span, msg); - } if cfg!(windows) { env::set_var("PATH", &old_path); } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 0b9c27c2cd6e3..1fa180b320cd8 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -140,7 +140,6 @@ pub struct ParseSess { pub config: CrateConfig, pub check_config: CrateCheckConfig, pub edition: Edition, - pub missing_fragment_specifiers: Lock>, /// Places where raw identifiers were used. This is used to avoid complaining about idents /// clashing with keywords in new editions. pub raw_identifier_spans: Lock>, @@ -195,7 +194,6 @@ impl ParseSess { config: FxHashSet::default(), check_config: CrateCheckConfig::default(), edition: ExpnId::root().expn_data().edition, - missing_fragment_specifiers: Default::default(), raw_identifier_spans: Lock::new(Vec::new()), bad_unicode_identifiers: Lock::new(Default::default()), source_map,