From 8c402f125ccb3d8ccbabef40694482d481fc28b8 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 20 Jul 2024 07:18:09 -0500 Subject: [PATCH] Make `missing_fragment_specifier` an error in edition 2024 `missing_fragment_specifier` has been a future compatibility warning since 2017. Uplifting it to an unconditional hard error was attempted in 2020, but eventually reverted due to fallout. Make it an error only in edition >= 2024, leaving the lint for older editions. This change will make it easier to support more macro syntax that relies on usage of `$`. Fixes --- compiler/rustc_expand/messages.ftl | 5 ++ compiler/rustc_expand/src/errors.rs | 17 +++++++ compiler/rustc_expand/src/mbe/macro_check.rs | 23 ++++++--- compiler/rustc_expand/src/mbe/quoted.rs | 2 +- ...rr => macro-missing-fragment.e2015.stderr} | 22 ++++----- .../macro-missing-fragment.e2024.stderr | 47 +++++++++++++++++++ tests/ui/macros/macro-missing-fragment.rs | 23 ++++++--- 7 files changed, 114 insertions(+), 25 deletions(-) rename tests/ui/macros/{macro-missing-fragment.stderr => macro-missing-fragment.e2015.stderr} (86%) create mode 100644 tests/ui/macros/macro-missing-fragment.e2024.stderr diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index cc0b110d2bc6f..18d95a398fd4f 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -105,6 +105,11 @@ expand_meta_var_dif_seq_matchers = {$msg} expand_meta_var_expr_unrecognized_var = variable `{$key}` is not recognized in meta-variable expression +expand_missing_fragment_specifier = missing fragment specifier + .note = fragment specifiers must be specified in the 2024 edition + .suggestion_add_fragspec = try adding a specifier here + .valid = {$valid} + expand_module_circular = circular modules: {$modules} diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 0be7403f25b17..6f1a0f16c49ff 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -416,6 +416,23 @@ pub struct DuplicateMatcherBinding { pub prev: Span, } +#[derive(Diagnostic)] +#[diag(expand_missing_fragment_specifier)] +#[note] +#[help(expand_valid)] +pub struct MissingFragmentSpecifier { + #[primary_span] + pub span: Span, + #[suggestion( + expand_suggestion_add_fragspec, + style = "verbose", + code = ":spec", + applicability = "maybe-incorrect" + )] + pub add_span: Span, + pub valid: &'static str, +} + #[derive(Diagnostic)] #[diag(expand_invalid_fragment_specifier)] #[help] diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 4b730d307fd6c..161e27fe02c61 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -115,6 +115,7 @@ use rustc_errors::MultiSpan; use rustc_lint_defs::BuiltinLintDiag; use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER}; use rustc_session::parse::ParseSess; +use rustc_span::edition::Edition; use rustc_span::symbol::kw; use rustc_span::{symbol::MacroRulesNormalizedIdent, ErrorGuaranteed, Span}; @@ -122,6 +123,8 @@ use smallvec::SmallVec; use std::iter; +use super::quoted::VALID_FRAGMENT_NAMES_MSG_2021; + /// Stack represented as linked list. /// /// Those are used for environments because they grow incrementally and are not mutable. @@ -269,12 +272,20 @@ fn check_binders( // 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. - psess.buffer_lint( - MISSING_FRAGMENT_SPECIFIER, - span, - node_id, - BuiltinLintDiag::MissingFragmentSpecifier, - ); + if span.edition() >= Edition::Edition2024 { + psess.dcx().emit_err(errors::MissingFragmentSpecifier { + span, + add_span: span.shrink_to_hi(), + valid: VALID_FRAGMENT_NAMES_MSG_2021, + }); + } else { + psess.buffer_lint( + MISSING_FRAGMENT_SPECIFIER, + span, + node_id, + BuiltinLintDiag::MissingFragmentSpecifier, + ); + } } if !macros.is_empty() { psess.dcx().span_bug(span, "unexpected MetaVarDecl in nested lhs"); diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 9c480f17b4215..57b6947316d65 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -16,7 +16,7 @@ use rustc_span::Span; const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ `literal`, `path`, `meta`, `tt`, `item` and `vis`"; -const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \ +pub const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \ `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, \ `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \ `item` and `vis`"; diff --git a/tests/ui/macros/macro-missing-fragment.stderr b/tests/ui/macros/macro-missing-fragment.e2015.stderr similarity index 86% rename from tests/ui/macros/macro-missing-fragment.stderr rename to tests/ui/macros/macro-missing-fragment.e2015.stderr index abe4d4cd68a2b..a068dc5c054f0 100644 --- a/tests/ui/macros/macro-missing-fragment.stderr +++ b/tests/ui/macros/macro-missing-fragment.e2015.stderr @@ -1,11 +1,11 @@ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:4:20 + --> $DIR/macro-missing-fragment.rs:9:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:4:20 + --> $DIR/macro-missing-fragment.rs:9:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | ( $( any_token $field_rust_type )* ) => {}; = 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 note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:1:9 + --> $DIR/macro-missing-fragment.rs:6:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:12:7 + --> $DIR/macro-missing-fragment.rs:19:7 | LL | ( $name ) => {}; | ^^^^^ @@ -28,7 +28,7 @@ LL | ( $name ) => {}; = note: for more information, see issue #40107 warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:18:7 + --> $DIR/macro-missing-fragment.rs:26:7 | LL | ( $name ) => {}; | ^^^^^ @@ -40,7 +40,7 @@ error: aborting due to 1 previous error; 3 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:4:20 + --> $DIR/macro-missing-fragment.rs:9:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ @@ -48,14 +48,14 @@ LL | ( $( any_token $field_rust_type )* ) => {}; = 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 note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:1:9 + --> $DIR/macro-missing-fragment.rs:6:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:12:7 + --> $DIR/macro-missing-fragment.rs:19:7 | LL | ( $name ) => {}; | ^^^^^ @@ -63,14 +63,14 @@ 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 note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:1:9 + --> $DIR/macro-missing-fragment.rs:6:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:18:7 + --> $DIR/macro-missing-fragment.rs:26:7 | LL | ( $name ) => {}; | ^^^^^ @@ -78,7 +78,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 note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:1:9 + --> $DIR/macro-missing-fragment.rs:6:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/macro-missing-fragment.e2024.stderr b/tests/ui/macros/macro-missing-fragment.e2024.stderr new file mode 100644 index 0000000000000..3afa069c170e4 --- /dev/null +++ b/tests/ui/macros/macro-missing-fragment.e2024.stderr @@ -0,0 +1,47 @@ +error: missing fragment specifier + --> $DIR/macro-missing-fragment.rs:9:20 + | +LL | ( $( any_token $field_rust_type )* ) => {}; + | ^^^^^^^^^^^^^^^^ + | + = note: fragment specifiers must be specified in the 2024 edition + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` +help: try adding a specifier here + | +LL | ( $( any_token $field_rust_type:spec )* ) => {}; + | +++++ + +error: missing fragment specifier + --> $DIR/macro-missing-fragment.rs:19:7 + | +LL | ( $name ) => {}; + | ^^^^^ + | + = note: fragment specifiers must be specified in the 2024 edition + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` +help: try adding a specifier here + | +LL | ( $name:spec ) => {}; + | +++++ + +error: missing fragment specifier + --> $DIR/macro-missing-fragment.rs:26:7 + | +LL | ( $name ) => {}; + | ^^^^^ + | + = note: fragment specifiers must be specified in the 2024 edition + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` +help: try adding a specifier here + | +LL | ( $name:spec ) => {}; + | +++++ + +error: missing fragment specifier + --> $DIR/macro-missing-fragment.rs:9:20 + | +LL | ( $( any_token $field_rust_type )* ) => {}; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/macro-missing-fragment.rs b/tests/ui/macros/macro-missing-fragment.rs index 210c85ebbf2f3..b7da87ae610f2 100644 --- a/tests/ui/macros/macro-missing-fragment.rs +++ b/tests/ui/macros/macro-missing-fragment.rs @@ -1,23 +1,32 @@ +//@ revisions: e2015 e2024 +//@[e2015] edition:2015 +//@[e2024] edition:2024 +//@[e2024] compile-flags: -Zunstable-options + #![warn(missing_fragment_specifier)] macro_rules! used_arm { ( $( any_token $field_rust_type )* ) => {}; - //~^ ERROR missing fragment - //~| WARN missing fragment - //~| WARN this was previously accepted + //[e2015]~^ ERROR missing fragment + //[e2015]~| WARN missing fragment + //[e2015]~| WARN this was previously accepted + //[e2024]~^^^^ ERROR missing fragment + //[e2024]~| ERROR missing fragment } macro_rules! used_macro_unused_arm { () => {}; ( $name ) => {}; - //~^ WARN missing fragment - //~| WARN this was previously accepted + //[e2015]~^ WARN missing fragment + //[e2015]~| WARN this was previously accepted + //[e2024]~^^^ ERROR missing fragment } macro_rules! unused_macro { ( $name ) => {}; - //~^ WARN missing fragment - //~| WARN this was previously accepted + //[e2015]~^ WARN missing fragment + //[e2015]~| WARN this was previously accepted + //[e2024]~^^^ ERROR missing fragment } fn main() {