about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-04-09 18:26:28 +0200
committerGitHub <noreply@github.com>2022-04-09 18:26:28 +0200
commit17157c717e8121c18c38fd08f47ac2cecd9aa57c (patch)
treee92a54ae727d10a077f896f2ab3fdbd79545333d
parent50929460419d5235c17e61773b18376f41a88a04 (diff)
parent379ae12a1dfc26ba58607be7f83a3e7f24550a84 (diff)
downloadrust-17157c717e8121c18c38fd08f47ac2cecd9aa57c.tar.gz
rust-17157c717e8121c18c38fd08f47ac2cecd9aa57c.zip
Rollup merge of #95808 - petrochenkov:fragspec, r=nnethercote
expand: Remove `ParseSess::missing_fragment_specifiers`

It was used for deduplicating some errors for legacy code which are mostly deduplicated even without that, but at cost of global mutable state, which is not a good tradeoff.

cc https://github.com/rust-lang/rust/pull/95747#issuecomment-1091619403
r? ``@nnethercote``
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs15
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs18
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs8
-rw-r--r--compiler/rustc_interface/src/passes.rs16
-rw-r--r--compiler/rustc_session/src/parse.rs2
-rw-r--r--src/test/ui/macros/macro-match-nonterminal.rs2
-rw-r--r--src/test/ui/macros/macro-match-nonterminal.stderr13
-rw-r--r--src/test/ui/macros/macro-missing-fragment-deduplication.rs15
-rw-r--r--src/test/ui/macros/macro-missing-fragment-deduplication.stderr18
-rw-r--r--src/test/ui/macros/macro-missing-fragment.rs25
-rw-r--r--src/test/ui/macros/macro-missing-fragment.stderr36
-rw-r--r--src/test/ui/parser/macro/issue-33569.rs2
-rw-r--r--src/test/ui/parser/macro/issue-33569.stderr14
13 files changed, 137 insertions, 47 deletions
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index fbacebf99c0..4298475767e 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,18 @@ 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() && node_id != DUMMY_NODE_ID {
+                // FIXME: Report this as a hard error eventually and remove equivalent errors from
+                // `parse_tt_inner` and `nameize`. Until then the error may be reported twice, once
+                // as a hard error and then once as a buffered lint.
+                sess.buffer_lint(
+                    MISSING_FRAGMENT_SPECIFIER,
+                    span,
+                    node_id,
+                    &format!("missing fragment specifier"),
+                );
+            }
             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 a137e0c92e8..ce243b4a672 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -411,7 +411,6 @@ impl TtParser {
     /// track of through the mps generated.
     fn parse_tt_inner(
         &mut self,
-        sess: &ParseSess,
         matcher: &[MatcherLoc],
         token: &Token,
     ) -> Option<NamedParseResult> {
@@ -519,11 +518,9 @@ impl TtParser {
                             self.bb_mps.push(mp);
                         }
                     } else {
+                        // E.g. `$e` instead of `$e:expr`, reported as a hard error if actually used.
                         // 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()));
-                        }
+                        return Some(Error(span, "missing fragment specifier".to_string()));
                     }
                 }
                 MatcherLoc::Eof => {
@@ -549,7 +546,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())
@@ -587,7 +584,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;
             }
 
@@ -694,7 +691,6 @@ impl TtParser {
 
     fn nameize<I: Iterator<Item = NamedMatch>>(
         &self,
-        sess: &ParseSess,
         matcher: &[MatcherLoc],
         mut res: I,
     ) -> NamedParseResult {
@@ -711,11 +707,9 @@ impl TtParser {
                         }
                     };
                 } else {
+                    // E.g. `$e` instead of `$e:expr`, reported as a hard error if actually used.
                     // 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());
-                    }
+                    return Error(span, "missing fragment specifier".to_string());
                 }
             }
         }
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index a99a18aae11..024299fbd9c 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -2,8 +2,7 @@ use crate::mbe::macro_parser::count_metavar_decls;
 use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
 
 use rustc_ast::token::{self, Token};
-use rustc_ast::tokenstream;
-use rustc_ast::{NodeId, DUMMY_NODE_ID};
+use rustc_ast::{tokenstream, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_feature::Features;
 use rustc_session::parse::{feature_err, ParseSess};
@@ -104,10 +103,7 @@ 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 eac6a33cf22..2a01b677e33 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 0b9c27c2cd6..1fa180b320c 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<FxHashMap<Span, NodeId>>,
     /// 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<Vec<Span>>,
@@ -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,
diff --git a/src/test/ui/macros/macro-match-nonterminal.rs b/src/test/ui/macros/macro-match-nonterminal.rs
index b23e5c71c03..5d9eb55fee0 100644
--- a/src/test/ui/macros/macro-match-nonterminal.rs
+++ b/src/test/ui/macros/macro-match-nonterminal.rs
@@ -2,6 +2,8 @@ macro_rules! test {
     ($a, $b) => {
         //~^ ERROR missing fragment
         //~| ERROR missing fragment
+        //~| ERROR missing fragment
+        //~| WARN this was previously accepted
         //~| WARN this was previously accepted
         ()
     };
diff --git a/src/test/ui/macros/macro-match-nonterminal.stderr b/src/test/ui/macros/macro-match-nonterminal.stderr
index 674ce3434aa..48b9bc6ff6a 100644
--- a/src/test/ui/macros/macro-match-nonterminal.stderr
+++ b/src/test/ui/macros/macro-match-nonterminal.stderr
@@ -5,14 +5,23 @@ LL |     ($a, $b) => {
    |        ^
 
 error: missing fragment specifier
+  --> $DIR/macro-match-nonterminal.rs:2:8
+   |
+LL |     ($a, $b) => {
+   |        ^
+   |
+   = note: `#[deny(missing_fragment_specifier)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+
+error: missing fragment specifier
   --> $DIR/macro-match-nonterminal.rs:2:10
    |
 LL |     ($a, $b) => {
    |          ^^
    |
-   = note: `#[deny(missing_fragment_specifier)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/macros/macro-missing-fragment-deduplication.rs b/src/test/ui/macros/macro-missing-fragment-deduplication.rs
new file mode 100644
index 00000000000..c1e6ba74647
--- /dev/null
+++ b/src/test/ui/macros/macro-missing-fragment-deduplication.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
+macro_rules! m {
+    ($name) => {}
+    //~^ ERROR missing fragment
+    //~| ERROR missing fragment
+    //~| WARN this was previously accepted
+}
+
+fn main() {
+    m!();
+    m!();
+    m!();
+    m!();
+}
diff --git a/src/test/ui/macros/macro-missing-fragment-deduplication.stderr b/src/test/ui/macros/macro-missing-fragment-deduplication.stderr
new file mode 100644
index 00000000000..7622ca054c8
--- /dev/null
+++ b/src/test/ui/macros/macro-missing-fragment-deduplication.stderr
@@ -0,0 +1,18 @@
+error: missing fragment specifier
+  --> $DIR/macro-missing-fragment-deduplication.rs:4:6
+   |
+LL |     ($name) => {}
+   |      ^^^^^
+
+error: missing fragment specifier
+  --> $DIR/macro-missing-fragment-deduplication.rs:4:6
+   |
+LL |     ($name) => {}
+   |      ^^^^^
+   |
+   = note: `#[deny(missing_fragment_specifier)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/macro-missing-fragment.rs b/src/test/ui/macros/macro-missing-fragment.rs
index 1d0b0889b4c..210c85ebbf2 100644
--- a/src/test/ui/macros/macro-missing-fragment.rs
+++ b/src/test/ui/macros/macro-missing-fragment.rs
@@ -1,7 +1,26 @@
-macro_rules! m {
-    ( $( any_token $field_rust_type )* ) => {}; //~ ERROR missing fragment
+#![warn(missing_fragment_specifier)]
+
+macro_rules! used_arm {
+    ( $( any_token $field_rust_type )* ) => {};
+    //~^ ERROR missing fragment
+    //~| WARN missing fragment
+    //~| WARN this was previously accepted
+}
+
+macro_rules! used_macro_unused_arm {
+    () => {};
+    ( $name ) => {};
+    //~^ WARN missing fragment
+    //~| WARN this was previously accepted
+}
+
+macro_rules! unused_macro {
+    ( $name ) => {};
+    //~^ WARN missing fragment
+    //~| WARN this was previously accepted
 }
 
 fn main() {
-    m!();
+    used_arm!();
+    used_macro_unused_arm!();
 }
diff --git a/src/test/ui/macros/macro-missing-fragment.stderr b/src/test/ui/macros/macro-missing-fragment.stderr
index b7871c0ec3a..1bf6f04ec7f 100644
--- a/src/test/ui/macros/macro-missing-fragment.stderr
+++ b/src/test/ui/macros/macro-missing-fragment.stderr
@@ -1,8 +1,40 @@
 error: missing fragment specifier
-  --> $DIR/macro-missing-fragment.rs:2:20
+  --> $DIR/macro-missing-fragment.rs:4:20
    |
 LL |     ( $( any_token $field_rust_type )* ) => {};
    |                    ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+warning: missing fragment specifier
+  --> $DIR/macro-missing-fragment.rs:4:20
+   |
+LL |     ( $( any_token $field_rust_type )* ) => {};
+   |                    ^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/macro-missing-fragment.rs:1:9
+   |
+LL | #![warn(missing_fragment_specifier)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+
+warning: missing fragment specifier
+  --> $DIR/macro-missing-fragment.rs:12:7
+   |
+LL |     ( $name ) => {};
+   |       ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+
+warning: missing fragment specifier
+  --> $DIR/macro-missing-fragment.rs:18:7
+   |
+LL |     ( $name ) => {};
+   |       ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+
+error: aborting due to previous error; 3 warnings emitted
 
diff --git a/src/test/ui/parser/macro/issue-33569.rs b/src/test/ui/parser/macro/issue-33569.rs
index 80e2d7c6545..069d181e962 100644
--- a/src/test/ui/parser/macro/issue-33569.rs
+++ b/src/test/ui/parser/macro/issue-33569.rs
@@ -1,6 +1,8 @@
 macro_rules! foo {
     { $+ } => { //~ ERROR expected identifier, found `+`
                 //~^ ERROR missing fragment specifier
+                //~| ERROR missing fragment specifier
+                //~| WARN this was previously accepted
         $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?`
     }
 }
diff --git a/src/test/ui/parser/macro/issue-33569.stderr b/src/test/ui/parser/macro/issue-33569.stderr
index b4d38d3ce48..39d49fd03f1 100644
--- a/src/test/ui/parser/macro/issue-33569.stderr
+++ b/src/test/ui/parser/macro/issue-33569.stderr
@@ -5,7 +5,7 @@ LL |     { $+ } => {
    |        ^
 
 error: expected one of: `*`, `+`, or `?`
-  --> $DIR/issue-33569.rs:4:13
+  --> $DIR/issue-33569.rs:6:13
    |
 LL |         $(x)(y)
    |             ^^^
@@ -16,5 +16,15 @@ error: missing fragment specifier
 LL |     { $+ } => {
    |        ^
 
-error: aborting due to 3 previous errors
+error: missing fragment specifier
+  --> $DIR/issue-33569.rs:2:8
+   |
+LL |     { $+ } => {
+   |        ^
+   |
+   = note: `#[deny(missing_fragment_specifier)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+
+error: aborting due to 4 previous errors