From 3b979aebfe98099d2c2c6d320e364e9b7a50a8ac Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 17 Apr 2024 20:21:38 +0000 Subject: [PATCH 01/12] Implement IntoDiagArg for hir Namespace --- compiler/rustc_errors/src/diagnostic_impls.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 4bf7dccab9238..662c8a7b8be07 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -282,6 +282,12 @@ impl IntoDiagArg for ClosureKind { } } +impl IntoDiagArg for hir::def::Namespace { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Str(Cow::Borrowed(self.descr())) + } +} + #[derive(Clone)] pub struct DiagSymbolList(Vec); From 56bca95875ac710faebdaf35df4eff17e1e64c73 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 21 Apr 2024 19:56:00 +0000 Subject: [PATCH 02/12] Implement IntoDiagArg for RustcVersion --- compiler/rustc_session/src/version.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/version.rs b/compiler/rustc_session/src/version.rs index 39e4541349ecd..e244c77f7f95b 100644 --- a/compiler/rustc_session/src/version.rs +++ b/compiler/rustc_session/src/version.rs @@ -1,5 +1,10 @@ use rustc_macros::{current_rustc_version, Decodable, Encodable, HashStable_Generic}; -use std::fmt::{self, Display}; +use std::{ + borrow::Cow, + fmt::{self, Display}, +}; + +use rustc_errors::IntoDiagArg; #[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(HashStable_Generic)] @@ -18,3 +23,9 @@ impl Display for RustcVersion { write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch) } } + +impl IntoDiagArg for RustcVersion { + fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + rustc_errors::DiagArgValue::Str(Cow::Owned(self.to_string())) + } +} From eee14e9adf525169f8ea6fdf2579f6abce7ab24c Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 24 Apr 2024 17:28:26 +0000 Subject: [PATCH 03/12] Add note_once/help_once to diagnostic derives --- .../src/diagnostics/diagnostic_builder.rs | 16 ++++++++++++---- compiler/rustc_macros/src/diagnostics/utils.rs | 12 ++++++++++++ compiler/rustc_macros/src/lib.rs | 6 ++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index ae481efb263df..38d4a5ee61ce4 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -158,7 +158,9 @@ impl DiagnosticDeriveVariantBuilder { let slug = subdiag.slug.unwrap_or_else(|| match subdiag.kind { SubdiagnosticKind::Label => parse_quote! { _subdiag::label }, SubdiagnosticKind::Note => parse_quote! { _subdiag::note }, + SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once }, SubdiagnosticKind::Help => parse_quote! { _subdiag::help }, + SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once }, SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn }, SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion }, SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), @@ -233,9 +235,11 @@ impl DiagnosticDeriveVariantBuilder { }; let fn_ident = format_ident!("{}", subdiag); match subdiag { - SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => { - Ok(self.add_subdiagnostic(&fn_ident, slug)) - } + SubdiagnosticKind::Note + | SubdiagnosticKind::NoteOnce + | SubdiagnosticKind::Help + | SubdiagnosticKind::HelpOnce + | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug)), SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => { throw_invalid_attr!(attr, |diag| diag .help("`#[label]` and `#[suggestion]` can only be applied to fields")); @@ -347,7 +351,11 @@ impl DiagnosticDeriveVariantBuilder { report_error_if_not_applied_to_span(attr, &info)?; Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) } - SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => { + SubdiagnosticKind::Note + | SubdiagnosticKind::NoteOnce + | SubdiagnosticKind::Help + | SubdiagnosticKind::HelpOnce + | SubdiagnosticKind::Warn => { let inner = info.ty.inner_type(); if type_matches_path(inner, &["rustc_span", "Span"]) || type_matches_path(inner, &["rustc_span", "MultiSpan"]) diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 4684306e23592..05a5a32514bb7 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -575,8 +575,12 @@ pub(super) enum SubdiagnosticKind { Label, /// `#[note(...)]` Note, + /// `#[note_once(...)]` + NoteOnce, /// `#[help(...)]` Help, + /// `#[help_once(...)]` + HelpOnce, /// `#[warning(...)]` Warn, /// `#[suggestion{,_short,_hidden,_verbose}]` @@ -624,7 +628,9 @@ impl SubdiagnosticVariant { let mut kind = match name { "label" => SubdiagnosticKind::Label, "note" => SubdiagnosticKind::Note, + "note_once" => SubdiagnosticKind::NoteOnce, "help" => SubdiagnosticKind::Help, + "help_once" => SubdiagnosticKind::HelpOnce, "warning" => SubdiagnosticKind::Warn, _ => { // Recover old `#[(multipart_)suggestion_*]` syntaxes @@ -682,7 +688,9 @@ impl SubdiagnosticVariant { match kind { SubdiagnosticKind::Label | SubdiagnosticKind::Note + | SubdiagnosticKind::NoteOnce | SubdiagnosticKind::Help + | SubdiagnosticKind::HelpOnce | SubdiagnosticKind::Warn | SubdiagnosticKind::MultipartSuggestion { .. } => { return Ok(Some(SubdiagnosticVariant { kind, slug: None, no_span: false })); @@ -836,7 +844,9 @@ impl SubdiagnosticVariant { } SubdiagnosticKind::Label | SubdiagnosticKind::Note + | SubdiagnosticKind::NoteOnce | SubdiagnosticKind::Help + | SubdiagnosticKind::HelpOnce | SubdiagnosticKind::Warn => {} } @@ -849,7 +859,9 @@ impl quote::IdentFragment for SubdiagnosticKind { match self { SubdiagnosticKind::Label => write!(f, "label"), SubdiagnosticKind::Note => write!(f, "note"), + SubdiagnosticKind::NoteOnce => write!(f, "note_once"), SubdiagnosticKind::Help => write!(f, "help"), + SubdiagnosticKind::HelpOnce => write!(f, "help_once"), SubdiagnosticKind::Warn => write!(f, "warn"), SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestions_with_style"), SubdiagnosticKind::MultipartSuggestion { .. } => { diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index c7b7eadbd9d6b..de9c916b4f04f 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -108,7 +108,9 @@ decl_derive!( // struct attributes diag, help, + help_once, note, + note_once, warning, // field attributes skip_arg, @@ -125,7 +127,9 @@ decl_derive!( // struct attributes diag, help, + help_once, note, + note_once, warning, // field attributes skip_arg, @@ -142,7 +146,9 @@ decl_derive!( // struct/variant attributes label, help, + help_once, note, + note_once, warning, subdiagnostic, suggestion, From 36902fbcf6d3ae211141b393b93ceef632d0db57 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 24 Apr 2024 17:05:48 +0000 Subject: [PATCH 04/12] Fix subdiagnostic-only enum variants not generating code --- compiler/rustc_macros/src/diagnostics/subdiagnostic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 45236771bce63..69014f39925ab 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -510,11 +510,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); - if kind_slugs.is_empty() { + if kind_slugs.is_empty() && !self.has_subdiagnostic { if self.is_enum { // It's okay for a variant to not be a subdiagnostic at all.. return Ok(quote! {}); - } else if !self.has_subdiagnostic { + } else { // ..but structs should always be _something_. throw_span_err!( self.variant.ast().ident.span().unwrap(), From bac6b6248b63d2cd39b8d010e8b23308a4800508 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Tue, 16 Apr 2024 16:23:47 +0000 Subject: [PATCH 05/12] Convert NAMED_ASM_LABELS lint to diag struct --- compiler/rustc_lint/messages.ftl | 2 ++ compiler/rustc_lint/src/builtin.rs | 21 ++++++------------- .../rustc_lint/src/context/diagnostics.rs | 4 ---- compiler/rustc_lint/src/lints.rs | 6 ++++++ compiler/rustc_lint_defs/src/lib.rs | 1 - 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index cf9d089ff626a..34a40deafad00 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -30,6 +30,8 @@ lint_builtin_anonymous_params = anonymous parameters are deprecated and will be .suggestion = try naming the parameter or explicitly ignoring it lint_builtin_asm_labels = avoid using named labels in inline assembly + .help = only local labels of the form `:` should be used in inline asm + .note = see the asm section of Rust By Example for more information lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty} diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6b9f9d1531ea1..0f059bceae7cb 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -30,10 +30,10 @@ use crate::{ BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, - BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, - BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds, - BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause, - BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, + BuiltinMutablesTransmutes, BuiltinNamedAsmLabel, BuiltinNoMangleGeneric, + BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, + BuiltinTypeAliasGenericBounds, BuiltinTypeAliasGenericBoundsSuggestion, + BuiltinTypeAliasWhereClause, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue, SuggestChangingAssocTypes, @@ -60,7 +60,7 @@ use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::Upcast; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; -use rustc_session::lint::{BuiltinLintDiag, FutureIncompatibilityReason}; +use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; @@ -2882,16 +2882,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { let target_spans: MultiSpan = if spans.len() > 0 { spans.into() } else { (*template_span).into() }; - cx.span_lint_with_diagnostics( - NAMED_ASM_LABELS, - Some(target_spans), - fluent::lint_builtin_asm_labels, - |_| {}, - BuiltinLintDiag::NamedAsmLabel( - "only local labels of the form `:` should be used in inline asm" - .to_string(), - ), - ); + cx.emit_span_lint(NAMED_ASM_LABELS, target_spans, BuiltinNamedAsmLabel); } } } diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 5ad3ff71a6d4a..b8aac6c15d948 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -179,10 +179,6 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di Applicability::MachineApplicable, ); } - BuiltinLintDiag::NamedAsmLabel(help) => { - diag.help(help); - diag.note("see the asm section of Rust By Example for more information"); - } BuiltinLintDiag::UnexpectedCfgName(name, value) => { check_cfg::unexpected_cfg_name(sess, diag, name, value) } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index bc0c8cf85d8a2..42a177157bc10 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1947,3 +1947,9 @@ pub struct UnitBindingsDiag { #[label] pub label: Span, } + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_asm_labels)] +#[help] +#[note] +pub struct BuiltinNamedAsmLabel; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index e06e3e9b805f7..7da65ba0eec9a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -592,7 +592,6 @@ pub enum BuiltinLintDiag { ReservedPrefix(Span), TrailingMacro(bool, Ident), BreakWithLabelAndLoop(Span), - NamedAsmLabel(String), UnicodeTextFlow(Span, String), UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), From 2482f3c17cd1fd4c4988b1f4fbf07270cd93c771 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Tue, 23 Apr 2024 16:18:24 +0000 Subject: [PATCH 06/12] Convert unexpected_cfg_{name,value} to struct diagnostics --- compiler/rustc_lint/messages.ftl | 34 ++ .../src/context/diagnostics/check_cfg.rs | 303 +++++++++--------- compiler/rustc_lint/src/lints.rs | 251 +++++++++++++++ tests/ui/check-cfg/allow-same-level.stderr | 2 +- tests/ui/check-cfg/cargo-feature.none.stderr | 2 +- tests/ui/check-cfg/cargo-feature.some.stderr | 2 +- .../cfg-value-for-cfg-name-duplicate.stderr | 2 +- .../cfg-value-for-cfg-name-multiple.stderr | 2 +- .../check-cfg/cfg-value-for-cfg-name.stderr | 2 +- tests/ui/check-cfg/compact-names.stderr | 2 +- tests/ui/check-cfg/compact-values.stderr | 2 +- tests/ui/check-cfg/concat-values.stderr | 4 +- .../exhaustive-names-values.empty_cfg.stderr | 2 +- .../exhaustive-names-values.feature.stderr | 2 +- .../exhaustive-names-values.full.stderr | 2 +- tests/ui/check-cfg/exhaustive-names.stderr | 2 +- tests/ui/check-cfg/mix.stderr | 4 +- tests/ui/check-cfg/stmt-no-ice.stderr | 2 +- .../ui/check-cfg/unexpected-cfg-value.stderr | 4 +- tests/ui/check-cfg/well-known-names.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 32 +- 21 files changed, 472 insertions(+), 188 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 34a40deafad00..6ad13c0181284 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -593,6 +593,40 @@ lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::Manual .label = argument has type `{$arg_ty}` .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value +lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_println}` to the top of the `build.rs` +lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead +lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg} +lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}` +lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml` +lint_unexpected_cfg_doc_cargo = see for more information about checking conditional configuration +lint_unexpected_cfg_doc_rustc = see for more information about checking conditional configuration + +lint_unexpected_cfg_name_expected_names = expected names are: {$possibilities}{$and_more -> + [0] {""} + *[other] {" "}and {$and_more} more + } +lint_unexpected_cfg_name_expected_values = expected values for `{$best_match}` are: {$possibilities} +lint_unexpected_cfg_name_similar_name = there is a config with a similar name +lint_unexpected_cfg_name_similar_name_different_values = there is a config with a similar name and different values +lint_unexpected_cfg_name_similar_name_no_value = there is a config with a similar name and no value +lint_unexpected_cfg_name_similar_name_value = there is a config with a similar name and value +lint_unexpected_cfg_name_with_similar_value = found config with similar value + +lint_unexpected_cfg_value_add_feature = consider adding `{$value}` as a feature in `Cargo.toml` +lint_unexpected_cfg_value_expected_values = expected values for `{$name}` are: {$have_none_possibility -> + [true] {"(none), "} + *[false] {""} + }{$possibilities}{$and_more -> + [0] {""} + *[other] {" "}and {$and_more} more + } +lint_unexpected_cfg_value_no_expected_value = no expected value for `{$name}` +lint_unexpected_cfg_value_no_expected_values = no expected values for `{$name}` +lint_unexpected_cfg_value_remove_condition = remove the condition +lint_unexpected_cfg_value_remove_value = remove the value +lint_unexpected_cfg_value_similar_name = there is a expected value with a similar name +lint_unexpected_cfg_value_specify_value = specify a config value + lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op .label = this function will not propagate the caller location diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index 3fa04ab75f8d4..38a87d9a11c29 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -1,44 +1,28 @@ -use rustc_errors::{Applicability, Diag}; +use rustc_errors::Diag; use rustc_middle::bug; use rustc_session::{config::ExpectedValues, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{sym, Span, Symbol}; +use crate::lints; + const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35; -fn check_cfg_expected_note( +fn sort_and_truncate_possibilities( sess: &Session, - possibilities: &[Symbol], - type_: &str, - name: Option, - suffix: &str, -) -> String { - use std::fmt::Write; - + mut possibilities: Vec, +) -> (Vec, usize) { let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected { possibilities.len() } else { std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES) }; - let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::>(); - possibilities.sort(); + possibilities.sort_by(|s1, s2| s1.as_str().cmp(s2.as_str())); let and_more = possibilities.len().saturating_sub(n_possibilities); - let possibilities = possibilities[..n_possibilities].join("`, `"); - - let mut note = String::with_capacity(50 + possibilities.len()); - - write!(&mut note, "expected {type_}").unwrap(); - if let Some(name) = name { - write!(&mut note, " for `{name}`").unwrap(); - } - write!(&mut note, " are: {suffix}`{possibilities}`").unwrap(); - if and_more > 0 { - write!(&mut note, " and {and_more} more").unwrap(); - } - - note + possibilities.truncate(n_possibilities); + (possibilities, and_more) } enum EscapeQuotes { @@ -87,106 +71,115 @@ pub(super) fn unexpected_cfg_name( let is_from_cargo = rustc_session::utils::was_invoked_from_cargo(); let mut is_feature_cfg = name == sym::feature; - if is_feature_cfg && is_from_cargo { - diag.help("consider defining some features in `Cargo.toml`"); + let code_sugg = if is_feature_cfg && is_from_cargo { + lints::unexpected_cfg_name::CodeSuggestion::DefineFeatures // Suggest the most probable if we found one } else if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) { + is_feature_cfg |= best_match == sym::feature; + if let Some(ExpectedValues::Some(best_match_values)) = sess.psess.check_config.expecteds.get(&best_match) { // We will soon sort, so the initial order does not matter. #[allow(rustc::potential_query_instability)] - let mut possibilities = - best_match_values.iter().flatten().map(Symbol::as_str).collect::>(); - possibilities.sort(); + let mut possibilities = best_match_values.iter().flatten().collect::>(); + possibilities.sort_by_key(|s| s.as_str()); + + let get_possibilities_sub = || { + if !possibilities.is_empty() { + let possibilities = + possibilities.iter().copied().cloned().collect::>().into(); + Some(lints::unexpected_cfg_name::ExpectedValues { best_match, possibilities }) + } else { + None + } + }; - let mut should_print_possibilities = true; if let Some((value, value_span)) = value { if best_match_values.contains(&Some(value)) { - diag.span_suggestion( - name_span, - "there is a config with a similar name and value", - best_match, - Applicability::MaybeIncorrect, - ); - should_print_possibilities = false; + lints::unexpected_cfg_name::CodeSuggestion::SimilarNameAndValue { + span: name_span, + code: best_match.to_string(), + } } else if best_match_values.contains(&None) { - diag.span_suggestion( - name_span.to(value_span), - "there is a config with a similar name and no value", - best_match, - Applicability::MaybeIncorrect, - ); - should_print_possibilities = false; + lints::unexpected_cfg_name::CodeSuggestion::SimilarNameNoValue { + span: name_span.to(value_span), + code: best_match.to_string(), + } } else if let Some(first_value) = possibilities.first() { - diag.span_suggestion( - name_span.to(value_span), - "there is a config with a similar name and different values", - format!("{best_match} = \"{first_value}\""), - Applicability::MaybeIncorrect, - ); + lints::unexpected_cfg_name::CodeSuggestion::SimilarNameDifferentValues { + span: name_span.to(value_span), + code: format!("{best_match} = \"{first_value}\""), + expected: get_possibilities_sub(), + } } else { - diag.span_suggestion( - name_span.to(value_span), - "there is a config with a similar name and different values", - best_match, - Applicability::MaybeIncorrect, - ); - }; + lints::unexpected_cfg_name::CodeSuggestion::SimilarNameDifferentValues { + span: name_span.to(value_span), + code: best_match.to_string(), + expected: get_possibilities_sub(), + } + } } else { - diag.span_suggestion( - name_span, - "there is a config with a similar name", - best_match, - Applicability::MaybeIncorrect, - ); - } - - if !possibilities.is_empty() && should_print_possibilities { - let possibilities = possibilities.join("`, `"); - diag.help(format!("expected values for `{best_match}` are: `{possibilities}`")); + lints::unexpected_cfg_name::CodeSuggestion::SimilarName { + span: name_span, + code: best_match.to_string(), + expected: get_possibilities_sub(), + } } } else { - diag.span_suggestion( - name_span, - "there is a config with a similar name", - best_match, - Applicability::MaybeIncorrect, - ); + lints::unexpected_cfg_name::CodeSuggestion::SimilarName { + span: name_span, + code: best_match.to_string(), + expected: None, + } } - - is_feature_cfg |= best_match == sym::feature; } else { - if !names_possibilities.is_empty() && names_possibilities.len() <= 3 { + let similar_values = if !names_possibilities.is_empty() && names_possibilities.len() <= 3 { names_possibilities.sort(); - for cfg_name in names_possibilities.iter() { - diag.span_suggestion( - name_span, - "found config with similar value", - format!("{cfg_name} = \"{name}\""), - Applicability::MaybeIncorrect, - ); - } - } - if !possibilities.is_empty() { - diag.help_once(check_cfg_expected_note(sess, &possibilities, "names", None, "")); + names_possibilities + .iter() + .map(|cfg_name| lints::unexpected_cfg_name::FoundWithSimilarValue { + span: name_span, + code: format!("{cfg_name} = \"{name}\""), + }) + .collect() + } else { + vec![] + }; + let expected_names = if !possibilities.is_empty() { + let (possibilities, and_more) = sort_and_truncate_possibilities(sess, possibilities); + Some(lints::unexpected_cfg_name::ExpectedNames { + possibilities: possibilities.into(), + and_more, + }) + } else { + None + }; + lints::unexpected_cfg_name::CodeSuggestion::SimilarValues { + with_similar_values: similar_values, + expected_names, } - } + }; let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes); - if is_from_cargo { - if !is_feature_cfg { - diag.help(format!("consider using a Cargo feature instead")); - diag.help(format!("or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{}'] }}", inst(EscapeQuotes::No))); - diag.help(format!("or consider adding `println!(\"cargo::rustc-check-cfg={}\");` to the top of the `build.rs`", inst(EscapeQuotes::Yes))); - } - diag.note("see for more information about checking conditional configuration"); + let invocation_help = if is_from_cargo { + let sub = if !is_feature_cfg { + Some(lints::UnexpectedCfgCargoHelp::new( + &inst(EscapeQuotes::No), + &inst(EscapeQuotes::Yes), + )) + } else { + None + }; + lints::unexpected_cfg_name::InvocationHelp::Cargo { sub } } else { - let inst = inst(EscapeQuotes::No); - diag.help(format!("to expect this configuration use `--check-cfg={inst}`",)); - diag.note("see for more information about checking conditional configuration"); - } + lints::unexpected_cfg_name::InvocationHelp::Rustc(lints::UnexpectedCfgRustcHelp::new( + &inst(EscapeQuotes::No), + )) + }; + + diag.subdiagnostic(diag.dcx, lints::UnexpectedCfgNameSub { code_sugg, invocation_help }); } pub(super) fn unexpected_cfg_value( @@ -214,53 +207,53 @@ pub(super) fn unexpected_cfg_value( // Show the full list if all possible values for a given name, but don't do it // for names as the possibilities could be very long - if !possibilities.is_empty() { - diag.note(check_cfg_expected_note( - sess, - &possibilities, - "values", - Some(name), - if have_none_possibility { "(none), " } else { "" }, - )); + let code_sugg = if !possibilities.is_empty() { + let expected_values = { + let (possibilities, and_more) = + sort_and_truncate_possibilities(sess, possibilities.clone()); + lints::unexpected_cfg_value::ExpectedValues { + name, + have_none_possibility, + possibilities: possibilities.into(), + and_more, + } + }; - if let Some((value, value_span)) = value { + let suggestion = if let Some((value, value_span)) = value { // Suggest the most probable if we found one if let Some(best_match) = find_best_match_for_name(&possibilities, value, None) { - diag.span_suggestion( - value_span, - "there is a expected value with a similar name", - format!("\"{best_match}\""), - Applicability::MaybeIncorrect, - ); + Some(lints::unexpected_cfg_value::ChangeValueSuggestion::SimilarName { + span: value_span, + best_match, + }) + } else { + None } } else if let &[first_possibility] = &possibilities[..] { - diag.span_suggestion( - name_span.shrink_to_hi(), - "specify a config value", - format!(" = \"{first_possibility}\""), - Applicability::MaybeIncorrect, - ); - } + Some(lints::unexpected_cfg_value::ChangeValueSuggestion::SpecifyValue { + span: name_span.shrink_to_hi(), + first_possibility, + }) + } else { + None + }; + + lints::unexpected_cfg_value::CodeSuggestion::ChangeValue { expected_values, suggestion } } else if have_none_possibility { - diag.note(format!("no expected value for `{name}`")); - if let Some((_value, value_span)) = value { - diag.span_suggestion( - name_span.shrink_to_hi().to(value_span), - "remove the value", - "", - Applicability::MaybeIncorrect, - ); - } + let suggestion = + value.map(|(_value, value_span)| lints::unexpected_cfg_value::RemoveValueSuggestion { + span: name_span.shrink_to_hi().to(value_span), + }); + lints::unexpected_cfg_value::CodeSuggestion::RemoveValue { suggestion, name } } else { - diag.note(format!("no expected values for `{name}`")); - - let sp = if let Some((_value, value_span)) = value { + let span = if let Some((_value, value_span)) = value { name_span.to(value_span) } else { name_span }; - diag.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect); - } + let suggestion = lints::unexpected_cfg_value::RemoveConditionSuggestion { span }; + lints::unexpected_cfg_value::CodeSuggestion::RemoveCondition { suggestion, name } + }; // We don't want to suggest adding values to well known names // since those are defined by rustc it-self. Users can still @@ -269,24 +262,30 @@ pub(super) fn unexpected_cfg_value( let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes); - if is_from_cargo { - if name == sym::feature { + let invocation_help = if is_from_cargo { + let help = if name == sym::feature { if let Some((value, _value_span)) = value { - diag.help(format!("consider adding `{value}` as a feature in `Cargo.toml`")); + Some(lints::unexpected_cfg_value::CargoHelp::AddFeature { value }) } else { - diag.help("consider defining some features in `Cargo.toml`"); + Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures) } } else if !is_cfg_a_well_know_name { - diag.help(format!("consider using a Cargo feature instead")); - diag.help(format!("or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{}'] }}", inst(EscapeQuotes::No))); - diag.help(format!("or consider adding `println!(\"cargo::rustc-check-cfg={}\");` to the top of the `build.rs`", inst(EscapeQuotes::Yes))); - } - diag.note("see for more information about checking conditional configuration"); + Some(lints::unexpected_cfg_value::CargoHelp::Other(lints::UnexpectedCfgCargoHelp::new( + &inst(EscapeQuotes::No), + &inst(EscapeQuotes::Yes), + ))) + } else { + None + }; + lints::unexpected_cfg_value::InvocationHelp::Cargo(help) } else { - if !is_cfg_a_well_know_name { - let inst = inst(EscapeQuotes::No); - diag.help(format!("to expect this configuration use `--check-cfg={inst}`",)); - } - diag.note("see for more information about checking conditional configuration"); - } + let help = if !is_cfg_a_well_know_name { + Some(lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No))) + } else { + None + }; + lints::unexpected_cfg_value::InvocationHelp::Rustc(help) + }; + + diag.subdiagnostic(diag.dcx, lints::UnexpectedCfgValueSub { code_sugg, invocation_help }); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 42a177157bc10..2a07db27616ab 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1953,3 +1953,254 @@ pub struct UnitBindingsDiag { #[help] #[note] pub struct BuiltinNamedAsmLabel; + +#[derive(Subdiagnostic)] +#[help(lint_unexpected_cfg_add_cargo_feature)] +#[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] +#[help(lint_unexpected_cfg_add_build_rs_println)] +pub struct UnexpectedCfgCargoHelp { + pub build_rs_println: String, + pub cargo_toml_lint_cfg: String, +} + +impl UnexpectedCfgCargoHelp { + pub fn new(unescaped: &str, escaped: &str) -> Self { + Self { + cargo_toml_lint_cfg: format!( + "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}", + ), + build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");",), + } + } +} + +#[derive(Subdiagnostic)] +#[help(lint_unexpected_cfg_add_cmdline_arg)] +pub struct UnexpectedCfgRustcHelp { + pub cmdline_arg: String, +} + +impl UnexpectedCfgRustcHelp { + pub fn new(unescaped: &str) -> Self { + Self { cmdline_arg: format!("--check-cfg={unescaped}") } + } +} + +#[derive(Subdiagnostic)] +pub struct UnexpectedCfgNameSub { + #[subdiagnostic] + pub code_sugg: unexpected_cfg_name::CodeSuggestion, + #[subdiagnostic] + pub invocation_help: unexpected_cfg_name::InvocationHelp, +} + +pub mod unexpected_cfg_name { + use rustc_errors::DiagSymbolList; + use rustc_macros::Subdiagnostic; + use rustc_span::{Span, Symbol}; + + #[derive(Subdiagnostic)] + pub enum CodeSuggestion { + #[help(lint_unexpected_cfg_define_features)] + DefineFeatures, + #[suggestion( + lint_unexpected_cfg_name_similar_name_value, + applicability = "maybe-incorrect", + code = "{code}" + )] + SimilarNameAndValue { + #[primary_span] + span: Span, + code: String, + }, + #[suggestion( + lint_unexpected_cfg_name_similar_name_no_value, + applicability = "maybe-incorrect", + code = "{code}" + )] + SimilarNameNoValue { + #[primary_span] + span: Span, + code: String, + }, + #[suggestion( + lint_unexpected_cfg_name_similar_name_different_values, + applicability = "maybe-incorrect", + code = "{code}" + )] + SimilarNameDifferentValues { + #[primary_span] + span: Span, + code: String, + #[subdiagnostic] + expected: Option, + }, + #[suggestion( + lint_unexpected_cfg_name_similar_name, + applicability = "maybe-incorrect", + code = "{code}" + )] + SimilarName { + #[primary_span] + span: Span, + code: String, + #[subdiagnostic] + expected: Option, + }, + SimilarValues { + #[subdiagnostic] + with_similar_values: Vec, + #[subdiagnostic] + expected_names: Option, + }, + } + + #[derive(Subdiagnostic)] + #[help(lint_unexpected_cfg_name_expected_values)] + pub struct ExpectedValues { + pub best_match: Symbol, + pub possibilities: DiagSymbolList, + } + + #[derive(Subdiagnostic)] + #[suggestion( + lint_unexpected_cfg_name_with_similar_value, + applicability = "maybe-incorrect", + code = "{code}" + )] + pub struct FoundWithSimilarValue { + #[primary_span] + pub span: Span, + pub code: String, + } + + #[derive(Subdiagnostic)] + #[help_once(lint_unexpected_cfg_name_expected_names)] + pub struct ExpectedNames { + pub possibilities: DiagSymbolList, + pub and_more: usize, + } + + #[derive(Subdiagnostic)] + pub enum InvocationHelp { + #[note(lint_unexpected_cfg_doc_cargo)] + Cargo { + #[subdiagnostic] + sub: Option, + }, + #[note(lint_unexpected_cfg_doc_rustc)] + Rustc(#[subdiagnostic] super::UnexpectedCfgRustcHelp), + } +} + +#[derive(Subdiagnostic)] +pub struct UnexpectedCfgValueSub { + #[subdiagnostic] + pub code_sugg: unexpected_cfg_value::CodeSuggestion, + #[subdiagnostic] + pub invocation_help: unexpected_cfg_value::InvocationHelp, +} + +pub mod unexpected_cfg_value { + use rustc_errors::DiagSymbolList; + use rustc_macros::Subdiagnostic; + use rustc_span::{Span, Symbol}; + + #[derive(Subdiagnostic)] + pub enum CodeSuggestion { + ChangeValue { + #[subdiagnostic] + expected_values: ExpectedValues, + #[subdiagnostic] + suggestion: Option, + }, + #[note(lint_unexpected_cfg_value_no_expected_value)] + RemoveValue { + #[subdiagnostic] + suggestion: Option, + + name: Symbol, + }, + #[note(lint_unexpected_cfg_value_no_expected_values)] + RemoveCondition { + #[subdiagnostic] + suggestion: RemoveConditionSuggestion, + + name: Symbol, + }, + } + + #[derive(Subdiagnostic)] + pub enum ChangeValueSuggestion { + #[suggestion( + lint_unexpected_cfg_value_similar_name, + code = r#""{best_match}""#, + applicability = "maybe-incorrect" + )] + SimilarName { + #[primary_span] + span: Span, + best_match: Symbol, + }, + #[suggestion( + lint_unexpected_cfg_value_specify_value, + code = r#" = "{first_possibility}""#, + applicability = "maybe-incorrect" + )] + SpecifyValue { + #[primary_span] + span: Span, + first_possibility: Symbol, + }, + } + + #[derive(Subdiagnostic)] + #[suggestion( + lint_unexpected_cfg_value_remove_value, + code = "", + applicability = "maybe-incorrect" + )] + pub struct RemoveValueSuggestion { + #[primary_span] + pub span: Span, + } + + #[derive(Subdiagnostic)] + #[suggestion( + lint_unexpected_cfg_value_remove_condition, + code = "", + applicability = "maybe-incorrect" + )] + pub struct RemoveConditionSuggestion { + #[primary_span] + pub span: Span, + } + + #[derive(Subdiagnostic)] + #[note(lint_unexpected_cfg_value_expected_values)] + pub struct ExpectedValues { + pub name: Symbol, + pub have_none_possibility: bool, + pub possibilities: DiagSymbolList, + pub and_more: usize, + } + + #[derive(Subdiagnostic)] + pub enum InvocationHelp { + #[note(lint_unexpected_cfg_doc_cargo)] + Cargo(#[subdiagnostic] Option), + #[note(lint_unexpected_cfg_doc_rustc)] + Rustc(#[subdiagnostic] Option), + } + + #[derive(Subdiagnostic)] + pub enum CargoHelp { + #[help(lint_unexpected_cfg_value_add_feature)] + AddFeature { + value: Symbol, + }, + #[help(lint_unexpected_cfg_define_features)] + DefineFeatures, + Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp), + } +} diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr index ae4c1605f0162..b311a80c8fd5b 100644 --- a/tests/ui/check-cfg/allow-same-level.stderr +++ b/tests/ui/check-cfg/allow-same-level.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE` LL | #[cfg(FALSE)] | ^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(FALSE)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr index a940eda468980..9d3117ed54d1b 100644 --- a/tests/ui/check-cfg/cargo-feature.none.stderr +++ b/tests/ui/check-cfg/cargo-feature.none.stderr @@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable` LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr index 70d3182eec8c5..14e24cb1429ab 100644 --- a/tests/ui/check-cfg/cargo-feature.some.stderr +++ b/tests/ui/check-cfg/cargo-feature.some.stderr @@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable` LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr index 4975129802b69..08bd43832ea18 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value` LL | #[cfg(value)] | ^^^^^ | - = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(value)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr index 6404556f46c4b..6db1144eada41 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_value` LL | #[cfg(my_value)] | ^^^^^^^^ | - = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(my_value)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr index bda1a601410e6..a5f8176343a4c 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `linux` LL | #[cfg(linux)] | ^^^^^ help: found config with similar value: `target_os = "linux"` | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(linux)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr index 079be8d08c29b..6fecdb52362e8 100644 --- a/tests/ui/check-cfg/compact-names.stderr +++ b/tests/ui/check-cfg/compact-names.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `target_architecture` LL | #[cfg(target(os = "linux", architecture = "arm"))] | ^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(target_architecture, values("arm"))` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr index 4fe921dd24b20..c8d14f8c02aa5 100644 --- a/tests/ui/check-cfg/compact-values.stderr +++ b/tests/ui/check-cfg/compact-values.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value: `X` LL | #[cfg(target(os = "linux", pointer_width = "X"))] | ^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_pointer_width` are: `16`, `32`, `64` + = note: expected values for `target_pointer_width` are: `16`, `32`, and `64` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/concat-values.stderr b/tests/ui/check-cfg/concat-values.stderr index a508c3976617d..ec740952f573e 100644 --- a/tests/ui/check-cfg/concat-values.stderr +++ b/tests/ui/check-cfg/concat-values.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value: (none) LL | #[cfg(my_cfg)] | ^^^^^^ | - = note: expected values for `my_cfg` are: `bar`, `foo` + = note: expected values for `my_cfg` are: `bar` and `foo` = help: to expect this configuration use `--check-cfg=cfg(my_cfg)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `unk` LL | #[cfg(my_cfg = "unk")] | ^^^^^^^^^^^^^^ | - = note: expected values for `my_cfg` are: `bar`, `foo` + = note: expected values for `my_cfg` are: `bar` and `foo` = help: to expect this configuration use `--check-cfg=cfg(my_cfg, values("unk"))` = note: see for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index 755373d7b77af..2497864e87ec4 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index 6344739ae7670..a7d4c6d4df66e 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index 6344739ae7670..a7d4c6d4df66e 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr index 605825cd4e584..7ac3241db5f8e 100644 --- a/tests/ui/check-cfg/exhaustive-names.stderr +++ b/tests/ui/check-cfg/exhaustive-names.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 5459169914530..8c1bf5a11607d 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -44,7 +44,7 @@ warning: unexpected `cfg` condition name: `uu` LL | #[cfg_attr(uu, test)] | ^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(uu)` = note: see for more information about checking conditional configuration @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 188 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, and `bmi2` and 188 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr index ab0deae428d17..e8b61d808fe5b 100644 --- a/tests/ui/check-cfg/stmt-no-ice.stderr +++ b/tests/ui/check-cfg/stmt-no-ice.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `crossbeam_loom` LL | #[cfg(crossbeam_loom)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(crossbeam_loom)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/unexpected-cfg-value.stderr b/tests/ui/check-cfg/unexpected-cfg-value.stderr index efcf65bb707e3..0fa0dde41b6df 100644 --- a/tests/ui/check-cfg/unexpected-cfg-value.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-value.stderr @@ -6,7 +6,7 @@ LL | #[cfg(feature = "sedre")] | | | help: there is a expected value with a similar name: `"serde"` | - = note: expected values for `feature` are: `full`, `serde` + = note: expected values for `feature` are: `full` and `serde` = help: to expect this configuration use `--check-cfg=cfg(feature, values("sedre"))` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default @@ -17,7 +17,7 @@ warning: unexpected `cfg` condition value: `rand` LL | #[cfg(feature = "rand")] | ^^^^^^^^^^^^^^^^ | - = note: expected values for `feature` are: `full`, `serde` + = note: expected values for `feature` are: `full` and `serde` = help: to expect this configuration use `--check-cfg=cfg(feature, values("rand"))` = note: see for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index 2ce6fe80ef20f..41130210df1ec 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -18,7 +18,7 @@ warning: unexpected `cfg` condition name: `features` LL | #[cfg(features = "foo")] | ^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(features, values("foo"))` = note: see for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index db4a5fd49e6a9..c13446bb9f89b 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -71,7 +71,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | panic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `panic` are: `abort`, `unwind` + = note: expected values for `panic` are: `abort` and `unwind` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -91,7 +91,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | relocation_model = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, `static` + = note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, and `static` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -111,7 +111,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread` + = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, and `thread` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -120,7 +120,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, `x32` + = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, and `x32` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -129,7 +129,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_arch = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` + = note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, and `x86_64` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -138,7 +138,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_endian = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_endian` are: `big`, `little` + = note: expected values for `target_endian` are: `big` and `little` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -147,7 +147,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p2`, `psx`, `relibc`, `sgx`, `uclibc` + = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p2`, `psx`, `relibc`, `sgx`, and `uclibc` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -156,7 +156,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_family` are: `unix`, `wasm`, `windows` + = note: expected values for `target_family` are: `unix`, `wasm`, and `windows` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -174,7 +174,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_has_atomic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr` + = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, and `ptr` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -183,7 +183,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr` + = note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, and `ptr` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -192,7 +192,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr` + = note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, and `ptr` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -210,7 +210,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_pointer_width = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_pointer_width` are: `16`, `32`, `64` + = note: expected values for `target_pointer_width` are: `16`, `32`, and `64` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -230,7 +230,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, `wrs` + = note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -285,7 +285,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 29 warnings emitted From c227f35a9cd7ef894abfb623a16ad28abf8b6e3f Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 14 Apr 2024 17:59:54 +0000 Subject: [PATCH 07/12] Generate lint diagnostic message from BuiltinLintDiag Translation of the lint message happens when the actual diagnostic is created, not when the lint is buffered. Generating the message from BuiltinLintDiag ensures that all required data to construct the message is preserved in the LintBuffer, eventually allowing the messages to be moved to fluent. Remove the `msg` field from BufferedEarlyLint, it is either generated from the data in the BuiltinLintDiag or stored inside BuiltinLintDiag::Normal. --- compiler/rustc_ast_passes/messages.ftl | 5 - .../rustc_ast_passes/src/ast_validation.rs | 15 +- compiler/rustc_ast_passes/src/errors.rs | 2 + compiler/rustc_attr/src/builtin.rs | 6 - .../src/deriving/generic/mod.rs | 7 +- compiler/rustc_builtin_macros/src/format.rs | 1 - compiler/rustc_expand/src/base.rs | 1 - compiler/rustc_expand/src/expand.rs | 2 - compiler/rustc_expand/src/mbe/macro_rules.rs | 2 - compiler/rustc_interface/src/util.rs | 1 - compiler/rustc_lint/messages.ftl | 11 ++ compiler/rustc_lint/src/context.rs | 3 +- .../rustc_lint/src/context/diagnostics.rs | 150 ++++++++++++++++-- compiler/rustc_lint/src/early.rs | 10 +- compiler/rustc_lint_defs/src/lib.rs | 49 ++++-- compiler/rustc_middle/src/middle/stability.rs | 4 +- compiler/rustc_parse/src/lexer/mod.rs | 4 +- compiler/rustc_parse/src/parser/expr.rs | 1 - compiler/rustc_resolve/src/check_unused.rs | 23 +-- compiler/rustc_resolve/src/diagnostics.rs | 6 - compiler/rustc_resolve/src/ident.rs | 13 +- compiler/rustc_resolve/src/imports.rs | 9 +- compiler/rustc_resolve/src/late.rs | 7 - .../rustc_resolve/src/late/diagnostics.rs | 4 +- compiler/rustc_resolve/src/macros.rs | 1 - compiler/rustc_session/src/parse.rs | 5 +- 26 files changed, 212 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index a3731e94276b5..31a184fe921e7 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -55,9 +55,6 @@ ast_passes_const_without_body = ast_passes_constraint_on_negative_bound = associated type constraints not allowed on negative bounds -ast_passes_deprecated_where_clause_location = - where clause not allowed here - ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses .label = not supported .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax @@ -80,8 +77,6 @@ ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$de .suggestion = remove the {$remove_descr} .label = `extern` block begins here -ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated - ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel .suggestion = remove the attribute .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 9d07683f8d665..c287f6e4b3d8e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -27,7 +27,6 @@ use std::ops::{Deref, DerefMut}; use thin_vec::thin_vec; use crate::errors; -use crate::fluent_generated as fluent; /// Is `self` allowed semantically as the first parameter in an `FnDecl`? enum SelfSemantic { @@ -770,7 +769,6 @@ impl<'a> AstValidator<'a> { MISSING_ABI, id, span, - fluent::ast_passes_extern_without_abi, BuiltinLintDiag::MissingAbi(span, abi::Abi::FALLBACK), ) } @@ -1428,17 +1426,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) { if let Some(ident) = ident { - let msg = match ctxt { - FnCtxt::Foreign => fluent::ast_passes_pattern_in_foreign, - _ => fluent::ast_passes_pattern_in_bodiless, - }; - let diag = BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident); self.lint_buffer.buffer_lint_with_diagnostic( PATTERNS_IN_FNS_WITHOUT_BODY, id, span, - msg, - diag, + BuiltinLintDiag::PatternsInFnsWithoutBody { + span, + ident, + is_foreign: matches!(ctxt, FnCtxt::Foreign), + }, ) } } else { @@ -1514,7 +1510,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { DEPRECATED_WHERE_CLAUSE_LOCATION, item.id, err.span, - fluent::ast_passes_deprecated_where_clause_location, BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg), ); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 25a125f83935b..a95a7bdaf6da5 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -669,6 +669,7 @@ pub struct ConstAndCVariadic { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_foreign, code = E0130)] +// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) pub struct PatternInForeign { #[primary_span] #[label] @@ -677,6 +678,7 @@ pub struct PatternInForeign { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_bodiless, code = E0642)] +// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) pub struct PatternInBodiless { #[primary_span] #[label] diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index c08bf28773362..1ac2e15c32758 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -532,11 +532,6 @@ pub fn cfg_matches( UNEXPECTED_CFGS, cfg.span, lint_node_id, - if let Some(value) = cfg.value { - format!("unexpected `cfg` condition value: `{value}`") - } else { - format!("unexpected `cfg` condition value: (none)") - }, BuiltinLintDiag::UnexpectedCfgValue( (cfg.name, cfg.name_span), cfg.value.map(|v| (v, cfg.value_span.unwrap())), @@ -548,7 +543,6 @@ pub fn cfg_matches( UNEXPECTED_CFGS, cfg.span, lint_node_id, - format!("unexpected `cfg` condition name: `{}`", cfg.name), BuiltinLintDiag::UnexpectedCfgName( (cfg.name, cfg.name_span), cfg.value.map(|v| (v, cfg.value_span.unwrap())), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 46949f731aaab..18dca4b2615db 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1625,10 +1625,9 @@ impl<'a> TraitDef<'a> { BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE, sp, ast::CRATE_NODE_ID, - format!( - "{ty} slice in a packed struct that derives a built-in trait" - ), - rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive, + rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive { + ty: ty.to_string(), + }, ); } else { // Wrap the expression in `{...}`, causing a copy. diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index a5fc74f1d6669..5cb0407bd59e6 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -556,7 +556,6 @@ fn make_format_args( let arg_name = args.explicit_args()[index].kind.ident().unwrap(); ecx.buffered_early_lint.push(BufferedEarlyLint { span: arg_name.span.into(), - msg: format!("named argument `{}` is not used by name", arg_name.name).into(), node_id: rustc_ast::CRATE_NODE_ID, lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY), diagnostic: BuiltinLintDiag::NamedArgumentUsedPositionally { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 12868a666056d..c7ca515afc464 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1370,7 +1370,6 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { PROC_MACRO_BACK_COMPAT, item.ident.span, ast::CRATE_NODE_ID, - "using an old version of `rental`", BuiltinLintDiag::ProcMacroBackCompat( "older versions of the `rental` crate will stop compiling in future versions of Rust; \ please update to `rental` v0.5.6, or switch to one of the `rental` alternatives".to_string() diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index a049ac251e1e7..02e4f5e0f9e11 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1803,7 +1803,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { UNUSED_DOC_COMMENTS, current_span, self.cx.current_expansion.lint_node_id, - "unused doc comment", BuiltinLintDiag::UnusedDocComment(attr.span), ); } else if rustc_attr::is_builtin_attr(attr) { @@ -1815,7 +1814,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { UNUSED_ATTRIBUTES, attr.span, self.cx.current_expansion.lint_node_id, - format!("unused attribute `{attr_name}`"), BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name: pprust::path_to_string(&call.path), diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8f18055f83817..fee7ba099aade 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -83,7 +83,6 @@ impl<'a> ParserAnyMacro<'a> { SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, parser.token.span, lint_node_id, - "trailing semicolon in macro used in expression position", BuiltinLintDiag::TrailingMacro(is_trailing_mac, macro_ident), ); } @@ -1158,7 +1157,6 @@ fn check_matcher_core<'tt>( RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, ast::CRATE_NODE_ID, - "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro", BuiltinLintDiag::OrPatternsBackCompat(span, suggestion), ); } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index ce2382b950193..de7005a541be2 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -409,7 +409,6 @@ pub(crate) fn check_attr_crate_type( lint::builtin::UNKNOWN_CRATE_TYPES, ast::CRATE_NODE_ID, span, - "invalid `crate_type` value", BuiltinLintDiag::UnknownCrateTypes( span, "did you mean".to_string(), diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 6ad13c0181284..e1b0aec6c96e9 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -180,6 +180,9 @@ lint_deprecated_lint_name = .suggestion = change it to .help = change it to {$replace} +lint_deprecated_where_clause_location = + where clause not allowed here + lint_diag_out_of_impl = diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls @@ -209,6 +212,8 @@ lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message .rationale = {$rationale} +lint_extern_without_abi = extern declarations without an explicit ABI are deprecated + lint_for_loops_over_fallibles = for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement .suggestion = consider using `if let` to clear intent @@ -521,6 +526,12 @@ lint_path_statement_drop = path statement drops value lint_path_statement_no_effect = path statement with no effect +lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies + .label = pattern not allowed in function without body + +lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations + .label = pattern not allowed in foreign function + lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value .label = expression has type `{$orig_ty}` diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 62ba9ef5c113a..563d96d9519fb 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -539,12 +539,11 @@ pub trait LintContext { &self, lint: &'static Lint, span: Option>, - msg: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), diagnostic: BuiltinLintDiag, ) { // We first generate a blank diagnostic. - self.opt_span_lint(lint, span, msg, |db| { + self.opt_span_lint(lint, span, diagnostics::builtin_message(&diagnostic), |db| { // Now, set up surrounding context. diagnostics::builtin(self.sess(), diagnostic, db); // Rewrap `db`, and pass control to the user. diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index b8aac6c15d948..df012b2d10bfd 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -2,7 +2,7 @@ #![allow(rustc::untranslatable_diagnostic)] use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; -use rustc_errors::{elided_lifetime_in_path_suggestion, Diag}; +use rustc_errors::{elided_lifetime_in_path_suggestion, pluralize, Diag, DiagMessage}; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_middle::middle::stability; use rustc_session::lint::BuiltinLintDiag; @@ -50,7 +50,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di ); } } - BuiltinLintDiag::Normal => (), + BuiltinLintDiag::Normal(_) => (), BuiltinLintDiag::AbsPathWithModule(span) => { let (sugg, app) = match sess.source_map().span_to_snippet(span) { Ok(ref s) => { @@ -64,7 +64,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di }; diag.span_suggestion(span, "use `crate`", sugg, app); } - BuiltinLintDiag::ProcMacroDeriveResolutionFallback(span) => { + BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span, .. } => { diag.span_label( span, "names from parent modules are not accessible without an explicit import", @@ -88,16 +88,16 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => { diag.span_suggestion(span, note, sugg, Applicability::MaybeIncorrect); } - BuiltinLintDiag::UnusedImports(message, replaces, in_test_module) => { - if !replaces.is_empty() { + BuiltinLintDiag::UnusedImports { fix_msg, fixes, test_module_span, .. } => { + if !fixes.is_empty() { diag.tool_only_multipart_suggestion( - message, - replaces, + fix_msg, + fixes, Applicability::MachineApplicable, ); } - if let Some(span) = in_test_module { + if let Some(span) = test_module_span { diag.span_help( sess.source_map().guess_head_span(span), "if this is a test module, consider adding a `#[cfg(test)]` to the containing module", @@ -114,7 +114,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di ); } } - BuiltinLintDiag::DeprecatedMacro(suggestion, span) => { + BuiltinLintDiag::DeprecatedMacro { suggestion, span, .. } => { stability::deprecation_suggestion(diag, "macro", suggestion, span) } BuiltinLintDiag::UnusedDocComment(span) => { @@ -122,7 +122,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di diag.help("to document an item produced by a macro, \ the macro must produce the documentation as part of its expansion"); } - BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident) => { + BuiltinLintDiag::PatternsInFnsWithoutBody { span, ident, .. } => { diag.span_suggestion( span, "remove `mut` from the parameter", @@ -148,7 +148,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di Applicability::MachineApplicable, ); } - BuiltinLintDiag::ReservedPrefix(span) => { + BuiltinLintDiag::ReservedPrefix(span, _) => { diag.span_label(span, "unknown prefix"); diag.span_suggestion_verbose( span.shrink_to_hi(), @@ -206,6 +206,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di param_span, use_span: Some((use_span, elide)), deletion_span, + .. } => { debug!(?param_span, ?use_span, ?deletion_span); diag.span_label(param_span, "this lifetime..."); @@ -230,7 +231,9 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di diag.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable); } } - BuiltinLintDiag::SingleUseLifetime { param_span: _, use_span: None, deletion_span } => { + BuiltinLintDiag::SingleUseLifetime { + param_span: _, use_span: None, deletion_span, .. + } => { debug!(?deletion_span); if let Some(deletion_span) = deletion_span { diag.span_suggestion( @@ -277,7 +280,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di ); } } - BuiltinLintDiag::ByteSliceInPackedStructWithDerive => { + BuiltinLintDiag::ByteSliceInPackedStructWithDerive { .. } => { diag.help("consider implementing the trait by hand, or remove the `packed` attribute"); } BuiltinLintDiag::UnusedExternCrate { removal_span } => { @@ -337,7 +340,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di Applicability::MachineApplicable, ); } - BuiltinLintDiag::RedundantImportVisibility { max_vis, span } => { + BuiltinLintDiag::RedundantImportVisibility { max_vis, span, .. } => { diag.span_note(span, format!("the most public imported item is `{max_vis}`")); diag.help( "reduce the glob import's visibility or increase visibility of imported items", @@ -353,3 +356,122 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di } } } + +pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage { + match diagnostic { + BuiltinLintDiag::Normal(msg) => msg.clone(), + BuiltinLintDiag::AbsPathWithModule(_) => { + "absolute paths must start with `self`, `super`, `crate`, or an \ + external crate name in the 2018 edition" + .into() + } + BuiltinLintDiag::ProcMacroDeriveResolutionFallback { ns, ident, .. } => { + format!("cannot find {} `{}` in this scope", ns.descr(), ident).into() + } + BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(_) => { + "macro-expanded `macro_export` macros from the current crate cannot \ + be referred to by absolute paths" + .into() + } + BuiltinLintDiag::ElidedLifetimesInPaths(_, _, _, _) => { + "hidden lifetime parameters in types are deprecated".into() + } + BuiltinLintDiag::UnknownCrateTypes(_, _, _) => "invalid `crate_type` value".into(), + BuiltinLintDiag::UnusedImports { span_snippets, .. } => format!( + "unused import{}{}", + pluralize!(span_snippets.len()), + if !span_snippets.is_empty() { + format!(": {}", span_snippets.join(", ")) + } else { + String::new() + } + ) + .into(), + BuiltinLintDiag::RedundantImport(_, source) => { + format!("the item `{source}` is imported redundantly").into() + } + BuiltinLintDiag::DeprecatedMacro { message, .. } => message.clone().into(), + BuiltinLintDiag::MissingAbi(_, _) => crate::fluent_generated::lint_extern_without_abi, + BuiltinLintDiag::UnusedDocComment(_) => "unused doc comment".into(), + BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, .. } => { + format!("unused attribute `{attr_name}`").into() + } + BuiltinLintDiag::PatternsInFnsWithoutBody { is_foreign, .. } => { + if *is_foreign { + crate::fluent_generated::lint_pattern_in_foreign + } else { + crate::fluent_generated::lint_pattern_in_bodiless + } + } + BuiltinLintDiag::LegacyDeriveHelpers(_) => { + "derive helper attribute is used before it is introduced".into() + } + BuiltinLintDiag::ProcMacroBackCompat(_) => "using an old version of `rental`".into(), + BuiltinLintDiag::OrPatternsBackCompat(_, _) => { + "the meaning of the `pat` fragment specifier is changing in Rust 2021, \ + which may affect this macro" + .into() + } + BuiltinLintDiag::ReservedPrefix(_, prefix) => { + format!("prefix `{prefix}` is unknown").into() + } + BuiltinLintDiag::TrailingMacro(_, _) => { + "trailing semicolon in macro used in expression position".into() + } + BuiltinLintDiag::BreakWithLabelAndLoop(_) => { + "this labeled break expression is easy to confuse with an unlabeled break with a \ + labeled value expression" + .into() + } + BuiltinLintDiag::UnicodeTextFlow(_, _) => { + "unicode codepoint changing visible direction of text present in comment".into() + } + BuiltinLintDiag::UnexpectedCfgName((name, _), _) => { + format!("unexpected `cfg` condition name: `{}`", name).into() + } + BuiltinLintDiag::UnexpectedCfgValue(_, v) => if let Some((value, _)) = v { + format!("unexpected `cfg` condition value: `{value}`") + } else { + format!("unexpected `cfg` condition value: (none)") + } + .into(), + BuiltinLintDiag::DeprecatedWhereclauseLocation(_) => { + crate::fluent_generated::lint_deprecated_where_clause_location + } + BuiltinLintDiag::SingleUseLifetime { use_span, ident, .. } => { + if use_span.is_some() { + format!("lifetime parameter `{}` only used once", ident).into() + } else { + format!("lifetime parameter `{}` never used", ident).into() + } + } + BuiltinLintDiag::NamedArgumentUsedPositionally { named_arg_name, .. } => { + format!("named argument `{}` is not used by name", named_arg_name).into() + } + BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => { + format!("{ty} slice in a packed struct that derives a built-in trait").into() + } + BuiltinLintDiag::UnusedExternCrate { .. } => "unused extern crate".into(), + BuiltinLintDiag::ExternCrateNotIdiomatic { .. } => { + "`extern crate` is not idiomatic in the new edition".into() + } + BuiltinLintDiag::AmbiguousGlobImports { diag } => diag.msg.clone().into(), + BuiltinLintDiag::AmbiguousGlobReexports { .. } => "ambiguous glob re-exports".into(), + BuiltinLintDiag::HiddenGlobReexports { .. } => { + "private item shadows public glob re-export".into() + } + BuiltinLintDiag::UnusedQualifications { .. } => "unnecessary qualification".into(), + BuiltinLintDiag::AssociatedConstElidedLifetime { elided, .. } => if *elided { + "`&` without an explicit lifetime name cannot be used here" + } else { + "`'_` cannot be used here" + } + .into(), + BuiltinLintDiag::RedundantImportVisibility { import_vis, .. } => format!( + "glob import doesn't reexport anything with visibility `{}` \ + because no imported item is public enough", + import_vis + ) + .into(), + } +} diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 3f627baf7704f..80cb70ba277c8 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -44,14 +44,8 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { #[allow(rustc::diagnostic_outside_of_impl)] fn inlined_check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { - let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint; - self.context.span_lint_with_diagnostics( - lint_id.lint, - Some(span), - msg, - |_| {}, - diagnostic, - ); + let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; + self.context.span_lint_with_diagnostics(lint_id.lint, Some(span), |_| {}, diagnostic); } } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7da65ba0eec9a..a0b24d02561d9 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -6,6 +6,7 @@ use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; use rustc_error_messages::{DiagMessage, MultiSpan}; +use rustc_hir::def::Namespace; use rustc_hir::HashStableContext; use rustc_hir::HirId; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; @@ -569,15 +570,28 @@ pub struct AmbiguityErrorDiag { // becomes hacky (and it gets allocated). #[derive(Debug)] pub enum BuiltinLintDiag { - Normal, + Normal(DiagMessage), AbsPathWithModule(Span), - ProcMacroDeriveResolutionFallback(Span), + ProcMacroDeriveResolutionFallback { + span: Span, + ns: Namespace, + ident: Ident, + }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span), UnknownCrateTypes(Span, String, String), - UnusedImports(String, Vec<(Span, String)>, Option), + UnusedImports { + fix_msg: String, + fixes: Vec<(Span, String)>, + test_module_span: Option, + span_snippets: Vec, + }, RedundantImport(Vec<(Span, bool)>, Ident), - DeprecatedMacro(Option, Span), + DeprecatedMacro { + suggestion: Option, + span: Span, + message: String, + }, MissingAbi(Span, Abi), UnusedDocComment(Span), UnusedBuiltinAttribute { @@ -585,11 +599,15 @@ pub enum BuiltinLintDiag { macro_name: String, invoc_span: Span, }, - PatternsInFnsWithoutBody(Span, Ident), + PatternsInFnsWithoutBody { + span: Span, + ident: Ident, + is_foreign: bool, + }, LegacyDeriveHelpers(Span), ProcMacroBackCompat(String), OrPatternsBackCompat(Span, String), - ReservedPrefix(Span), + ReservedPrefix(Span, String), TrailingMacro(bool, Ident), BreakWithLabelAndLoop(Span), UnicodeTextFlow(Span, String), @@ -605,6 +623,7 @@ pub enum BuiltinLintDiag { /// Span of the single use, or None if the lifetime is never used. /// If true, the lifetime will be fully elided. use_span: Option<(Span, bool)>, + ident: Ident, }, NamedArgumentUsedPositionally { /// Span where the named argument is used by position and will be replaced with the named @@ -619,7 +638,10 @@ pub enum BuiltinLintDiag { /// Indicates if the named argument is used as a width/precision for formatting is_formatting_arg: bool, }, - ByteSliceInPackedStructWithDerive, + ByteSliceInPackedStructWithDerive { + // FIXME: enum of byte/string + ty: String, + }, UnusedExternCrate { removal_span: Span, }, @@ -661,6 +683,7 @@ pub enum BuiltinLintDiag { RedundantImportVisibility { span: Span, max_vis: String, + import_vis: String, }, MaybeTypo { span: Span, @@ -675,9 +698,6 @@ pub struct BufferedEarlyLint { /// The span of code that we are linting on. pub span: MultiSpan, - /// The lint message. - pub msg: DiagMessage, - /// The `NodeId` of the AST node that generated the lint. pub node_id: NodeId, @@ -705,12 +725,10 @@ impl LintBuffer { lint: &'static Lint, node_id: NodeId, span: MultiSpan, - msg: impl Into, diagnostic: BuiltinLintDiag, ) { let lint_id = LintId::of(lint); - let msg = msg.into(); - self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, msg, diagnostic }); + self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, diagnostic }); } pub fn take(&mut self, id: NodeId) -> Vec { @@ -725,7 +743,7 @@ impl LintBuffer { sp: impl Into, msg: impl Into, ) { - self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiag::Normal) + self.add_lint(lint, id, sp.into(), BuiltinLintDiag::Normal(msg.into())) } pub fn buffer_lint_with_diagnostic( @@ -733,10 +751,9 @@ impl LintBuffer { lint: &'static Lint, id: NodeId, sp: impl Into, - msg: impl Into, diagnostic: BuiltinLintDiag, ) { - self.add_lint(lint, id, sp.into(), msg, diagnostic) + self.add_lint(lint, id, sp.into(), diagnostic) } } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 67bd53f53daeb..75ed408e64414 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -200,8 +200,8 @@ pub fn early_report_deprecation( return; } - let diag = BuiltinLintDiag::DeprecatedMacro(suggestion, span); - lint_buffer.buffer_lint_with_diagnostic(lint, node_id, span, message, diag); + let diag = BuiltinLintDiag::DeprecatedMacro { suggestion, span, message }; + lint_buffer.buffer_lint_with_diagnostic(lint, node_id, span, diag); } fn late_report_deprecation( diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index d2d200a91aff2..cdb1cf62cf782 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -374,7 +374,6 @@ impl<'psess, 'src> StringReader<'psess, 'src> { TEXT_DIRECTION_CODEPOINT_IN_COMMENT, span, ast::CRATE_NODE_ID, - "unicode codepoint changing visible direction of text present in comment", BuiltinLintDiag::UnicodeTextFlow(span, content.to_string()), ); } @@ -727,8 +726,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, prefix_span, ast::CRATE_NODE_ID, - format!("prefix `{prefix}` is unknown"), - BuiltinLintDiag::ReservedPrefix(prefix_span), + BuiltinLintDiag::ReservedPrefix(prefix_span, prefix.to_string()), ); } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index d2d21624150bf..be4a52a9bc4e6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1917,7 +1917,6 @@ impl<'a> Parser<'a> { BREAK_WITH_LABEL_AND_LOOP, lo.to(expr.span), ast::CRATE_NODE_ID, - "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression", BuiltinLintDiag::BreakWithLabelAndLoop(expr.span), ); } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 180e7f6def3a3..2a8eb940ccf53 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -32,7 +32,7 @@ use rustc_ast as ast; use rustc_ast::visit::{self, Visitor}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{pluralize, MultiSpan}; +use rustc_errors::MultiSpan; use rustc_hir::def::{DefKind, Res}; use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES}; use rustc_session::lint::builtin::{UNUSED_IMPORTS, UNUSED_QUALIFICATIONS}; @@ -155,7 +155,6 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { UNUSED_EXTERN_CRATES, extern_crate.id, span, - "unused extern crate", BuiltinLintDiag::UnusedExternCrate { removal_span: extern_crate.span_with_attributes, }, @@ -208,7 +207,6 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { UNUSED_EXTERN_CRATES, extern_crate.id, extern_crate.span, - "`extern crate` is not idiomatic in the new edition", BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span }, ); } @@ -459,16 +457,6 @@ impl Resolver<'_, '_> { .collect::>(); span_snippets.sort(); - let msg = format!( - "unused import{}{}", - pluralize!(ms.primary_spans().len()), - if !span_snippets.is_empty() { - format!(": {}", span_snippets.join(", ")) - } else { - String::new() - } - ); - let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span { "remove the whole `use` item" } else if ms.primary_spans().len() > 1 { @@ -505,8 +493,12 @@ impl Resolver<'_, '_> { UNUSED_IMPORTS, unused.use_tree_id, ms, - msg, - BuiltinLintDiag::UnusedImports(fix_msg.into(), fixes, test_module_span), + BuiltinLintDiag::UnusedImports { + fix_msg: fix_msg.into(), + fixes, + test_module_span, + span_snippets, + }, ); } @@ -556,7 +548,6 @@ impl Resolver<'_, '_> { UNUSED_QUALIFICATIONS, unn_qua.node_id, unn_qua.path_span, - "unnecessary qualification", BuiltinLintDiag::UnusedQualifications { removal_span: unn_qua.removal_span }, ); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index b28312fa473a7..791d777b3d447 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -128,13 +128,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.report_with_use_injections(krate); for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { - let msg = "macro-expanded `macro_export` macros from the current crate \ - cannot be referred to by absolute paths"; self.lint_buffer.buffer_lint_with_diagnostic( MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, CRATE_NODE_ID, span_use, - msg, BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def), ); } @@ -149,7 +146,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { AMBIGUOUS_GLOB_IMPORTS, import.root_id, ambiguity_error.ident.span, - diag.msg.to_string(), BuiltinLintDiag::AmbiguousGlobImports { diag }, ); } else { @@ -530,8 +526,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, node_id, root_span, - "absolute paths must start with `self`, `super`, \ - `crate`, or an external crate name in the 2018 edition", diag, ); } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index f88725830f1e7..d1fd19e9953e0 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -528,14 +528,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, lint_id, orig_ident.span, - format!( - "cannot find {} `{}` in this scope", - ns.descr(), - ident - ), - BuiltinLintDiag::ProcMacroDeriveResolutionFallback( - orig_ident.span, - ), + BuiltinLintDiag::ProcMacroDeriveResolutionFallback { + span: orig_ident.span, + ns, + ident, + }, ); } let misc_flags = if module == this.graph_root { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index f53bcb0e9d0de..55a0382a8e808 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -623,7 +623,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { AMBIGUOUS_GLOB_REEXPORTS, import.root_id, import.root_span, - "ambiguous glob re-exports", BuiltinLintDiag::AmbiguousGlobReexports { name: key.ident.to_string(), namespace: key.ns.descr().to_string(), @@ -659,7 +658,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { HIDDEN_GLOB_REEXPORTS, binding_id, binding.span, - "private item shadows public glob re-export", BuiltinLintDiag::HiddenGlobReexports { name: key.ident.name.to_string(), namespace: key.ns.descr().to_owned(), @@ -1015,17 +1013,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && !max_vis.is_at_least(import_vis, self.tcx) { let def_id = self.local_def_id(id); - let msg = format!( - "glob import doesn't reexport anything with visibility `{}` because no imported item is public enough", - import_vis.to_string(def_id, self.tcx) - ); self.lint_buffer.buffer_lint_with_diagnostic( UNUSED_IMPORTS, id, import.span, - msg, BuiltinLintDiag::RedundantImportVisibility { max_vis: max_vis.to_string(def_id, self.tcx), + import_vis: import_vis.to_string(def_id, self.tcx), span: import.span, }, ); @@ -1397,7 +1391,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { UNUSED_IMPORTS, id, import.span, - format!("the item `{source}` is imported redundantly"), BuiltinLintDiag::RedundantImport(redundant_spans, source), ); */ diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0f585aafdd5cf..9442741b6cc50 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1675,16 +1675,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { return; } LifetimeRibKind::AnonymousWarn(node_id) => { - let msg = if elided { - "`&` without an explicit lifetime name cannot be used here" - } else { - "`'_` cannot be used here" - }; self.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, node_id, lifetime.ident.span, - msg, lint::BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lifetime.ident.span, @@ -1970,7 +1964,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lint::builtin::ELIDED_LIFETIMES_IN_PATHS, segment_id, elided_lifetime_span, - "hidden lifetime parameters in types are deprecated", lint::BuiltinLintDiag::ElidedLifetimesInPaths( expected_lifetimes, path_span, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 1958fdf1cbc46..ce14c98b0d615 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2655,11 +2655,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { lint::builtin::SINGLE_USE_LIFETIMES, param.id, param.ident.span, - format!("lifetime parameter `{}` only used once", param.ident), lint::BuiltinLintDiag::SingleUseLifetime { param_span: param.ident.span, use_span: Some((use_span, elidable)), deletion_span, + ident: param.ident, }, ); } @@ -2673,11 +2673,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { lint::builtin::UNUSED_LIFETIMES, param.id, param.ident.span, - format!("lifetime parameter `{}` never used", param.ident), lint::BuiltinLintDiag::SingleUseLifetime { param_span: param.ident.span, use_span: None, deletion_span, + ident: param.ident, }, ); } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index f8d245f94e53a..0e0e6ffc136d3 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -786,7 +786,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { LEGACY_DERIVE_HELPERS, node_id, ident.span, - "derive helper attribute is used before it is introduced", BuiltinLintDiag::LegacyDeriveHelpers(binding.span), ); } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index f6053f43fbd19..59281f96126c0 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -311,9 +311,8 @@ impl ParseSess { buffered_lints.push(BufferedEarlyLint { span: span.into(), node_id, - msg: msg.into(), lint_id: LintId::of(lint), - diagnostic: BuiltinLintDiag::Normal, + diagnostic: BuiltinLintDiag::Normal(msg.into()), }); }); } @@ -323,14 +322,12 @@ impl ParseSess { lint: &'static Lint, span: impl Into, node_id: NodeId, - msg: impl Into, diagnostic: BuiltinLintDiag, ) { self.buffered_lints.with_lock(|buffered_lints| { buffered_lints.push(BufferedEarlyLint { span: span.into(), node_id, - msg: msg.into(), lint_id: LintId::of(lint), diagnostic, }); From 41a20b4c5659d93ef01051351f012c04fea1a38a Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 21 Apr 2024 13:24:25 +0000 Subject: [PATCH 08/12] Port DeprecatedMacro to diag structs --- .../rustc_lint/src/context/diagnostics.rs | 25 ++- compiler/rustc_lint_defs/src/lib.rs | 13 +- compiler/rustc_middle/messages.ftl | 14 ++ compiler/rustc_middle/src/middle/stability.rs | 188 ++++++++++-------- compiler/rustc_resolve/src/macros.rs | 8 +- 5 files changed, 152 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index df012b2d10bfd..70aa14a565d16 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -2,7 +2,9 @@ #![allow(rustc::untranslatable_diagnostic)] use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; -use rustc_errors::{elided_lifetime_in_path_suggestion, pluralize, Diag, DiagMessage}; +use rustc_errors::{ + elided_lifetime_in_path_suggestion, pluralize, Diag, DiagMessage, LintDiagnostic, +}; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_middle::middle::stability; use rustc_session::lint::BuiltinLintDiag; @@ -114,8 +116,21 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di ); } } - BuiltinLintDiag::DeprecatedMacro { suggestion, span, .. } => { - stability::deprecation_suggestion(diag, "macro", suggestion, span) + BuiltinLintDiag::DeprecatedMacro { + suggestion, + suggestion_span, + note, + path, + since_kind, + } => { + let sub = suggestion.map(|suggestion| stability::DeprecationSuggestion { + span: suggestion_span, + kind: "macro".to_owned(), + suggestion, + }); + let deprecated = + stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }; + deprecated.decorate_lint(diag); } BuiltinLintDiag::UnusedDocComment(span) => { diag.span_label(span, "rustdoc does not generate documentation for macro invocations"); @@ -390,7 +405,9 @@ pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage { BuiltinLintDiag::RedundantImport(_, source) => { format!("the item `{source}` is imported redundantly").into() } - BuiltinLintDiag::DeprecatedMacro { message, .. } => message.clone().into(), + BuiltinLintDiag::DeprecatedMacro { since_kind, .. } => { + stability::Deprecated::msg_for_since_kind(since_kind) + } BuiltinLintDiag::MissingAbi(_, _) => crate::fluent_generated::lint_extern_without_abi, BuiltinLintDiag::UnusedDocComment(_) => "unused doc comment".into(), BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, .. } => { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index a0b24d02561d9..53238ed96299d 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -566,6 +566,13 @@ pub struct AmbiguityErrorDiag { pub b2_help_msgs: Vec, } +#[derive(Debug, Clone)] +pub enum DeprecatedSinceKind { + InEffect, + InFuture, + InVersion(String), +} + // This could be a closure, but then implementing derive trait // becomes hacky (and it gets allocated). #[derive(Debug)] @@ -589,8 +596,10 @@ pub enum BuiltinLintDiag { RedundantImport(Vec<(Span, bool)>, Ident), DeprecatedMacro { suggestion: Option, - span: Span, - message: String, + suggestion_span: Span, + note: Option, + path: String, + since_kind: DeprecatedSinceKind, }, MissingAbi(Span, Abi), UnusedDocComment(Span), diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 27d555d7e26c7..f4d619329eb9c 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -50,6 +50,20 @@ middle_const_not_used_in_type_alias = middle_cycle = a cycle occurred during layout computation +middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note -> + [true] : {$note} + *[other] {""} + } +middle_deprecated_in_future = use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> + [true] : {$note} + *[other] {""} + } +middle_deprecated_in_version = use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> + [true] : {$note} + *[other] {""} + } +middle_deprecated_suggestion = replace the use of the deprecated {$kind} + middle_drop_check_overflow = overflow while adding drop-check rules for {$ty} .note = overflowed on {$overflow_ty} diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 75ed408e64414..37d2c6a707854 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -9,15 +9,15 @@ use rustc_attr::{ self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability, }; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{Applicability, Diag}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee}; use rustc_feature::GateIssue; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::{self as hir, HirId}; -use rustc_macros::{Decodable, Encodable, HashStable}; +use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; -use rustc_session::lint::{BuiltinLintDiag, Level, Lint, LintBuffer}; +use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer}; use rustc_session::parse::feature_err_issue; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; @@ -125,90 +125,114 @@ pub fn report_unstable( } } -pub fn deprecation_suggestion( - diag: &mut Diag<'_, ()>, - kind: &str, - suggestion: Option, - span: Span, -) { - if let Some(suggestion) = suggestion { - diag.span_suggestion_verbose( - span, - format!("replace the use of the deprecated {kind}"), - suggestion, - Applicability::MachineApplicable, - ); +fn deprecation_lint(is_in_effect: bool) -> &'static Lint { + if is_in_effect { DEPRECATED } else { DEPRECATED_IN_FUTURE } +} + +#[derive(Subdiagnostic)] +#[suggestion( + middle_deprecated_suggestion, + code = "{suggestion}", + style = "verbose", + applicability = "machine-applicable" +)] +pub struct DeprecationSuggestion { + #[primary_span] + pub span: Span, + + pub kind: String, + pub suggestion: Symbol, +} + +pub struct Deprecated { + pub sub: Option, + + // FIXME: make this translatable + pub kind: String, + pub path: String, + pub note: Option, + pub since_kind: DeprecatedSinceKind, +} + +impl Deprecated { + // FIXME: remove + pub fn msg_for_since_kind(since_kind: &DeprecatedSinceKind) -> rustc_errors::DiagMessage { + match since_kind { + DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated, + DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future, + DeprecatedSinceKind::InVersion(_) => { + crate::fluent_generated::middle_deprecated_in_version + } + } } } -fn deprecation_lint(is_in_effect: bool) -> &'static Lint { - if is_in_effect { DEPRECATED } else { DEPRECATED_IN_FUTURE } +impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { + diag.arg("kind", self.kind); + diag.arg("path", self.path); + if let DeprecatedSinceKind::InVersion(version) = self.since_kind { + diag.arg("version", version); + } + if let Some(note) = self.note { + diag.arg("has_note", true); + diag.arg("note", note); + } else { + diag.arg("has_note", false); + } + if let Some(sub) = self.sub { + diag.subdiagnostic(diag.dcx, sub); + } + } + + fn msg(&self) -> rustc_errors::DiagMessage { + Self::msg_for_since_kind(&self.since_kind) + } } -fn deprecation_message( - is_in_effect: bool, - since: DeprecatedSince, - note: Option, - kind: &str, - path: &str, -) -> String { - let message = if is_in_effect { - format!("use of deprecated {kind} `{path}`") +fn deprecated_since_kind(is_in_effect: bool, since: DeprecatedSince) -> DeprecatedSinceKind { + if is_in_effect { + DeprecatedSinceKind::InEffect } else { match since { - DeprecatedSince::RustcVersion(version) => format!( - "use of {kind} `{path}` that will be deprecated in future version {version}" - ), - DeprecatedSince::Future => { - format!("use of {kind} `{path}` that will be deprecated in a future Rust version") + DeprecatedSince::RustcVersion(version) => { + DeprecatedSinceKind::InVersion(version.to_string()) } + DeprecatedSince::Future => DeprecatedSinceKind::InFuture, DeprecatedSince::NonStandard(_) | DeprecatedSince::Unspecified | DeprecatedSince::Err => { unreachable!("this deprecation is always in effect; {since:?}") } } - }; - - match note { - Some(reason) => format!("{message}: {reason}"), - None => message, } } -pub fn deprecation_message_and_lint( - depr: &Deprecation, - kind: &str, - path: &str, -) -> (String, &'static Lint) { - let is_in_effect = depr.is_in_effect(); - ( - deprecation_message(is_in_effect, depr.since, depr.note, kind, path), - deprecation_lint(is_in_effect), - ) -} - -pub fn early_report_deprecation( +pub fn early_report_macro_deprecation( lint_buffer: &mut LintBuffer, - message: String, - suggestion: Option, - lint: &'static Lint, + depr: &Deprecation, span: Span, node_id: NodeId, + path: String, ) { if span.in_derive_expansion() { return; } - let diag = BuiltinLintDiag::DeprecatedMacro { suggestion, span, message }; - lint_buffer.buffer_lint_with_diagnostic(lint, node_id, span, diag); + let is_in_effect = depr.is_in_effect(); + let diag = BuiltinLintDiag::DeprecatedMacro { + suggestion: depr.suggestion, + suggestion_span: span, + note: depr.note, + path, + since_kind: deprecated_since_kind(is_in_effect, depr.since.clone()), + }; + lint_buffer.buffer_lint_with_diagnostic(deprecation_lint(is_in_effect), node_id, span, diag); } fn late_report_deprecation( tcx: TyCtxt<'_>, - message: String, - suggestion: Option, - lint: &'static Lint, + depr: &Deprecation, span: Span, method_span: Option, hir_id: HirId, @@ -217,13 +241,26 @@ fn late_report_deprecation( if span.in_derive_expansion() { return; } + + let def_path = with_no_trimmed_paths!(tcx.def_path_str(def_id)); + let def_kind = tcx.def_descr(def_id); + let is_in_effect = depr.is_in_effect(); + let method_span = method_span.unwrap_or(span); - tcx.node_span_lint(lint, hir_id, method_span, message, |diag| { - if let hir::Node::Expr(_) = tcx.hir_node(hir_id) { - let kind = tcx.def_descr(def_id); - deprecation_suggestion(diag, kind, suggestion, method_span); - } - }); + let suggestion = + if let hir::Node::Expr(_) = tcx.hir_node(hir_id) { depr.suggestion } else { None }; + let diag = Deprecated { + sub: suggestion.map(|suggestion| DeprecationSuggestion { + span: method_span, + kind: def_kind.to_owned(), + suggestion, + }), + kind: def_kind.to_owned(), + path: def_path, + note: depr.note, + since_kind: deprecated_since_kind(is_in_effect, depr.since), + }; + tcx.emit_node_span_lint(deprecation_lint(is_in_effect), hir_id, method_span, diag); } /// Result of `TyCtxt::eval_stability`. @@ -352,28 +389,9 @@ impl<'tcx> TyCtxt<'tcx> { // Calculating message for lint involves calling `self.def_path_str`. // Which by default to calculate visible path will invoke expensive `visible_parent_map` query. // So we skip message calculation altogether, if lint is allowed. - let is_in_effect = depr_attr.is_in_effect(); - let lint = deprecation_lint(is_in_effect); + let lint = deprecation_lint(depr_attr.is_in_effect()); if self.lint_level_at_node(lint, id).0 != Level::Allow { - let def_path = with_no_trimmed_paths!(self.def_path_str(def_id)); - let def_kind = self.def_descr(def_id); - - late_report_deprecation( - self, - deprecation_message( - is_in_effect, - depr_attr.since, - depr_attr.note, - def_kind, - &def_path, - ), - depr_attr.suggestion, - lint, - span, - method_span, - id, - def_id, - ); + late_report_deprecation(self, depr_attr, span, method_span, id, def_id); } } }; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 0e0e6ffc136d3..63461d5744b17 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -852,14 +852,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let Some(depr) = &ext.deprecation { let path = pprust::path_to_string(path); - let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path); - stability::early_report_deprecation( + stability::early_report_macro_deprecation( &mut self.lint_buffer, - message, - depr.suggestion, - lint, + depr, span, node_id, + path, ); } } From b7abf014ec85e362c10bd7dc222a1a71968bc427 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 14 Apr 2024 20:11:14 +0000 Subject: [PATCH 09/12] Convert uses of BuiltinLintDiag::Normal to custom variants This ensures all diagnostic messages are created at diagnostic emission time, making them translatable. --- compiler/rustc_builtin_macros/messages.ftl | 2 - compiler/rustc_builtin_macros/src/asm.rs | 9 +- .../rustc_builtin_macros/src/source_util.rs | 5 +- .../rustc_builtin_macros/src/test_harness.rs | 5 +- compiler/rustc_builtin_macros/src/util.rs | 6 +- compiler/rustc_expand/src/config.rs | 15 +- compiler/rustc_expand/src/mbe/macro_check.rs | 26 ++-- compiler/rustc_interface/src/util.rs | 27 +--- compiler/rustc_lint/messages.ftl | 14 ++ .../rustc_lint/src/context/diagnostics.rs | 137 ++++++++++++++++-- compiler/rustc_lint_defs/src/lib.rs | 56 +++++-- compiler/rustc_metadata/messages.ftl | 2 - compiler/rustc_metadata/src/creader.rs | 25 ++-- compiler/rustc_parse/src/validate_attr.rs | 32 ++-- compiler/rustc_resolve/src/check_unused.rs | 15 +- compiler/rustc_resolve/src/imports.rs | 9 +- compiler/rustc_resolve/src/late.rs | 9 +- compiler/rustc_resolve/src/lib.rs | 10 +- compiler/rustc_resolve/src/macros.rs | 47 +++--- compiler/rustc_session/src/parse.rs | 17 --- 20 files changed, 295 insertions(+), 173 deletions(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 0f15899031938..a3d6a1c736072 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -247,5 +247,3 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal .label = not a trait .str_lit = try using `#[derive({$sym})]` .other = for example, write `#[derive(Debug)]` for `Debug` - -builtin_macros_unnameable_test_items = cannot test inner items diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 49b1b8cf99268..bf2a5813af60b 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -1,6 +1,7 @@ use crate::errors; use crate::util::expr_to_spanned_string; use ast::token::IdentIsRaw; +use lint::BuiltinLintDiag; use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; @@ -509,19 +510,19 @@ fn expand_preparsed_asm( }; if template_str.contains(".intel_syntax") { - ecx.psess().buffer_lint( + ecx.psess().buffer_lint_with_diagnostic( lint::builtin::BAD_ASM_STYLE, find_span(".intel_syntax"), ecx.current_expansion.lint_node_id, - "avoid using `.intel_syntax`, Intel syntax is the default", + BuiltinLintDiag::AvoidUsingIntelSyntax, ); } if template_str.contains(".att_syntax") { - ecx.psess().buffer_lint( + ecx.psess().buffer_lint_with_diagnostic( lint::builtin::BAD_ASM_STYLE, find_span(".att_syntax"), ecx.current_expansion.lint_node_id, - "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead", + BuiltinLintDiag::AvoidUsingAttSyntax, ); } } diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 47b2ee975ca89..15d2546ba8669 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -11,6 +11,7 @@ use rustc_expand::base::{ resolve_path, DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, }; use rustc_expand::module::DirOwnership; +use rustc_lint_defs::BuiltinLintDiag; use rustc_parse::new_parser_from_file; use rustc_parse::parser::{ForceCollect, Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; @@ -143,11 +144,11 @@ pub(crate) fn expand_include<'cx>( fn make_expr(mut self: Box>) -> Option> { let expr = parse_expr(&mut self.p).ok()?; if self.p.token != token::Eof { - self.p.psess.buffer_lint( + self.p.psess.buffer_lint_with_diagnostic( INCOMPLETE_INCLUDE, self.p.token.span, self.node_id, - "include macro expected single expression in source", + BuiltinLintDiag::IncompleteInclude, ); } Some(expr) diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 8cf431482ff73..f6c35a75228a5 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -9,6 +9,7 @@ use rustc_ast::{attr, ModKind}; use rustc_expand::base::{ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_feature::Features; +use rustc_lint_defs::BuiltinLintDiag; use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS; use rustc_session::Session; use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency}; @@ -159,11 +160,11 @@ struct InnerItemLinter<'a> { impl<'a> Visitor<'a> for InnerItemLinter<'_> { fn visit_item(&mut self, i: &'a ast::Item) { if let Some(attr) = attr::find_by_name(&i.attrs, sym::rustc_test_marker) { - self.sess.psess.buffer_lint( + self.sess.psess.buffer_lint_with_diagnostic( UNNAMEABLE_TEST_ITEMS, attr.span, i.id, - crate::fluent_generated::builtin_macros_unnameable_test_items, + BuiltinLintDiag::UnnameableTestItems, ); } } diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 8dc7bc14ec3e6..f08238ad46061 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -5,7 +5,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt}; use rustc_expand::expand::AstFragment; use rustc_feature::AttributeTemplate; -use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES; +use rustc_lint_defs::{builtin::DUPLICATE_MACRO_ATTRIBUTES, BuiltinLintDiag}; use rustc_parse::{parser, validate_attr}; use rustc_session::errors::report_lit_error; use rustc_span::{BytePos, Span, Symbol}; @@ -42,11 +42,11 @@ pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, }; if let Some(attrs) = attrs { if let Some(attr) = attr::find_by_name(attrs, name) { - ecx.psess().buffer_lint( + ecx.psess().buffer_lint_with_diagnostic( DUPLICATE_MACRO_ATTRIBUTES, attr.span, ecx.current_expansion.lint_node_id, - "duplicated attribute", + BuiltinLintDiag::DuplicateMacroAttribute, ); } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 35f0d8abffc57..45d87d5e5a5eb 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -14,6 +14,7 @@ use rustc_attr as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_feature::Features; use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES}; +use rustc_lint_defs::BuiltinLintDiag; use rustc_parse::validate_attr; use rustc_session::parse::feature_err; use rustc_session::Session; @@ -248,7 +249,6 @@ impl<'a> StripUnconfigured<'a> { /// Gives a compiler warning when the `cfg_attr` contains no attributes and /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect. - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub(crate) fn expand_cfg_attr(&self, attr: &Attribute, recursive: bool) -> Vec { let Some((cfg_predicate, expanded_attrs)) = rustc_parse::parse_cfg_attr(attr, &self.sess.psess) @@ -258,11 +258,11 @@ impl<'a> StripUnconfigured<'a> { // Lint on zero attributes in source. if expanded_attrs.is_empty() { - self.sess.psess.buffer_lint( + self.sess.psess.buffer_lint_with_diagnostic( rustc_lint_defs::builtin::UNUSED_ATTRIBUTES, attr.span, ast::CRATE_NODE_ID, - "`#[cfg_attr]` does not expand to any attributes", + BuiltinLintDiag::CfgAttrNoAttributes, ); } @@ -283,7 +283,6 @@ impl<'a> StripUnconfigured<'a> { } } - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn expand_cfg_attr_item( &self, attr: &Attribute, @@ -342,19 +341,19 @@ impl<'a> StripUnconfigured<'a> { item_span, ); if attr.has_name(sym::crate_type) { - self.sess.psess.buffer_lint( + self.sess.psess.buffer_lint_with_diagnostic( rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, attr.span, ast::CRATE_NODE_ID, - "`crate_type` within an `#![cfg_attr] attribute is deprecated`", + BuiltinLintDiag::CrateTypeInCfgAttr, ); } if attr.has_name(sym::crate_name) { - self.sess.psess.buffer_lint( + self.sess.psess.buffer_lint_with_diagnostic( rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, attr.span, ast::CRATE_NODE_ID, - "`crate_name` within an `#![cfg_attr] attribute is deprecated`", + BuiltinLintDiag::CrateNameInCfgAttr, ); } attr diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index dce8e0c36edf7..63eeefa314c30 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -110,7 +110,8 @@ use crate::mbe::{KleeneToken, TokenTree}; use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{DiagMessage, MultiSpan}; +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::symbol::kw; @@ -252,7 +253,7 @@ fn check_binders( // 1. The meta-variable is already bound in the current LHS: This is an error. let mut span = MultiSpan::from_span(span); span.push_span_label(prev_info.span, "previous declaration"); - buffer_lint(psess, span, node_id, "duplicate matcher binding"); + buffer_lint(psess, span, node_id, BuiltinLintDiag::DuplicateMatcherBinding); } else if get_binder_info(macros, binders, name).is_none() { // 2. The meta-variable is free: This is a binder. binders.insert(name, BinderInfo { span, ops: ops.into() }); @@ -267,11 +268,11 @@ 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( + psess.buffer_lint_with_diagnostic( MISSING_FRAGMENT_SPECIFIER, span, node_id, - "missing fragment specifier", + BuiltinLintDiag::MissingFragmentSpecifier, ); } if !macros.is_empty() { @@ -595,7 +596,7 @@ fn check_ops_is_prefix( return; } } - buffer_lint(psess, span.into(), node_id, format!("unknown macro variable `{name}`")); + buffer_lint(psess, span.into(), node_id, BuiltinLintDiag::UnknownMacroVariable(name)); } /// Returns whether `binder_ops` is a prefix of `occurrence_ops`. @@ -628,8 +629,7 @@ fn ops_is_prefix( if i >= occurrence_ops.len() { let mut span = MultiSpan::from_span(span); span.push_span_label(binder.span, "expected repetition"); - let message = format!("variable '{name}' is still repeating at this depth"); - buffer_lint(psess, span, node_id, message); + buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableStillRepeating(name)); return; } let occurrence = &occurrence_ops[i]; @@ -637,21 +637,15 @@ fn ops_is_prefix( let mut span = MultiSpan::from_span(span); span.push_span_label(binder.span, "expected repetition"); span.push_span_label(occurrence.span, "conflicting repetition"); - let message = "meta-variable repeats with different Kleene operator"; - buffer_lint(psess, span, node_id, message); + buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableWrongOperator); return; } } } -fn buffer_lint( - psess: &ParseSess, - span: MultiSpan, - node_id: NodeId, - message: impl Into, -) { +fn buffer_lint(psess: &ParseSess, span: MultiSpan, node_id: NodeId, diag: BuiltinLintDiag) { // Macros loaded from other crates have dummy node ids. if node_id != DUMMY_NODE_ID { - psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message); + psess.buffer_lint_with_diagnostic(META_VARIABLE_MISUSE, span, node_id, diag); } } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index de7005a541be2..cb25bcac36850 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -399,30 +399,17 @@ pub(crate) fn check_attr_crate_type( if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() { let span = spanned.span; - let lev_candidate = find_best_match_for_name( + let candidate = find_best_match_for_name( &CRATE_TYPES.iter().map(|(k, _)| *k).collect::>(), n, None, ); - if let Some(candidate) = lev_candidate { - lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - span, - BuiltinLintDiag::UnknownCrateTypes( - span, - "did you mean".to_string(), - format!("\"{candidate}\""), - ), - ); - } else { - lint_buffer.buffer_lint( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - span, - "invalid `crate_type` value", - ); - } + lint_buffer.buffer_lint_with_diagnostic( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + BuiltinLintDiag::UnknownCrateTypes { span, candidate }, + ); } } else { // This is here mainly to check for using a macro, such as diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index e1b0aec6c96e9..7abba3bb5c4f1 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -156,6 +156,9 @@ lint_builtin_unused_doc_comment = unused doc comment lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}` .suggestion = use `loop` +lint_cfg_attr_no_attributes = + `#[cfg_attr]` does not expand to any attributes + lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}` lint_command_line_source = `forbid` lint level was set on command line @@ -164,6 +167,12 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i .current_use = this identifier can be confused with `{$existing_sym}` .other_use = other identifier used here +lint_crate_name_in_cfg_attr_deprecated = + `crate_name` within an `#![cfg_attr] attribute is deprecated` + +lint_crate_type_in_cfg_attr_deprecated = + `crate_type` within an `#![cfg_attr] attribute is deprecated` + lint_cstring_ptr = getting the inner pointer of a temporary `CString` .as_ptr_label = this pointer will be invalid .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime @@ -662,6 +671,8 @@ lint_unknown_lint = lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}` .help = add `#![register_tool({$tool_name})]` to the crate root +lint_unnameable_test_items = cannot test inner items + lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´ lint_untranslatable_diag = diagnostics should be created using translatable messages @@ -701,3 +712,6 @@ lint_unused_result = unused result of type `{$ty}` lint_variant_size_differences = enum variant is more than three times larger ({$largest} bytes) than the next largest + +lint_wasm_c_abi = + older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88 diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 70aa14a565d16..f298ed98d9806 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -11,8 +11,13 @@ use rustc_session::lint::BuiltinLintDiag; use rustc_session::Session; use rustc_span::BytePos; +use std::fmt::Write; + mod check_cfg; +#[cfg(test)] +mod tests; + pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) { match diagnostic { BuiltinLintDiag::UnicodeTextFlow(span, content) => { @@ -52,7 +57,6 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di ); } } - BuiltinLintDiag::Normal(_) => (), BuiltinLintDiag::AbsPathWithModule(span) => { let (sugg, app) = match sess.source_map().span_to_snippet(span) { Ok(ref s) => { @@ -87,8 +91,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di ), ); } - BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => { - diag.span_suggestion(span, note, sugg, Applicability::MaybeIncorrect); + BuiltinLintDiag::UnknownCrateTypes { span, candidate } => { + if let Some(candidate) = candidate { + diag.span_suggestion( + span, + "did you mean", + format!(r#""{candidate}""#), + Applicability::MaybeIncorrect, + ); + } } BuiltinLintDiag::UnusedImports { fix_msg, fixes, test_module_span, .. } => { if !fixes.is_empty() { @@ -361,20 +372,46 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di "reduce the glob import's visibility or increase visibility of imported items", ); } - BuiltinLintDiag::MaybeTypo { span, name } => { - diag.span_suggestion_verbose( - span, - "an attribute with a similar name exists", - name, - Applicability::MachineApplicable, - ); + BuiltinLintDiag::UnknownDiagnosticAttribute { span, typo_name } => { + if let Some(typo_name) = typo_name { + diag.span_suggestion_verbose( + span, + "an attribute with a similar name exists", + typo_name, + Applicability::MachineApplicable, + ); + } } + BuiltinLintDiag::MacroUseDeprecated + | BuiltinLintDiag::UnusedMacroUse + | BuiltinLintDiag::PrivateExternCrateReexport(_) + | BuiltinLintDiag::UnusedLabel + | BuiltinLintDiag::MacroIsPrivate(_) + | BuiltinLintDiag::UnusedMacroDefinition(_) + | BuiltinLintDiag::MacroRuleNeverUsed(_, _) + | BuiltinLintDiag::UnstableFeature(_) + | BuiltinLintDiag::AvoidUsingIntelSyntax + | BuiltinLintDiag::AvoidUsingAttSyntax + | BuiltinLintDiag::IncompleteInclude + | BuiltinLintDiag::UnnameableTestItems + | BuiltinLintDiag::DuplicateMacroAttribute + | BuiltinLintDiag::CfgAttrNoAttributes + | BuiltinLintDiag::CrateTypeInCfgAttr + | BuiltinLintDiag::CrateNameInCfgAttr + | BuiltinLintDiag::MissingFragmentSpecifier + | BuiltinLintDiag::MetaVariableStillRepeating(_) + | BuiltinLintDiag::MetaVariableWrongOperator + | BuiltinLintDiag::DuplicateMatcherBinding + | BuiltinLintDiag::UnknownMacroVariable(_) + | BuiltinLintDiag::UnusedExternCrate2 { .. } + | BuiltinLintDiag::WasmCAbi + | BuiltinLintDiag::IllFormedAttributeInput { .. } + | BuiltinLintDiag::InnerAttributeUnstable { .. } => {} } } pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage { match diagnostic { - BuiltinLintDiag::Normal(msg) => msg.clone(), BuiltinLintDiag::AbsPathWithModule(_) => { "absolute paths must start with `self`, `super`, `crate`, or an \ external crate name in the 2018 edition" @@ -391,7 +428,7 @@ pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage { BuiltinLintDiag::ElidedLifetimesInPaths(_, _, _, _) => { "hidden lifetime parameters in types are deprecated".into() } - BuiltinLintDiag::UnknownCrateTypes(_, _, _) => "invalid `crate_type` value".into(), + BuiltinLintDiag::UnknownCrateTypes { .. } => "invalid `crate_type` value".into(), BuiltinLintDiag::UnusedImports { span_snippets, .. } => format!( "unused import{}{}", pluralize!(span_snippets.len()), @@ -490,5 +527,81 @@ pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage { import_vis ) .into(), + BuiltinLintDiag::MacroUseDeprecated => "deprecated `#[macro_use]` attribute used to \ + import macros should be replaced at use sites \ + with a `use` item to import the macro \ + instead" + .into(), + BuiltinLintDiag::UnusedMacroUse => "unused `#[macro_use]` import".into(), + BuiltinLintDiag::PrivateExternCrateReexport(ident) => format!( + "extern crate `{ident}` is private, and cannot be \ + re-exported (error E0365), consider declaring with \ + `pub`" + ) + .into(), + BuiltinLintDiag::UnusedLabel => "unused label".into(), + BuiltinLintDiag::MacroIsPrivate(ident) => format!("macro `{ident}` is private").into(), + BuiltinLintDiag::UnusedMacroDefinition(name) => { + format!("unused macro definition: `{}`", name).into() + } + BuiltinLintDiag::MacroRuleNeverUsed(n, name) => { + format!("rule #{} of macro `{}` is never used", n + 1, name).into() + } + BuiltinLintDiag::UnstableFeature(msg) => msg.clone().into(), + BuiltinLintDiag::AvoidUsingIntelSyntax => { + "avoid using `.intel_syntax`, Intel syntax is the default".into() + } + BuiltinLintDiag::AvoidUsingAttSyntax => { + "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead".into() + } + BuiltinLintDiag::IncompleteInclude => { + "include macro expected single expression in source".into() + } + BuiltinLintDiag::UnnameableTestItems => crate::fluent_generated::lint_unnameable_test_items, + BuiltinLintDiag::DuplicateMacroAttribute => "duplicated attribute".into(), + BuiltinLintDiag::CfgAttrNoAttributes => { + crate::fluent_generated::lint_cfg_attr_no_attributes + } + BuiltinLintDiag::CrateTypeInCfgAttr => { + crate::fluent_generated::lint_crate_type_in_cfg_attr_deprecated + } + BuiltinLintDiag::CrateNameInCfgAttr => { + crate::fluent_generated::lint_crate_name_in_cfg_attr_deprecated + } + BuiltinLintDiag::MissingFragmentSpecifier => "missing fragment specifier".into(), + BuiltinLintDiag::MetaVariableStillRepeating(name) => { + format!("variable '{name}' is still repeating at this depth").into() + } + BuiltinLintDiag::MetaVariableWrongOperator => { + "meta-variable repeats with different Kleene operator".into() + } + BuiltinLintDiag::DuplicateMatcherBinding => "duplicate matcher binding".into(), + BuiltinLintDiag::UnknownMacroVariable(name) => { + format!("unknown macro variable `{name}`").into() + } + BuiltinLintDiag::UnusedExternCrate2 { extern_crate, local_crate } => format!( + "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`", + extern_crate, local_crate, extern_crate + ) + .into(), + BuiltinLintDiag::WasmCAbi => crate::fluent_generated::lint_wasm_c_abi, + BuiltinLintDiag::IllFormedAttributeInput { suggestions } => suggestions + .iter() + .enumerate() + .fold("attribute must be of the form ".to_string(), |mut acc, (i, sugg)| { + if i != 0 { + write!(acc, " or ").unwrap(); + } + write!(acc, "`{sugg}`").unwrap(); + acc + }) + .into(), + BuiltinLintDiag::InnerAttributeUnstable { is_macro } => if *is_macro { + "inner macro attributes are unstable" + } else { + "custom inner attributes are unstable" + } + .into(), + BuiltinLintDiag::UnknownDiagnosticAttribute { .. } => "unknown diagnostic attribute".into(), } } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 53238ed96299d..4dacafaaea699 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -5,12 +5,13 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; -use rustc_error_messages::{DiagMessage, MultiSpan}; +use rustc_error_messages::MultiSpan; use rustc_hir::def::Namespace; use rustc_hir::HashStableContext; use rustc_hir::HirId; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::Edition; +use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::{sym, symbol::Ident, Span, Symbol}; use rustc_target::spec::abi::Abi; @@ -577,7 +578,6 @@ pub enum DeprecatedSinceKind { // becomes hacky (and it gets allocated). #[derive(Debug)] pub enum BuiltinLintDiag { - Normal(DiagMessage), AbsPathWithModule(Span), ProcMacroDeriveResolutionFallback { span: Span, @@ -586,7 +586,10 @@ pub enum BuiltinLintDiag { }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span), - UnknownCrateTypes(Span, String, String), + UnknownCrateTypes { + span: Span, + candidate: Option, + }, UnusedImports { fix_msg: String, fixes: Vec<(Span, String)>, @@ -694,9 +697,42 @@ pub enum BuiltinLintDiag { max_vis: String, import_vis: String, }, - MaybeTypo { + UnknownDiagnosticAttribute { span: Span, - name: Symbol, + typo_name: Option, + }, + MacroUseDeprecated, + UnusedMacroUse, + PrivateExternCrateReexport(Ident), + UnusedLabel, + MacroIsPrivate(Ident), + UnusedMacroDefinition(Symbol), + MacroRuleNeverUsed(usize, Symbol), + UnstableFeature(String), + AvoidUsingIntelSyntax, + AvoidUsingAttSyntax, + IncompleteInclude, + UnnameableTestItems, + DuplicateMacroAttribute, + CfgAttrNoAttributes, + CrateTypeInCfgAttr, + CrateNameInCfgAttr, + MissingFragmentSpecifier, + MetaVariableStillRepeating(MacroRulesNormalizedIdent), + MetaVariableWrongOperator, + DuplicateMatcherBinding, + UnknownMacroVariable(MacroRulesNormalizedIdent), + // FIXME: combine with UnusedExternCrate? + UnusedExternCrate2 { + extern_crate: Symbol, + local_crate: Symbol, + }, + WasmCAbi, + IllFormedAttributeInput { + suggestions: Vec, + }, + InnerAttributeUnstable { + is_macro: bool, }, } @@ -745,16 +781,6 @@ impl LintBuffer { self.map.swap_remove(&id).unwrap_or_default() } - pub fn buffer_lint( - &mut self, - lint: &'static Lint, - id: NodeId, - sp: impl Into, - msg: impl Into, - ) { - self.add_lint(lint, id, sp.into(), BuiltinLintDiag::Normal(msg.into())) - } - pub fn buffer_lint_with_diagnostic( &mut self, lint: &'static Lint, diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 3d0846ae6deab..2f5dfad265c80 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -284,8 +284,6 @@ metadata_unsupported_abi = metadata_unsupported_abi_i686 = ABI not supported by `#[link(kind = "raw-dylib")]` on i686 -metadata_wasm_c_abi = - older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88 metadata_wasm_import_form = wasm import module must be of the form `wasm_import_module = "string"` diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index e3205fc1d30e1..394222cdb3573 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -20,7 +20,7 @@ use rustc_middle::bug; use rustc_middle::ty::{TyCtxt, TyCtxtFeed}; use rustc_session::config::{self, CrateType, ExternLocation}; use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource}; -use rustc_session::lint; +use rustc_session::lint::{self, BuiltinLintDiag}; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; use rustc_span::edition::Edition; @@ -974,16 +974,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { continue; } - self.sess.psess.buffer_lint( - lint::builtin::UNUSED_CRATE_DEPENDENCIES, - span, - ast::CRATE_NODE_ID, - format!( - "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`", - name, - self.tcx.crate_name(LOCAL_CRATE), - name), - ); + self.sess.psess.buffer_lint_with_diagnostic( + lint::builtin::UNUSED_CRATE_DEPENDENCIES, + span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::UnusedExternCrate2 { + extern_crate: name_interned, + local_crate: self.tcx.crate_name(LOCAL_CRATE), + }, + ); } } @@ -1016,11 +1015,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); - self.sess.psess.buffer_lint( + self.sess.psess.buffer_lint_with_diagnostic( lint::builtin::WASM_C_ABI, span, ast::CRATE_NODE_ID, - crate::fluent_generated::metadata_wasm_c_abi, + BuiltinLintDiag::WasmCAbi, ); } } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index f88edf29dcebe..3cfc68507d5aa 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -10,6 +10,7 @@ use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::errors::report_lit_error; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; +use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::ParseSess; use rustc_span::{sym, Span, Symbol}; @@ -176,37 +177,26 @@ fn emit_malformed_attribute( }; let error_msg = format!("malformed `{name}` attribute input"); - let mut msg = "attribute must be of the form ".to_owned(); let mut suggestions = vec![]; - let mut first = true; let inner = if style == ast::AttrStyle::Inner { "!" } else { "" }; if template.word { - first = false; - let code = format!("#{inner}[{name}]"); - msg.push_str(&format!("`{code}`")); - suggestions.push(code); + suggestions.push(format!("#{inner}[{name}]")); } if let Some(descr) = template.list { - if !first { - msg.push_str(" or "); - } - first = false; - let code = format!("#{inner}[{name}({descr})]"); - msg.push_str(&format!("`{code}`")); - suggestions.push(code); + suggestions.push(format!("#{inner}[{name}({descr})]")); } if let Some(descr) = template.name_value_str { - if !first { - msg.push_str(" or "); - } - let code = format!("#{inner}[{name} = \"{descr}\"]"); - msg.push_str(&format!("`{code}`")); - suggestions.push(code); + suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); } - suggestions.sort(); if should_warn(name) { - psess.buffer_lint(ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg); + psess.buffer_lint_with_diagnostic( + ILL_FORMED_ATTRIBUTE_INPUT, + span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::IllFormedAttributeInput { suggestions: suggestions.clone() }, + ); } else { + suggestions.sort(); psess .dcx .struct_span_err(span, error_msg) diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 2a8eb940ccf53..55b2d91260e9e 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -388,14 +388,11 @@ impl Resolver<'_, '_> { { if let ImportKind::MacroUse { .. } = import.kind { if !import.span.is_dummy() { - self.lint_buffer.buffer_lint( + self.lint_buffer.buffer_lint_with_diagnostic( MACRO_USE_EXTERN_CRATE, import.root_id, import.span, - "deprecated `#[macro_use]` attribute used to \ - import macros should be replaced at use sites \ - with a `use` item to import the macro \ - instead", + BuiltinLintDiag::MacroUseDeprecated, ); } } @@ -412,8 +409,12 @@ impl Resolver<'_, '_> { } } ImportKind::MacroUse { .. } => { - let msg = "unused `#[macro_use]` import"; - self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg); + self.lint_buffer.buffer_lint_with_diagnostic( + UNUSED_IMPORTS, + import.root_id, + import.span, + BuiltinLintDiag::UnusedMacroUse, + ); } _ => {} } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 55a0382a8e808..fb734895049cc 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1246,16 +1246,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !any_successful_reexport { let (ns, binding) = reexport_error.unwrap(); if pub_use_of_private_extern_crate_hack(import, binding) { - let msg = format!( - "extern crate `{ident}` is private, and cannot be \ - re-exported (error E0365), consider declaring with \ - `pub`" - ); - self.lint_buffer.buffer_lint( + self.lint_buffer.buffer_lint_with_diagnostic( PUB_USE_OF_PRIVATE_EXTERN_CRATE, import_id, import.span, - msg, + BuiltinLintDiag::PrivateExternCrateReexport(ident), ); } else { if ns == TypeNS { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9442741b6cc50..359e96775f8d0 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -24,7 +24,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::ty::DelegationFnSig; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; -use rustc_session::lint; +use rustc_session::lint::{self, BuiltinLintDiag}; use rustc_session::parse::feature_err; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -4815,7 +4815,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { - self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); + self.lint_buffer.buffer_lint_with_diagnostic( + lint::builtin::UNUSED_LABELS, + *id, + *span, + BuiltinLintDiag::UnusedLabel, + ); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 01bcfec4bdc0b..dda31f82d2fdf 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -51,7 +51,7 @@ use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTo use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; -use rustc_session::lint::LintBuffer; +use rustc_session::lint::{BuiltinLintDiag, LintBuffer}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -1860,8 +1860,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let NameBindingKind::Import { import, binding } = used_binding.kind { if let ImportKind::MacroUse { warn_private: true } = import.kind { - let msg = format!("macro `{ident}` is private"); - self.lint_buffer().buffer_lint(PRIVATE_MACRO_USE, import.root_id, ident.span, msg); + self.lint_buffer().buffer_lint_with_diagnostic( + PRIVATE_MACRO_USE, + import.root_id, + ident.span, + BuiltinLintDiag::MacroIsPrivate(ident), + ); } // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 63461d5744b17..74f55d0a19ced 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -311,11 +311,11 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { fn check_unused_macros(&mut self) { for (_, &(node_id, ident)) in self.unused_macros.iter() { - self.lint_buffer.buffer_lint( + self.lint_buffer.buffer_lint_with_diagnostic( UNUSED_MACROS, node_id, ident.span, - format!("unused macro definition: `{}`", ident.name), + BuiltinLintDiag::UnusedMacroDefinition(ident.name), ); } for (&(def_id, arm_i), &(ident, rule_span)) in self.unused_macro_rules.iter() { @@ -324,11 +324,11 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { continue; } let node_id = self.def_id_to_node_id[def_id]; - self.lint_buffer.buffer_lint( + self.lint_buffer.buffer_lint_with_diagnostic( UNUSED_MACRO_RULES, node_id, rule_span, - format!("rule #{} of macro `{}` is never used", arm_i + 1, ident.name), + BuiltinLintDiag::MacroRuleNeverUsed(arm_i, ident.name), ); } } @@ -552,14 +552,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // We are trying to avoid reporting this error if other related errors were reported. if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes { - let msg = match res { - Res::Def(..) => "inner macro attributes are unstable", - Res::NonMacroAttr(..) => "custom inner attributes are unstable", + let is_macro = match res { + Res::Def(..) => true, + Res::NonMacroAttr(..) => false, _ => unreachable!(), }; if soft_custom_inner_attributes_gate { - self.tcx.sess.psess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg); + self.tcx.sess.psess.buffer_lint_with_diagnostic( + SOFT_UNSTABLE, + path.span, + node_id, + BuiltinLintDiag::InnerAttributeUnstable { is_macro }, + ); } else { + // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::InnerAttributeUnstable`) + let msg = if is_macro { + "inner macro attributes are unstable" + } else { + "custom inner attributes are unstable" + }; feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit(); } } @@ -572,17 +583,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let distance = edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); - let help = if distance.is_some() { - BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented } - } else { - BuiltinLintDiag::Normal - }; + let typo_name = distance.map(|_| sym::on_unimplemented); + self.tcx.sess.psess.buffer_lint_with_diagnostic( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, attribute.span(), node_id, - "unknown diagnostic attribute", - help, + BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name }, ); } @@ -835,8 +842,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature)); if !is_allowed(feature) && !allowed_by_implication { let lint_buffer = &mut self.lint_buffer; - let soft_handler = - |lint, span, msg: String| lint_buffer.buffer_lint(lint, node_id, span, msg); + let soft_handler = |lint, span, msg: String| { + lint_buffer.buffer_lint_with_diagnostic( + lint, + node_id, + span, + BuiltinLintDiag::UnstableFeature(msg), + ) + }; stability::report_unstable( self.tcx.sess, feature, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 59281f96126c0..3db586622e594 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -300,23 +300,6 @@ impl ParseSess { self.source_map.clone() } - pub fn buffer_lint( - &self, - lint: &'static Lint, - span: impl Into, - node_id: NodeId, - msg: impl Into, - ) { - self.buffered_lints.with_lock(|buffered_lints| { - buffered_lints.push(BufferedEarlyLint { - span: span.into(), - node_id, - lint_id: LintId::of(lint), - diagnostic: BuiltinLintDiag::Normal(msg.into()), - }); - }); - } - pub fn buffer_lint_with_diagnostic( &self, lint: &'static Lint, From 8004e6a3796f832eb7752dcd22252b8e6d04e240 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Mon, 15 Apr 2024 18:07:22 +0000 Subject: [PATCH 10/12] Make early lints translatable --- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_expand/src/base.rs | 18 +- compiler/rustc_lint/messages.ftl | 178 +++- compiler/rustc_lint/src/context.rs | 21 +- .../rustc_lint/src/context/diagnostics.rs | 767 ++++++++---------- .../src/context/diagnostics/check_cfg.rs | 16 +- compiler/rustc_lint/src/early.rs | 4 +- compiler/rustc_lint/src/lints.rs | 601 +++++++++++++- compiler/rustc_lint_defs/src/lib.rs | 19 +- compiler/rustc_metadata/src/creader.rs | 2 +- compiler/rustc_middle/src/middle/stability.rs | 21 +- compiler/rustc_resolve/src/check_unused.rs | 34 +- compiler/rustc_resolve/src/macros.rs | 5 +- ...sue-43106-gating-of-builtin-attrs-error.rs | 2 +- ...43106-gating-of-builtin-attrs-error.stderr | 2 +- tests/ui/lint/anonymous-reexport.stderr | 2 +- .../ui/lint/unused/import_remove_line.stderr | 2 +- tests/ui/lint/unused/lint-unused-imports.rs | 2 +- .../ui/lint/unused/lint-unused-imports.stderr | 2 +- tests/ui/malformed/malformed-regressions.rs | 6 +- .../ui/malformed/malformed-regressions.stderr | 6 +- ...sue-46209-private-enum-variant-reexport.rs | 2 +- ...46209-private-enum-variant-reexport.stderr | 2 +- tests/ui/span/multispan-import-lint.stderr | 2 +- tests/ui/suggestions/unused-imports.stderr | 4 +- .../use/use-nested-groups-unused-imports.rs | 2 +- .../use-nested-groups-unused-imports.stderr | 2 +- 27 files changed, 1176 insertions(+), 550 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index c287f6e4b3d8e..b1158dc6fcafe 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1510,7 +1510,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { DEPRECATED_WHERE_CLAUSE_LOCATION, item.id, err.span, - BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg), + BuiltinLintDiag::DeprecatedWhereclauseLocation(err.span, sugg), ); } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c7ca515afc464..77db801c76f38 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1364,17 +1364,15 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { }; if crate_matches { - // FIXME: make this translatable - #[allow(rustc::untranslatable_diagnostic)] sess.psess.buffer_lint_with_diagnostic( - PROC_MACRO_BACK_COMPAT, - item.ident.span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::ProcMacroBackCompat( - "older versions of the `rental` crate will stop compiling in future versions of Rust; \ - please update to `rental` v0.5.6, or switch to one of the `rental` alternatives".to_string() - ) - ); + PROC_MACRO_BACK_COMPAT, + item.ident.span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::ProcMacroBackCompat { + crate_name: "rental".to_string(), + fixed_version: "0.5.6".to_string(), + }, + ); return true; } } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7abba3bb5c4f1..0cd6f1caebff8 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -1,7 +1,20 @@ +lint_abs_path_with_module = absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + .suggestion = use `crate` + +lint_ambiguous_glob_reexport = ambiguous glob re-exports + .label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here + .label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here + lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses +lint_associated_const_elided_lifetime = {$elided -> + [true] `&` without an explicit lifetime name cannot be used here + *[false] `'_` cannot be used here + } + .suggestion = use the `'static` lifetime + lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future` .suggestion = you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change @@ -19,10 +32,19 @@ lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` order lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed` +lint_avoid_att_syntax = + avoid using `.att_syntax`, prefer using `options(att_syntax)` instead + +lint_avoid_intel_syntax = + avoid using `.intel_syntax`, Intel syntax is the default + lint_bad_attribute_argument = bad attribute argument lint_bad_opt_access = {$msg} +lint_break_with_label_and_loop = this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression + .suggestion = wrap this expression in parentheses + lint_builtin_allow_internal_unsafe = `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site @@ -156,6 +178,9 @@ lint_builtin_unused_doc_comment = unused doc comment lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}` .suggestion = use `loop` +lint_byte_slice_in_packed_struct_with_derive = {$ty} slice in a packed struct that derives a built-in trait + .help = consider implementing the trait by hand, or remove the `packed` attribute + lint_cfg_attr_no_attributes = `#[cfg_attr]` does not expand to any attributes @@ -179,6 +204,8 @@ lint_cstring_ptr = getting the inner pointer of a temporary `CString` .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned .help = for more information, see https://doc.rust-lang.org/reference/destructors.html +lint_custom_inner_attribute_unstable = custom inner attributes are unstable + lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary @@ -189,8 +216,10 @@ lint_deprecated_lint_name = .suggestion = change it to .help = change it to {$replace} -lint_deprecated_where_clause_location = - where clause not allowed here +lint_deprecated_where_clause_location = where clause not allowed here + .note = see issue #89122 for more information + .suggestion_move_to_end = move it to the end of the type declaration + .suggestion_remove_where = remove this `where` lint_diag_out_of_impl = diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls @@ -209,6 +238,11 @@ lint_dropping_references = calls to `std::mem::drop` with a reference instead of .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result +lint_duplicate_macro_attribute = + duplicated attribute + +lint_duplicate_matcher_binding = duplicate matcher binding + lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum. @@ -221,7 +255,12 @@ lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message .rationale = {$rationale} +lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition + .suggestion = convert it to a `use` + lint_extern_without_abi = extern declarations without an explicit ABI are deprecated + .label = ABI should be specified here + .help = the default ABI is {$default_abi} lint_for_loops_over_fallibles = for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement @@ -237,6 +276,12 @@ lint_forgetting_references = calls to `std::mem::forget` with a reference instea .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result +lint_hidden_glob_reexport = private item shadows public glob re-export + .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here + .note_private_item = but the private item here shadows it + +lint_hidden_lifetime_parameters = hidden lifetime parameters in types are deprecated + lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label} .label = this {$label} contains {$count -> [one] an invisible @@ -278,6 +323,11 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level +lint_ill_formed_attribute_input = {$num_suggestions -> + [1] attribute must be of the form {$suggestions} + *[other] valid forms for the attribute are {$suggestions} + } + lint_impl_trait_overcaptures = `{$self_ty}` will capture more lifetimes than possibly intended in edition 2024 .note = specifically, {$num_captured -> [one] this lifetime is @@ -348,6 +398,14 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re lint_improper_ctypes_union_layout_reason = this union has unspecified layout lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive +lint_incomplete_include = + include macro expected single expression in source + +lint_inner_macro_attribute_unstable = inner macro attributes are unstable + +lint_invalid_crate_type_value = invalid `crate_type` value + .suggestion = did you mean + # FIXME: we should ordinalize $valid_up_to when we add support for doing so lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes @@ -376,9 +434,22 @@ lint_invalid_reference_casting_note_book = for more information, visit `, which means the only information carried by the iterator is the number of items .suggestion = you might have meant to use `Iterator::for_each` +lint_metavariable_still_repeating = variable '{$name}' is still repeating at this depth + +lint_metavariable_wrong_operator = meta-variable repeats with different Kleene operator + +lint_missing_fragment_specifier = missing fragment specifier + lint_mixed_script_confusables = the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables .includes_note = the usage includes {$includes} @@ -395,6 +472,11 @@ lint_mixed_script_confusables = lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits +lint_named_argument_used_positionally = named argument `{$named_arg_name}` is not used by name + .label_named_arg = this named argument is referred to by position in formatting string + .label_position_arg = this formatting argument uses named argument `{$named_arg_name}` by position + .suggestion = use the named argument by name to avoid ambiguity + lint_node_source = `forbid` level set here .note = {$reason} @@ -506,6 +588,9 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass lint_opaque_hidden_inferred_bound_sugg = add this bound +lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + .suggestion = use pat_param to preserve semantics + lint_overflowing_bin_hex = literal out of range for `{$ty}` .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}` @@ -541,6 +626,15 @@ lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations .label = pattern not allowed in foreign function +lint_private_extern_crate_reexport = + extern crate `{$ident}` is private, and cannot be re-exported (error E0365), consider declaring with `pub` + +lint_proc_macro_back_compat = using an old version of `{$crate_name}` + .note = older versions of the `{$crate_name}` crate will stop compiling in future versions of Rust; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives + +lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope + .label = names from parent modules are not accessible without an explicit import + lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value .label = expression has type `{$orig_ty}` @@ -562,6 +656,16 @@ lint_reason_must_be_string_literal = reason must be a string literal lint_reason_must_come_last = reason in lint attribute must come last +lint_redundant_import = the item `{$ident}` is imported redundantly + .label_imported_here = the item `{ident}` is already imported here + .label_defined_here = the item `{ident}` is already defined here + .label_imported_prelude = the item `{ident}` is already imported by the extern prelude + .label_defined_prelude = the item `{ident}` is already defined by the extern prelude + +lint_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough + .note = the most public imported item is `{$max_vis}` + .help = reduce the glob import's visibility or increase visibility of imported items + lint_redundant_semicolons = unnecessary trailing {$multiple -> [true] semicolons @@ -572,6 +676,8 @@ lint_redundant_semicolons = *[false] this semicolon } +lint_remove_mut_from_pattern = remove `mut` from the parameter + lint_removed_lint = lint `{$name}` has been removed: {$reason} lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` @@ -580,6 +686,10 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` +lint_reserved_prefix = prefix `{$prefix}` is unknown + .label = unknown prefix + .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + lint_shadowed_into_iter = this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition} .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity @@ -587,6 +697,11 @@ lint_shadowed_into_iter = .use_explicit_into_iter_suggestion = or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value +lint_single_use_lifetime = lifetime parameter `{$ident}` only used once + .label_param = this lifetime... + .label_use = ...is used only here + .suggestion = elide the single-use lifetime + lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion @@ -600,6 +715,10 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type +lint_trailing_semi_macro = trailing semicolon in macro used in expression position + .note1 = macro invocations at the end of a block are treated as expressions + .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}` + lint_ty_qualified = usage of qualified `ty::{$ty}` .suggestion = try importing it and using it unqualified @@ -621,6 +740,7 @@ lint_unexpected_cfg_define_features = consider defining some features in `Cargo. lint_unexpected_cfg_doc_cargo = see for more information about checking conditional configuration lint_unexpected_cfg_doc_rustc = see for more information about checking conditional configuration +lint_unexpected_cfg_name = unexpected `cfg` condition name: `{$name}` lint_unexpected_cfg_name_expected_names = expected names are: {$possibilities}{$and_more -> [0] {""} *[other] {" "}and {$and_more} more @@ -632,6 +752,10 @@ lint_unexpected_cfg_name_similar_name_no_value = there is a config with a simila lint_unexpected_cfg_name_similar_name_value = there is a config with a similar name and value lint_unexpected_cfg_name_with_similar_value = found config with similar value +lint_unexpected_cfg_value = unexpected `cfg` condition value: {$has_value -> + [true] `{$value}` + *[false] (none) + } lint_unexpected_cfg_value_add_feature = consider adding `{$value}` as a feature in `Cargo.toml` lint_unexpected_cfg_value_expected_values = expected values for `{$name}` are: {$have_none_possibility -> [true] {"(none), "} @@ -650,9 +774,22 @@ lint_unexpected_cfg_value_specify_value = specify a config value lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op .label = this function will not propagate the caller location +lint_unicode_text_flow = unicode codepoint changing visible direction of text present in comment + .label = {$num_codepoints -> + [1] this comment contains an invisible unicode text flow control codepoint + *[other] this comment contains invisible unicode text flow control codepoints + } + .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + .suggestion = if their presence wasn't intentional, you can remove them + .label_comment_char = {$c_debug} + + lint_unit_bindings = binding has unit type `()` .label = this pattern is inferred to be the unit type `()` +lint_unknown_diagnostic_attribute = unknown diagnostic attribute +lint_unknown_diagnostic_attribute_typo_sugg = an attribute with a similar name exists + lint_unknown_gated_lint = unknown lint: `{$name}` .note = the `{$name}` lint is unstable @@ -668,11 +805,16 @@ lint_unknown_lint = *[false] did you mean: `{$replace}` } +lint_unknown_macro_variable = unknown macro variable `{$name}` + lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}` .help = add `#![register_tool({$tool_name})]` to the crate root lint_unnameable_test_items = cannot test inner items +lint_unnecessary_qualification = unnecessary qualification + .suggestion = remove the unnecessary path segments + lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´ lint_untranslatable_diag = diagnostics should be created using translatable messages @@ -680,6 +822,9 @@ lint_untranslatable_diag = diagnostics should be created using translatable mess lint_unused_allocation = unnecessary allocation, use `&` instead lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead +lint_unused_builtin_attribute = unused attribute `{$attr_name}` + .note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}` + lint_unused_closure = unused {$pre}{$count -> [one] closure @@ -696,14 +841,43 @@ lint_unused_coroutine = }{$post} that must be used .note = coroutines are lazy and do nothing unless resumed +lint_unused_crate_dependency = external crate `{$extern_crate}` unused in `{$local_crate}`: remove the dependency or add `use {$extern_crate} as _;` + lint_unused_def = unused {$pre}`{$def}`{$post} that must be used .suggestion = use `let _ = ...` to ignore the resulting value lint_unused_delim = unnecessary {$delim} around {$item} .suggestion = remove these {$delim} +lint_unused_doc_comment = unused doc comment + .label = rustdoc does not generate documentation for macro invocations + .help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +lint_unused_extern_crate = unused extern crate + .suggestion = remove it + lint_unused_import_braces = braces around {$node} is unnecessary +lint_unused_imports = {$num_snippets -> + [one] unused import: {$span_snippets} + *[other] unused imports: {$span_snippets} + } + .suggestion_remove_whole_use = remove the whole `use` item + .suggestion_remove_imports = {$num_to_remove -> + [one] remove the unused import + *[other] remove the unused imports + } + .help = if this is a test module, consider adding a `#[cfg(test)]` to the containing module + +lint_unused_label = unused label + +lint_unused_lifetime = lifetime parameter `{$ident}` never used + .suggestion = elide the unused lifetime + +lint_unused_macro_definition = unused macro definition: `{$name}` + +lint_unused_macro_use = unused `#[macro_use]` import + lint_unused_op = unused {$op} that must be used .label = the {$op} produces a value .suggestion = use `let _ = ...` to ignore the resulting value diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 563d96d9519fb..deeb3ae090c57 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -527,29 +527,24 @@ pub struct EarlyContext<'a> { pub buffered: LintBuffer, } -pub trait LintContext { - fn sess(&self) -> &Session; - +impl EarlyContext<'_> { /// Emit a lint at the appropriate level, with an optional associated span and an existing /// diagnostic. /// /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature #[rustc_lint_diagnostics] - fn span_lint_with_diagnostics( + pub fn span_lint_with_diagnostics( &self, lint: &'static Lint, - span: Option>, - decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), + span: MultiSpan, diagnostic: BuiltinLintDiag, ) { - // We first generate a blank diagnostic. - self.opt_span_lint(lint, span, diagnostics::builtin_message(&diagnostic), |db| { - // Now, set up surrounding context. - diagnostics::builtin(self.sess(), diagnostic, db); - // Rewrap `db`, and pass control to the user. - decorate(db) - }); + diagnostics::emit_buffered_lint(self, lint, span, diagnostic) } +} + +pub trait LintContext { + fn sess(&self) -> &Session; // FIXME: These methods should not take an Into -- instead, callers should need to // set the span in their `decorate` function (preferably using set_span). diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index f298ed98d9806..236eeee615218 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -1,64 +1,57 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +use std::borrow::Cow; + use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; -use rustc_errors::{ - elided_lifetime_in_path_suggestion, pluralize, Diag, DiagMessage, LintDiagnostic, -}; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; +use rustc_errors::{elided_lifetime_in_path_suggestion, DiagArgValue, MultiSpan}; use rustc_middle::middle::stability; -use rustc_session::lint::BuiltinLintDiag; -use rustc_session::Session; +use rustc_session::lint::{BuiltinLintDiag, Lint}; use rustc_span::BytePos; -use std::fmt::Write; +use crate::{lints, EarlyContext, LintContext as _}; mod check_cfg; -#[cfg(test)] -mod tests; - -pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) { +pub(super) fn emit_buffered_lint( + ctx: &EarlyContext<'_>, + lint: &'static Lint, + span: MultiSpan, + diagnostic: BuiltinLintDiag, +) { + let sess = ctx.sess(); match diagnostic { - BuiltinLintDiag::UnicodeTextFlow(span, content) => { + BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { let spans: Vec<_> = content .char_indices() .filter_map(|(i, c)| { TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| { - let lo = span.lo() + BytePos(2 + i as u32); - (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) + let lo = comment_span.lo() + BytePos(2 + i as u32); + (c, comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) }) }) .collect(); - let (an, s) = match spans.len() { - 1 => ("an ", ""), - _ => ("", "s"), - }; - diag.span_label( + let characters = spans + .iter() + .map(|&(c, span)| lints::UnicodeCharNoteSub { span, c_debug: format!("{c:?}") }) + .collect(); + let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion { + spans: spans.iter().map(|(_c, span)| *span).collect(), + }); + ctx.emit_span_lint( + lint, span, - format!( - "this comment contains {an}invisible unicode text flow control codepoint{s}", - ), - ); - for (c, span) in &spans { - diag.span_label(*span, format!("{c:?}")); - } - diag.note( - "these kind of unicode codepoints change the way text flows on \ - applications that support them, but can cause confusion because they \ - change the order of characters on the screen", - ); - if !spans.is_empty() { - diag.multipart_suggestion_with_style( - "if their presence wasn't intentional, you can remove them", - spans.into_iter().map(|(_, span)| (span, "".to_string())).collect(), - Applicability::MachineApplicable, - SuggestionStyle::HideCodeAlways, - ); - } - } - BuiltinLintDiag::AbsPathWithModule(span) => { - let (sugg, app) = match sess.source_map().span_to_snippet(span) { + lints::UnicodeTextFlow { + comment_span, + characters, + suggestions, + num_codepoints: spans.len(), + }, + ) + } + BuiltinLintDiag::AbsPathWithModule(mod_span) => { + let (replacement, applicability) = match sess.source_map().span_to_snippet(mod_span) { Ok(ref s) => { // FIXME(Manishearth) ideally the emitting code // can tell us whether or not this is global @@ -68,64 +61,90 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di } Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), }; - diag.span_suggestion(span, "use `crate`", sugg, app); - } - BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span, .. } => { - diag.span_label( + ctx.emit_span_lint( + lint, span, - "names from parent modules are not accessible without an explicit import", + lints::AbsPathWithModule { + sugg: lints::AbsPathWithModuleSugg { + span: mod_span, + applicability, + replacement, + }, + }, ); } - BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => { - diag.span_note(span_def, "the macro is defined here"); - } + BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident } => ctx + .emit_span_lint( + lint, + span, + lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident }, + ), + BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => ctx + .emit_span_lint( + lint, + span, + lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def }, + ), BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { - diag.subdiagnostic( - sess.dcx(), - elided_lifetime_in_path_suggestion( - sess.source_map(), - n, - path_span, - incl_angl_brckt, - insertion_span, - ), + ctx.emit_span_lint( + lint, + span, + lints::ElidedLifetimesInPaths { + subdiag: elided_lifetime_in_path_suggestion( + sess.source_map(), + n, + path_span, + incl_angl_brckt, + insertion_span, + ), + }, ); } BuiltinLintDiag::UnknownCrateTypes { span, candidate } => { - if let Some(candidate) = candidate { - diag.span_suggestion( - span, - "did you mean", - format!(r#""{candidate}""#), - Applicability::MaybeIncorrect, - ); - } - } - BuiltinLintDiag::UnusedImports { fix_msg, fixes, test_module_span, .. } => { - if !fixes.is_empty() { - diag.tool_only_multipart_suggestion( - fix_msg, - fixes, - Applicability::MachineApplicable, - ); - } + let sugg = candidate.map(|candidate| lints::UnknownCrateTypesSub { span, candidate }); + ctx.emit_span_lint(lint, span, lints::UnknownCrateTypes { sugg }); + } + BuiltinLintDiag::UnusedImports { + remove_whole_use, + num_to_remove, + remove_spans, + test_module_span, + span_snippets, + } => { + let sugg = if remove_whole_use { + lints::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] } + } else { + lints::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove } + }; + let test_module_span = + test_module_span.map(|span| sess.source_map().guess_head_span(span)); - if let Some(span) = test_module_span { - diag.span_help( - sess.source_map().guess_head_span(span), - "if this is a test module, consider adding a `#[cfg(test)]` to the containing module", - ); - } + ctx.emit_span_lint( + lint, + span, + lints::UnusedImports { + sugg, + test_module_span, + num_snippets: span_snippets.len(), + span_snippets: DiagArgValue::StrListSepByAnd( + span_snippets.into_iter().map(Cow::Owned).collect(), + ), + }, + ); } BuiltinLintDiag::RedundantImport(spans, ident) => { - for (span, is_imported) in spans { - let introduced = if is_imported { "imported" } else { "defined" }; - let span_msg = if span.is_dummy() { "by the extern prelude" } else { "here" }; - diag.span_label( - span, - format!("the item `{ident}` is already {introduced} {span_msg}"), - ); - } + let subs = spans + .into_iter() + .map(|(span, is_imported)| { + (match (span.is_dummy(), is_imported) { + (false, true) => lints::RedundantImportSub::ImportedHere, + (false, false) => lints::RedundantImportSub::DefinedHere, + (true, true) => lints::RedundantImportSub::ImportedPrelude, + (true, false) => lints::RedundantImportSub::DefinedPrelude, + })(span) + }) + .collect(); + ctx.emit_span_lint(lint, span, lints::RedundantImport { subs, ident }); } BuiltinLintDiag::DeprecatedMacro { suggestion, @@ -139,106 +158,110 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di kind: "macro".to_owned(), suggestion, }); - let deprecated = - stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }; - deprecated.decorate_lint(diag); + ctx.emit_span_lint( + lint, + span, + stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }, + ); } - BuiltinLintDiag::UnusedDocComment(span) => { - diag.span_label(span, "rustdoc does not generate documentation for macro invocations"); - diag.help("to document an item produced by a macro, \ - the macro must produce the documentation as part of its expansion"); + BuiltinLintDiag::UnusedDocComment(attr_span) => { + ctx.emit_span_lint(lint, span, lints::UnusedDocComment { span: attr_span }); } - BuiltinLintDiag::PatternsInFnsWithoutBody { span, ident, .. } => { - diag.span_suggestion( + BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => { + let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span }; + + ctx.emit_span_lint( + lint, span, - "remove `mut` from the parameter", - ident, - Applicability::MachineApplicable, + if is_foreign { + lints::PatternsInFnsWithoutBody::Foreign { sub } + } else { + lints::PatternsInFnsWithoutBody::Bodiless { sub } + }, ); } - BuiltinLintDiag::MissingAbi(span, default_abi) => { - diag.span_label(span, "ABI should be specified here"); - diag.help(format!("the default ABI is {}", default_abi.name())); + BuiltinLintDiag::MissingAbi(label_span, default_abi) => { + ctx.emit_span_lint( + lint, + span, + lints::MissingAbi { span: label_span, default_abi: default_abi.name() }, + ); } - BuiltinLintDiag::LegacyDeriveHelpers(span) => { - diag.span_label(span, "the attribute is introduced here"); + BuiltinLintDiag::LegacyDeriveHelpers(label_span) => { + ctx.emit_span_lint(lint, span, lints::LegacyDeriveHelpers { span: label_span }); } - BuiltinLintDiag::ProcMacroBackCompat(note) => { - diag.note(note); + BuiltinLintDiag::ProcMacroBackCompat { crate_name, fixed_version } => { + ctx.emit_span_lint( + lint, + span, + lints::ProcMacroBackCompat { crate_name, fixed_version }, + ); } - BuiltinLintDiag::OrPatternsBackCompat(span, suggestion) => { - diag.span_suggestion( + BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => { + ctx.emit_span_lint( + lint, span, - "use pat_param to preserve semantics", - suggestion, - Applicability::MachineApplicable, + lints::OrPatternsBackCompat { span: suggestion_span, suggestion }, ); } - BuiltinLintDiag::ReservedPrefix(span, _) => { - diag.span_label(span, "unknown prefix"); - diag.span_suggestion_verbose( - span.shrink_to_hi(), - "insert whitespace here to avoid this being parsed as a prefix in Rust 2021", - " ", - Applicability::MachineApplicable, + BuiltinLintDiag::ReservedPrefix(label_span, prefix) => { + ctx.emit_span_lint( + lint, + span, + lints::ReservedPrefix { + label: label_span, + suggestion: label_span.shrink_to_hi(), + prefix, + }, ); } BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { - diag.span_note( - invoc_span, - format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`") - ); + ctx.emit_span_lint( + lint, + span, + lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }, + ); } BuiltinLintDiag::TrailingMacro(is_trailing, name) => { - if is_trailing { - diag.note("macro invocations at the end of a block are treated as expressions"); - diag.note(format!("to ignore the value produced by the macro, add a semicolon after the invocation of `{name}`")); - } - } - BuiltinLintDiag::BreakWithLabelAndLoop(span) => { - diag.multipart_suggestion( - "wrap this expression in parentheses", - vec![ - (span.shrink_to_lo(), "(".to_string()), - (span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, + ctx.emit_span_lint(lint, span, lints::TrailingMacro { is_trailing, name }); + } + BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => { + ctx.emit_span_lint( + lint, + span, + lints::BreakWithLabelAndLoop { + sub: lints::BreakWithLabelAndLoopSub { + left: sugg_span.shrink_to_lo(), + right: sugg_span.shrink_to_hi(), + }, + }, ); } BuiltinLintDiag::UnexpectedCfgName(name, value) => { - check_cfg::unexpected_cfg_name(sess, diag, name, value) + ctx.emit_span_lint(lint, span, check_cfg::unexpected_cfg_name(sess, name, value)); } BuiltinLintDiag::UnexpectedCfgValue(name, value) => { - check_cfg::unexpected_cfg_value(sess, diag, name, value) - } - BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => { - let left_sp = diag.span.primary_span().unwrap(); - match sugg { - Some((right_sp, sugg)) => diag.multipart_suggestion( - "move it to the end of the type declaration", - vec![(left_sp, String::new()), (right_sp, sugg)], - Applicability::MachineApplicable, - ), - None => diag.span_suggestion( - left_sp, - "remove this `where`", - "", - Applicability::MachineApplicable, - ), + ctx.emit_span_lint(lint, span, check_cfg::unexpected_cfg_value(sess, name, value)); + } + BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => { + let suggestion = match sugg { + Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd { + left: left_sp, + right: right_sp, + sugg, + }, + None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp }, }; - diag.note("see issue #89122 for more information"); + ctx.emit_span_lint(lint, span, lints::DeprecatedWhereClauseLocation { suggestion }); } BuiltinLintDiag::SingleUseLifetime { param_span, use_span: Some((use_span, elide)), deletion_span, - .. + ident, } => { debug!(?param_span, ?use_span, ?deletion_span); - diag.span_label(param_span, "this lifetime..."); - diag.span_label(use_span, "...is used only here"); - if let Some(deletion_span) = deletion_span { - let msg = "elide the single-use lifetime"; + let suggestion = if let Some(deletion_span) = deletion_span { let (use_span, replace_lt) = if elide { let use_span = sess.source_map().span_extend_while_whitespace(use_span); (use_span, String::new()) @@ -249,26 +272,22 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di // issue 107998 for the case such as a wrong function pointer type // `deletion_span` is empty and there is no need to report lifetime uses here - let suggestions = if deletion_span.is_empty() { - vec![(use_span, replace_lt)] - } else { - vec![(deletion_span, String::new()), (use_span, replace_lt)] - }; - diag.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable); - } + let deletion_span = + if deletion_span.is_empty() { None } else { Some(deletion_span) }; + Some(lints::SingleUseLifetimeSugg { deletion_span, use_span, replace_lt }) + } else { + None + }; + + ctx.emit_span_lint( + lint, + span, + lints::SingleUseLifetime { suggestion, param_span, use_span, ident }, + ); } - BuiltinLintDiag::SingleUseLifetime { - param_span: _, use_span: None, deletion_span, .. - } => { + BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => { debug!(?deletion_span); - if let Some(deletion_span) = deletion_span { - diag.span_suggestion( - deletion_span, - "elide the unused lifetime", - "", - Applicability::MachineApplicable, - ); - } + ctx.emit_span_lint(lint, span, lints::UnusedLifetime { deletion_span, ident }); } BuiltinLintDiag::NamedArgumentUsedPositionally { position_sp_to_replace, @@ -277,19 +296,12 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di named_arg_name, is_formatting_arg, } => { - diag.span_label( - named_arg_sp, - "this named argument is referred to by position in formatting string", - ); - if let Some(positional_arg_for_msg) = position_sp_for_msg { - let msg = format!( - "this formatting argument uses named argument `{named_arg_name}` by position" - ); - diag.span_label(positional_arg_for_msg, msg); - } - - if let Some(positional_arg_to_replace) = position_sp_to_replace { - let name = if is_formatting_arg { named_arg_name + "$" } else { named_arg_name }; + let (suggestion, name) = if let Some(positional_arg_to_replace) = position_sp_to_replace + { + let mut name = named_arg_name.clone(); + if is_formatting_arg { + name.push('$') + }; let span_to_replace = if let Ok(positional_arg_content) = sess.source_map().span_to_snippet(positional_arg_to_replace) && positional_arg_content.starts_with(':') @@ -298,31 +310,40 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di } else { positional_arg_to_replace }; - diag.span_suggestion_verbose( - span_to_replace, - "use the named argument by name to avoid ambiguity", + (Some(span_to_replace), name) + } else { + (None, String::new()) + }; + + ctx.emit_span_lint( + lint, + span, + lints::NamedArgumentUsedPositionally { + named_arg_sp, + position_label_sp: position_sp_for_msg, + suggestion, name, - Applicability::MaybeIncorrect, - ); - } + named_arg_name, + }, + ) } - BuiltinLintDiag::ByteSliceInPackedStructWithDerive { .. } => { - diag.help("consider implementing the trait by hand, or remove the `packed` attribute"); + BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => { + ctx.emit_span_lint(lint, span, lints::ByteSliceInPackedStructWithDerive { ty }) } BuiltinLintDiag::UnusedExternCrate { removal_span } => { - diag.span_suggestion(removal_span, "remove it", "", Applicability::MachineApplicable); + ctx.emit_span_lint(lint, span, lints::UnusedExternCrate { removal_span }) } BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => { let suggestion_span = vis_span.between(ident_span); - diag.span_suggestion_verbose( - suggestion_span, - "convert it to a `use`", - if vis_span.is_empty() { "use " } else { " use " }, - Applicability::MachineApplicable, + let code = if vis_span.is_empty() { "use " } else { " use " }; + ctx.emit_span_lint( + lint, + span, + lints::ExternCrateNotIdiomatic { span: suggestion_span, code }, ); } BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => { - rustc_errors::report_ambiguity_error(diag, ambiguity); + ctx.emit_span_lint(lint, span, lints::AmbiguousGlobImports { ambiguity }); } BuiltinLintDiag::AmbiguousGlobReexports { name, @@ -330,15 +351,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di first_reexport_span, duplicate_reexport_span, } => { - diag.span_label( - first_reexport_span, - format!("the name `{name}` in the {namespace} namespace is first re-exported here"), - ); - diag.span_label( - duplicate_reexport_span, - format!( - "but the name `{name}` in the {namespace} namespace is also re-exported here" - ), + ctx.emit_span_lint( + lint, + span, + lints::AmbiguousGlobReexports { + first_reexport: first_reexport_span, + duplicate_reexport: duplicate_reexport_span, + name, + namespace, + }, ); } BuiltinLintDiag::HiddenGlobReexports { @@ -347,261 +368,127 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di glob_reexport_span, private_item_span, } => { - diag.span_note(glob_reexport_span, format!("the name `{name}` in the {namespace} namespace is supposed to be publicly re-exported here")); - diag.span_note(private_item_span, "but the private item here shadows it".to_owned()); + ctx.emit_span_lint( + lint, + span, + lints::HiddenGlobReexports { + glob_reexport: glob_reexport_span, + private_item: private_item_span, + + name, + namespace, + }, + ); } BuiltinLintDiag::UnusedQualifications { removal_span } => { - diag.span_suggestion_verbose( - removal_span, - "remove the unnecessary path segments", - "", - Applicability::MachineApplicable, - ); + ctx.emit_span_lint(lint, span, lints::UnusedQualifications { removal_span }); } - BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span } => { - diag.span_suggestion_verbose( - if elided { span.shrink_to_hi() } else { span }, - "use the `'static` lifetime", - if elided { "'static " } else { "'static" }, - Applicability::MachineApplicable, + BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span } => { + let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; + let code = if elided { "'static " } else { "'static" }; + ctx.emit_span_lint( + lint, + span, + lints::AssociatedConstElidedLifetime { span: lt_span, code, elided }, ); } - BuiltinLintDiag::RedundantImportVisibility { max_vis, span, .. } => { - diag.span_note(span, format!("the most public imported item is `{max_vis}`")); - diag.help( - "reduce the glob import's visibility or increase visibility of imported items", + BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => { + ctx.emit_span_lint( + lint, + span, + lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis }, ); } - BuiltinLintDiag::UnknownDiagnosticAttribute { span, typo_name } => { - if let Some(typo_name) = typo_name { - diag.span_suggestion_verbose( - span, - "an attribute with a similar name exists", - typo_name, - Applicability::MachineApplicable, - ); - } - } - BuiltinLintDiag::MacroUseDeprecated - | BuiltinLintDiag::UnusedMacroUse - | BuiltinLintDiag::PrivateExternCrateReexport(_) - | BuiltinLintDiag::UnusedLabel - | BuiltinLintDiag::MacroIsPrivate(_) - | BuiltinLintDiag::UnusedMacroDefinition(_) - | BuiltinLintDiag::MacroRuleNeverUsed(_, _) - | BuiltinLintDiag::UnstableFeature(_) - | BuiltinLintDiag::AvoidUsingIntelSyntax - | BuiltinLintDiag::AvoidUsingAttSyntax - | BuiltinLintDiag::IncompleteInclude - | BuiltinLintDiag::UnnameableTestItems - | BuiltinLintDiag::DuplicateMacroAttribute - | BuiltinLintDiag::CfgAttrNoAttributes - | BuiltinLintDiag::CrateTypeInCfgAttr - | BuiltinLintDiag::CrateNameInCfgAttr - | BuiltinLintDiag::MissingFragmentSpecifier - | BuiltinLintDiag::MetaVariableStillRepeating(_) - | BuiltinLintDiag::MetaVariableWrongOperator - | BuiltinLintDiag::DuplicateMatcherBinding - | BuiltinLintDiag::UnknownMacroVariable(_) - | BuiltinLintDiag::UnusedExternCrate2 { .. } - | BuiltinLintDiag::WasmCAbi - | BuiltinLintDiag::IllFormedAttributeInput { .. } - | BuiltinLintDiag::InnerAttributeUnstable { .. } => {} - } -} - -pub(super) fn builtin_message(diagnostic: &BuiltinLintDiag) -> DiagMessage { - match diagnostic { - BuiltinLintDiag::AbsPathWithModule(_) => { - "absolute paths must start with `self`, `super`, `crate`, or an \ - external crate name in the 2018 edition" - .into() - } - BuiltinLintDiag::ProcMacroDeriveResolutionFallback { ns, ident, .. } => { - format!("cannot find {} `{}` in this scope", ns.descr(), ident).into() - } - BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(_) => { - "macro-expanded `macro_export` macros from the current crate cannot \ - be referred to by absolute paths" - .into() - } - BuiltinLintDiag::ElidedLifetimesInPaths(_, _, _, _) => { - "hidden lifetime parameters in types are deprecated".into() - } - BuiltinLintDiag::UnknownCrateTypes { .. } => "invalid `crate_type` value".into(), - BuiltinLintDiag::UnusedImports { span_snippets, .. } => format!( - "unused import{}{}", - pluralize!(span_snippets.len()), - if !span_snippets.is_empty() { - format!(": {}", span_snippets.join(", ")) - } else { - String::new() - } - ) - .into(), - BuiltinLintDiag::RedundantImport(_, source) => { - format!("the item `{source}` is imported redundantly").into() - } - BuiltinLintDiag::DeprecatedMacro { since_kind, .. } => { - stability::Deprecated::msg_for_since_kind(since_kind) - } - BuiltinLintDiag::MissingAbi(_, _) => crate::fluent_generated::lint_extern_without_abi, - BuiltinLintDiag::UnusedDocComment(_) => "unused doc comment".into(), - BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, .. } => { - format!("unused attribute `{attr_name}`").into() - } - BuiltinLintDiag::PatternsInFnsWithoutBody { is_foreign, .. } => { - if *is_foreign { - crate::fluent_generated::lint_pattern_in_foreign - } else { - crate::fluent_generated::lint_pattern_in_bodiless - } - } - BuiltinLintDiag::LegacyDeriveHelpers(_) => { - "derive helper attribute is used before it is introduced".into() - } - BuiltinLintDiag::ProcMacroBackCompat(_) => "using an old version of `rental`".into(), - BuiltinLintDiag::OrPatternsBackCompat(_, _) => { - "the meaning of the `pat` fragment specifier is changing in Rust 2021, \ - which may affect this macro" - .into() - } - BuiltinLintDiag::ReservedPrefix(_, prefix) => { - format!("prefix `{prefix}` is unknown").into() - } - BuiltinLintDiag::TrailingMacro(_, _) => { - "trailing semicolon in macro used in expression position".into() - } - BuiltinLintDiag::BreakWithLabelAndLoop(_) => { - "this labeled break expression is easy to confuse with an unlabeled break with a \ - labeled value expression" - .into() - } - BuiltinLintDiag::UnicodeTextFlow(_, _) => { - "unicode codepoint changing visible direction of text present in comment".into() - } - BuiltinLintDiag::UnexpectedCfgName((name, _), _) => { - format!("unexpected `cfg` condition name: `{}`", name).into() - } - BuiltinLintDiag::UnexpectedCfgValue(_, v) => if let Some((value, _)) = v { - format!("unexpected `cfg` condition value: `{value}`") - } else { - format!("unexpected `cfg` condition value: (none)") + BuiltinLintDiag::UnknownDiagnosticAttribute { span: typo_span, typo_name } => { + let typo = typo_name.map(|typo_name| lints::UnknownDiagnosticAttributeTypoSugg { + span: typo_span, + typo_name, + }); + ctx.emit_span_lint(lint, span, lints::UnknownDiagnosticAttribute { typo }); } - .into(), - BuiltinLintDiag::DeprecatedWhereclauseLocation(_) => { - crate::fluent_generated::lint_deprecated_where_clause_location + BuiltinLintDiag::MacroUseDeprecated => { + ctx.emit_span_lint(lint, span, lints::MacroUseDeprecated) } - BuiltinLintDiag::SingleUseLifetime { use_span, ident, .. } => { - if use_span.is_some() { - format!("lifetime parameter `{}` only used once", ident).into() - } else { - format!("lifetime parameter `{}` never used", ident).into() - } + BuiltinLintDiag::UnusedMacroUse => ctx.emit_span_lint(lint, span, lints::UnusedMacroUse), + BuiltinLintDiag::PrivateExternCrateReexport(ident) => { + ctx.emit_span_lint(lint, span, lints::PrivateExternCrateReexport { ident }) } - BuiltinLintDiag::NamedArgumentUsedPositionally { named_arg_name, .. } => { - format!("named argument `{}` is not used by name", named_arg_name).into() + BuiltinLintDiag::UnusedLabel => ctx.emit_span_lint(lint, span, lints::UnusedLabel), + BuiltinLintDiag::MacroIsPrivate(ident) => { + ctx.emit_span_lint(lint, span, lints::MacroIsPrivate { ident }) } - BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => { - format!("{ty} slice in a packed struct that derives a built-in trait").into() - } - BuiltinLintDiag::UnusedExternCrate { .. } => "unused extern crate".into(), - BuiltinLintDiag::ExternCrateNotIdiomatic { .. } => { - "`extern crate` is not idiomatic in the new edition".into() - } - BuiltinLintDiag::AmbiguousGlobImports { diag } => diag.msg.clone().into(), - BuiltinLintDiag::AmbiguousGlobReexports { .. } => "ambiguous glob re-exports".into(), - BuiltinLintDiag::HiddenGlobReexports { .. } => { - "private item shadows public glob re-export".into() - } - BuiltinLintDiag::UnusedQualifications { .. } => "unnecessary qualification".into(), - BuiltinLintDiag::AssociatedConstElidedLifetime { elided, .. } => if *elided { - "`&` without an explicit lifetime name cannot be used here" - } else { - "`'_` cannot be used here" - } - .into(), - BuiltinLintDiag::RedundantImportVisibility { import_vis, .. } => format!( - "glob import doesn't reexport anything with visibility `{}` \ - because no imported item is public enough", - import_vis - ) - .into(), - BuiltinLintDiag::MacroUseDeprecated => "deprecated `#[macro_use]` attribute used to \ - import macros should be replaced at use sites \ - with a `use` item to import the macro \ - instead" - .into(), - BuiltinLintDiag::UnusedMacroUse => "unused `#[macro_use]` import".into(), - BuiltinLintDiag::PrivateExternCrateReexport(ident) => format!( - "extern crate `{ident}` is private, and cannot be \ - re-exported (error E0365), consider declaring with \ - `pub`" - ) - .into(), - BuiltinLintDiag::UnusedLabel => "unused label".into(), - BuiltinLintDiag::MacroIsPrivate(ident) => format!("macro `{ident}` is private").into(), BuiltinLintDiag::UnusedMacroDefinition(name) => { - format!("unused macro definition: `{}`", name).into() + ctx.emit_span_lint(lint, span, lints::UnusedMacroDefinition { name }) } BuiltinLintDiag::MacroRuleNeverUsed(n, name) => { - format!("rule #{} of macro `{}` is never used", n + 1, name).into() + ctx.emit_span_lint(lint, span, lints::MacroRuleNeverUsed { n: n + 1, name }) + } + BuiltinLintDiag::UnstableFeature(msg) => { + ctx.emit_span_lint(lint, span, lints::UnstableFeature { msg }) } - BuiltinLintDiag::UnstableFeature(msg) => msg.clone().into(), BuiltinLintDiag::AvoidUsingIntelSyntax => { - "avoid using `.intel_syntax`, Intel syntax is the default".into() + ctx.emit_span_lint(lint, span, lints::AvoidIntelSyntax) } BuiltinLintDiag::AvoidUsingAttSyntax => { - "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead".into() + ctx.emit_span_lint(lint, span, lints::AvoidAttSyntax) } BuiltinLintDiag::IncompleteInclude => { - "include macro expected single expression in source".into() + ctx.emit_span_lint(lint, span, lints::IncompleteInclude) + } + BuiltinLintDiag::UnnameableTestItems => { + ctx.emit_span_lint(lint, span, lints::UnnameableTestItems) + } + BuiltinLintDiag::DuplicateMacroAttribute => { + ctx.emit_span_lint(lint, span, lints::DuplicateMacroAttribute) } - BuiltinLintDiag::UnnameableTestItems => crate::fluent_generated::lint_unnameable_test_items, - BuiltinLintDiag::DuplicateMacroAttribute => "duplicated attribute".into(), BuiltinLintDiag::CfgAttrNoAttributes => { - crate::fluent_generated::lint_cfg_attr_no_attributes + ctx.emit_span_lint(lint, span, lints::CfgAttrNoAttributes) } BuiltinLintDiag::CrateTypeInCfgAttr => { - crate::fluent_generated::lint_crate_type_in_cfg_attr_deprecated + ctx.emit_span_lint(lint, span, lints::CrateTypeInCfgAttr) } BuiltinLintDiag::CrateNameInCfgAttr => { - crate::fluent_generated::lint_crate_name_in_cfg_attr_deprecated + ctx.emit_span_lint(lint, span, lints::CrateNameInCfgAttr) + } + BuiltinLintDiag::MissingFragmentSpecifier => { + ctx.emit_span_lint(lint, span, lints::MissingFragmentSpecifier) } - BuiltinLintDiag::MissingFragmentSpecifier => "missing fragment specifier".into(), BuiltinLintDiag::MetaVariableStillRepeating(name) => { - format!("variable '{name}' is still repeating at this depth").into() + ctx.emit_span_lint(lint, span, lints::MetaVariableStillRepeating { name }) } BuiltinLintDiag::MetaVariableWrongOperator => { - "meta-variable repeats with different Kleene operator".into() + ctx.emit_span_lint(lint, span, lints::MetaVariableWrongOperator) + } + BuiltinLintDiag::DuplicateMatcherBinding => { + ctx.emit_span_lint(lint, span, lints::DuplicateMatcherBinding) } - BuiltinLintDiag::DuplicateMatcherBinding => "duplicate matcher binding".into(), BuiltinLintDiag::UnknownMacroVariable(name) => { - format!("unknown macro variable `{name}`").into() - } - BuiltinLintDiag::UnusedExternCrate2 { extern_crate, local_crate } => format!( - "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`", - extern_crate, local_crate, extern_crate - ) - .into(), - BuiltinLintDiag::WasmCAbi => crate::fluent_generated::lint_wasm_c_abi, - BuiltinLintDiag::IllFormedAttributeInput { suggestions } => suggestions - .iter() - .enumerate() - .fold("attribute must be of the form ".to_string(), |mut acc, (i, sugg)| { - if i != 0 { - write!(acc, " or ").unwrap(); - } - write!(acc, "`{sugg}`").unwrap(); - acc - }) - .into(), - BuiltinLintDiag::InnerAttributeUnstable { is_macro } => if *is_macro { - "inner macro attributes are unstable" - } else { - "custom inner attributes are unstable" - } - .into(), - BuiltinLintDiag::UnknownDiagnosticAttribute { .. } => "unknown diagnostic attribute".into(), + ctx.emit_span_lint(lint, span, lints::UnknownMacroVariable { name }) + } + BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => ctx.emit_span_lint( + lint, + span, + lints::UnusedCrateDependency { extern_crate, local_crate }, + ), + BuiltinLintDiag::WasmCAbi => ctx.emit_span_lint(lint, span, lints::WasmCAbi), + BuiltinLintDiag::IllFormedAttributeInput { suggestions } => ctx.emit_span_lint( + lint, + span, + lints::IllFormedAttributeInput { + num_suggestions: suggestions.len(), + suggestions: DiagArgValue::StrListSepByAnd( + suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), + ), + }, + ), + BuiltinLintDiag::InnerAttributeUnstable { is_macro } => ctx.emit_span_lint( + lint, + span, + if is_macro { + lints::InnerAttributeUnstable::InnerMacroAttribute + } else { + lints::InnerAttributeUnstable::CustomInnerAttribute + }, + ), } } diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index 38a87d9a11c29..020ca1753cf0b 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -1,4 +1,3 @@ -use rustc_errors::Diag; use rustc_middle::bug; use rustc_session::{config::ExpectedValues, Session}; use rustc_span::edit_distance::find_best_match_for_name; @@ -45,10 +44,9 @@ fn to_check_cfg_arg(name: Symbol, value: Option, quotes: EscapeQuotes) - pub(super) fn unexpected_cfg_name( sess: &Session, - diag: &mut Diag<'_, ()>, (name, name_span): (Symbol, Span), value: Option<(Symbol, Span)>, -) { +) -> lints::UnexpectedCfgName { #[allow(rustc::potential_query_instability)] let possibilities: Vec = sess.psess.check_config.expecteds.keys().copied().collect(); @@ -179,15 +177,14 @@ pub(super) fn unexpected_cfg_name( )) }; - diag.subdiagnostic(diag.dcx, lints::UnexpectedCfgNameSub { code_sugg, invocation_help }); + lints::UnexpectedCfgName { code_sugg, invocation_help, name } } pub(super) fn unexpected_cfg_value( sess: &Session, - diag: &mut Diag<'_, ()>, (name, name_span): (Symbol, Span), value: Option<(Symbol, Span)>, -) { +) -> lints::UnexpectedCfgValue { let Some(ExpectedValues::Some(values)) = &sess.psess.check_config.expecteds.get(&name) else { bug!( "it shouldn't be possible to have a diagnostic on a value whose name is not in values" @@ -287,5 +284,10 @@ pub(super) fn unexpected_cfg_value( lints::unexpected_cfg_value::InvocationHelp::Rustc(help) }; - diag.subdiagnostic(diag.dcx, lints::UnexpectedCfgValueSub { code_sugg, invocation_help }); + lints::UnexpectedCfgValue { + code_sugg, + invocation_help, + has_value: value.is_some(), + value: value.map_or_else(String::new, |(v, _span)| v.to_string()), + } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 80cb70ba277c8..736c7a1106932 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -14,7 +14,7 @@ //! upon. As the ast is traversed, this keeps track of the current lint level //! for all lint attributes. -use crate::context::{EarlyContext, LintContext, LintStore}; +use crate::context::{EarlyContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; use rustc_ast::ptr::P; use rustc_ast::visit::{self as ast_visit, walk_list, Visitor}; @@ -45,7 +45,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { fn inlined_check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; - self.context.span_lint_with_diagnostics(lint_id.lint, Some(span), |_| {}, diagnostic); + self.context.span_lint_with_diagnostics(lint_id.lint, span, diagnostic); } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 2a07db27616ab..3bd6faca37963 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,16 +5,22 @@ use std::num::NonZero; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ - codes::*, Applicability, Diag, DiagMessage, DiagStyledString, EmissionGuarantee, - LintDiagnostic, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, + codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, + ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, SubdiagMessageOp, + Subdiagnostic, SuggestionStyle, }; -use rustc_hir::def_id::DefId; +use rustc_hir::{def::Namespace, def_id::DefId}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{ inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt, }; -use rustc_session::Session; -use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; +use rustc_session::{lint::AmbiguityErrorDiag, Session}; +use rustc_span::{ + edition::Edition, + sym, + symbol::{Ident, MacroRulesNormalizedIdent}, + Span, Symbol, +}; use crate::{ builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext, @@ -1986,12 +1992,15 @@ impl UnexpectedCfgRustcHelp { } } -#[derive(Subdiagnostic)] -pub struct UnexpectedCfgNameSub { +#[derive(LintDiagnostic)] +#[diag(lint_unexpected_cfg_name)] +pub struct UnexpectedCfgName { #[subdiagnostic] pub code_sugg: unexpected_cfg_name::CodeSuggestion, #[subdiagnostic] pub invocation_help: unexpected_cfg_name::InvocationHelp, + + pub name: Symbol, } pub mod unexpected_cfg_name { @@ -2093,12 +2102,16 @@ pub mod unexpected_cfg_name { } } -#[derive(Subdiagnostic)] -pub struct UnexpectedCfgValueSub { +#[derive(LintDiagnostic)] +#[diag(lint_unexpected_cfg_value)] +pub struct UnexpectedCfgValue { #[subdiagnostic] pub code_sugg: unexpected_cfg_value::CodeSuggestion, #[subdiagnostic] pub invocation_help: unexpected_cfg_value::InvocationHelp, + + pub has_value: bool, + pub value: String, } pub mod unexpected_cfg_value { @@ -2204,3 +2217,573 @@ pub mod unexpected_cfg_value { Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp), } } + +#[derive(LintDiagnostic)] +#[diag(lint_macro_use_deprecated)] +pub struct MacroUseDeprecated; + +#[derive(LintDiagnostic)] +#[diag(lint_unused_macro_use)] +pub struct UnusedMacroUse; + +#[derive(LintDiagnostic)] +#[diag(lint_private_extern_crate_reexport)] +pub struct PrivateExternCrateReexport { + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_label)] +pub struct UnusedLabel; + +#[derive(LintDiagnostic)] +#[diag(lint_macro_is_private)] +pub struct MacroIsPrivate { + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_macro_definition)] +pub struct UnusedMacroDefinition { + pub name: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_macro_rule_never_used)] +pub struct MacroRuleNeverUsed { + pub n: usize, + pub name: Symbol, +} + +pub struct UnstableFeature { + pub msg: DiagMessage, +} + +impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { + fn decorate_lint<'b>(self, _diag: &'b mut Diag<'a, ()>) {} + + fn msg(&self) -> DiagMessage { + self.msg.clone() + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_avoid_intel_syntax)] +pub struct AvoidIntelSyntax; + +#[derive(LintDiagnostic)] +#[diag(lint_avoid_att_syntax)] +pub struct AvoidAttSyntax; + +#[derive(LintDiagnostic)] +#[diag(lint_incomplete_include)] +pub struct IncompleteInclude; + +#[derive(LintDiagnostic)] +#[diag(lint_unnameable_test_items)] +pub struct UnnameableTestItems; + +#[derive(LintDiagnostic)] +#[diag(lint_duplicate_macro_attribute)] +pub struct DuplicateMacroAttribute; + +#[derive(LintDiagnostic)] +#[diag(lint_cfg_attr_no_attributes)] +pub struct CfgAttrNoAttributes; + +#[derive(LintDiagnostic)] +#[diag(lint_crate_type_in_cfg_attr_deprecated)] +pub struct CrateTypeInCfgAttr; + +#[derive(LintDiagnostic)] +#[diag(lint_crate_name_in_cfg_attr_deprecated)] +pub struct CrateNameInCfgAttr; + +#[derive(LintDiagnostic)] +#[diag(lint_missing_fragment_specifier)] +pub struct MissingFragmentSpecifier; + +#[derive(LintDiagnostic)] +#[diag(lint_metavariable_still_repeating)] +pub struct MetaVariableStillRepeating { + pub name: MacroRulesNormalizedIdent, +} + +#[derive(LintDiagnostic)] +#[diag(lint_metavariable_wrong_operator)] +pub struct MetaVariableWrongOperator; + +#[derive(LintDiagnostic)] +#[diag(lint_duplicate_matcher_binding)] +pub struct DuplicateMatcherBinding; + +#[derive(LintDiagnostic)] +#[diag(lint_unknown_macro_variable)] +pub struct UnknownMacroVariable { + pub name: MacroRulesNormalizedIdent, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_crate_dependency)] +pub struct UnusedCrateDependency { + pub extern_crate: Symbol, + pub local_crate: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_wasm_c_abi)] +pub struct WasmCAbi; + +#[derive(LintDiagnostic)] +#[diag(lint_ill_formed_attribute_input)] +pub struct IllFormedAttributeInput { + pub num_suggestions: usize, + pub suggestions: DiagArgValue, +} + +#[derive(LintDiagnostic)] +pub enum InnerAttributeUnstable { + #[diag(lint_inner_macro_attribute_unstable)] + InnerMacroAttribute, + #[diag(lint_custom_inner_attribute_unstable)] + CustomInnerAttribute, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unknown_diagnostic_attribute)] +pub struct UnknownDiagnosticAttribute { + #[subdiagnostic] + pub typo: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion( + lint_unknown_diagnostic_attribute_typo_sugg, + style = "verbose", + code = "{typo_name}", + applicability = "machine-applicable" +)] +pub struct UnknownDiagnosticAttributeTypoSugg { + #[primary_span] + pub span: Span, + pub typo_name: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unicode_text_flow)] +#[note] +pub struct UnicodeTextFlow { + #[label] + pub comment_span: Span, + #[subdiagnostic] + pub characters: Vec, + #[subdiagnostic] + pub suggestions: Option, + + pub num_codepoints: usize, +} + +#[derive(Subdiagnostic)] +#[label(lint_label_comment_char)] +pub struct UnicodeCharNoteSub { + #[primary_span] + pub span: Span, + pub c_debug: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")] +pub struct UnicodeTextFlowSuggestion { + #[suggestion_part(code = "")] + pub spans: Vec, +} + +#[derive(LintDiagnostic)] +#[diag(lint_abs_path_with_module)] +pub struct AbsPathWithModule { + #[subdiagnostic] + pub sugg: AbsPathWithModuleSugg, +} + +#[derive(Subdiagnostic)] +#[suggestion(lint_suggestion, code = "{replacement}")] +pub struct AbsPathWithModuleSugg { + #[primary_span] + pub span: Span, + #[applicability] + pub applicability: Applicability, + pub replacement: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_proc_macro_derive_resolution_fallback)] +pub struct ProcMacroDeriveResolutionFallback { + #[label] + pub span: Span, + pub ns: Namespace, + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)] +pub struct MacroExpandedMacroExportsAccessedByAbsolutePaths { + #[note] + pub definition: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_hidden_lifetime_parameters)] +pub struct ElidedLifetimesInPaths { + #[subdiagnostic] + pub subdiag: ElidedLifetimeInPathSubdiag, +} + +#[derive(LintDiagnostic)] +#[diag(lint_invalid_crate_type_value)] +pub struct UnknownCrateTypes { + #[subdiagnostic] + pub sugg: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")] +pub struct UnknownCrateTypesSub { + #[primary_span] + pub span: Span, + pub candidate: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_imports)] +pub struct UnusedImports { + #[subdiagnostic] + pub sugg: UnusedImportsSugg, + #[help] + pub test_module_span: Option, + + pub span_snippets: DiagArgValue, + pub num_snippets: usize, +} + +#[derive(Subdiagnostic)] +pub enum UnusedImportsSugg { + #[suggestion( + lint_suggestion_remove_whole_use, + applicability = "machine-applicable", + code = "", + style = "tool-only" + )] + RemoveWholeUse { + #[primary_span] + span: Span, + }, + #[multipart_suggestion( + lint_suggestion_remove_imports, + applicability = "machine-applicable", + style = "tool-only" + )] + RemoveImports { + #[suggestion_part(code = "")] + remove_spans: Vec, + num_to_remove: usize, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_redundant_import)] +pub struct RedundantImport { + #[subdiagnostic] + pub subs: Vec, + + pub ident: Ident, +} + +#[derive(Subdiagnostic)] +pub enum RedundantImportSub { + #[label(lint_label_imported_here)] + ImportedHere(#[primary_span] Span), + #[label(lint_label_defined_here)] + DefinedHere(#[primary_span] Span), + #[label(lint_label_imported_prelude)] + ImportedPrelude(#[primary_span] Span), + #[label(lint_label_defined_prelude)] + DefinedPrelude(#[primary_span] Span), +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_doc_comment)] +#[help] +pub struct UnusedDocComment { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +pub enum PatternsInFnsWithoutBody { + #[diag(lint_pattern_in_foreign)] + Foreign { + #[subdiagnostic] + sub: PatternsInFnsWithoutBodySub, + }, + #[diag(lint_pattern_in_bodiless)] + Bodiless { + #[subdiagnostic] + sub: PatternsInFnsWithoutBodySub, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")] +pub struct PatternsInFnsWithoutBodySub { + #[primary_span] + pub span: Span, + + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_extern_without_abi)] +#[help] +pub struct MissingAbi { + #[label] + pub span: Span, + + pub default_abi: &'static str, +} + +#[derive(LintDiagnostic)] +#[diag(lint_legacy_derive_helpers)] +pub struct LegacyDeriveHelpers { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_proc_macro_back_compat)] +#[note] +pub struct ProcMacroBackCompat { + pub crate_name: String, + pub fixed_version: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_or_patterns_back_compat)] +pub struct OrPatternsBackCompat { + #[suggestion(code = "{suggestion}", applicability = "machine-applicable")] + pub span: Span, + pub suggestion: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_reserved_prefix)] +pub struct ReservedPrefix { + #[label] + pub label: Span, + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, + + pub prefix: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_builtin_attribute)] +pub struct UnusedBuiltinAttribute { + #[note] + pub invoc_span: Span, + + pub attr_name: Symbol, + pub macro_name: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_trailing_semi_macro)] +pub struct TrailingMacro { + #[note(lint_note1)] + #[note(lint_note2)] + pub is_trailing: bool, + + pub name: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_break_with_label_and_loop)] +pub struct BreakWithLabelAndLoop { + #[subdiagnostic] + pub sub: BreakWithLabelAndLoopSub, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +pub struct BreakWithLabelAndLoopSub { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_deprecated_where_clause_location)] +#[note] +pub struct DeprecatedWhereClauseLocation { + #[subdiagnostic] + pub suggestion: DeprecatedWhereClauseLocationSugg, +} + +#[derive(Subdiagnostic)] +pub enum DeprecatedWhereClauseLocationSugg { + #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")] + MoveToEnd { + #[suggestion_part(code = "")] + left: Span, + #[suggestion_part(code = "{sugg}")] + right: Span, + + sugg: String, + }, + #[suggestion(lint_suggestion_remove_where, code = "", applicability = "machine-applicable")] + RemoveWhere { + #[primary_span] + span: Span, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_single_use_lifetime)] +pub struct SingleUseLifetime { + #[label(lint_label_param)] + pub param_span: Span, + #[label(lint_label_use)] + pub use_span: Span, + #[subdiagnostic] + pub suggestion: Option, + + pub ident: Ident, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +pub struct SingleUseLifetimeSugg { + #[suggestion_part(code = "")] + pub deletion_span: Option, + #[suggestion_part(code = "{replace_lt}")] + pub use_span: Span, + + pub replace_lt: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_lifetime)] +pub struct UnusedLifetime { + #[suggestion(code = "", applicability = "machine-applicable")] + pub deletion_span: Option, + + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(lint_named_argument_used_positionally)] +pub struct NamedArgumentUsedPositionally { + #[label(lint_label_named_arg)] + pub named_arg_sp: Span, + #[label(lint_label_position_arg)] + pub position_label_sp: Option, + #[suggestion(style = "verbose", code = "{name}", applicability = "maybe-incorrect")] + pub suggestion: Option, + + pub name: String, + pub named_arg_name: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_byte_slice_in_packed_struct_with_derive)] +#[help] +pub struct ByteSliceInPackedStructWithDerive { + // FIXME: make this translatable + pub ty: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unused_extern_crate)] +pub struct UnusedExternCrate { + #[suggestion(code = "", applicability = "machine-applicable")] + pub removal_span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_extern_crate_not_idiomatic)] +pub struct ExternCrateNotIdiomatic { + #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + pub span: Span, + + pub code: &'static str, +} + +// FIXME: make this translatable +pub struct AmbiguousGlobImports { + pub ambiguity: AmbiguityErrorDiag, +} + +impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports { + fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { + rustc_errors::report_ambiguity_error(diag, self.ambiguity); + } + + fn msg(&self) -> DiagMessage { + DiagMessage::Str(self.ambiguity.msg.clone().into()) + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_ambiguous_glob_reexport)] +pub struct AmbiguousGlobReexports { + #[label(lint_label_first_reexport)] + pub first_reexport: Span, + #[label(lint_label_duplicate_reexport)] + pub duplicate_reexport: Span, + + pub name: String, + // FIXME: make this translatable + pub namespace: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_hidden_glob_reexport)] +pub struct HiddenGlobReexports { + #[note(lint_note_glob_reexport)] + pub glob_reexport: Span, + #[note(lint_note_private_item)] + pub private_item: Span, + + pub name: String, + // FIXME: make this translatable + pub namespace: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unnecessary_qualification)] +pub struct UnusedQualifications { + #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + pub removal_span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_associated_const_elided_lifetime)] +pub struct AssociatedConstElidedLifetime { + #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + pub span: Span, + + pub code: &'static str, + pub elided: bool, +} + +#[derive(LintDiagnostic)] +#[diag(lint_redundant_import_visibility)] +pub struct RedundantImportVisibility { + #[note] + pub span: Span, + #[help] + pub help: (), + + pub import_vis: String, + pub max_vis: String, +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 4dacafaaea699..8f3f6620cfcb6 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; -use rustc_error_messages::MultiSpan; +use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::def::Namespace; use rustc_hir::HashStableContext; use rustc_hir::HirId; @@ -591,8 +591,9 @@ pub enum BuiltinLintDiag { candidate: Option, }, UnusedImports { - fix_msg: String, - fixes: Vec<(Span, String)>, + remove_whole_use: bool, + num_to_remove: usize, + remove_spans: Vec, test_module_span: Option, span_snippets: Vec, }, @@ -617,7 +618,10 @@ pub enum BuiltinLintDiag { is_foreign: bool, }, LegacyDeriveHelpers(Span), - ProcMacroBackCompat(String), + ProcMacroBackCompat { + crate_name: String, + fixed_version: String, + }, OrPatternsBackCompat(Span, String), ReservedPrefix(Span, String), TrailingMacro(bool, Ident), @@ -625,7 +629,7 @@ pub enum BuiltinLintDiag { UnicodeTextFlow(Span, String), UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), - DeprecatedWhereclauseLocation(Option<(Span, String)>), + DeprecatedWhereclauseLocation(Span, Option<(Span, String)>), SingleUseLifetime { /// Span of the parameter which declares this lifetime. param_span: Span, @@ -708,7 +712,7 @@ pub enum BuiltinLintDiag { MacroIsPrivate(Ident), UnusedMacroDefinition(Symbol), MacroRuleNeverUsed(usize, Symbol), - UnstableFeature(String), + UnstableFeature(DiagMessage), AvoidUsingIntelSyntax, AvoidUsingAttSyntax, IncompleteInclude, @@ -722,8 +726,7 @@ pub enum BuiltinLintDiag { MetaVariableWrongOperator, DuplicateMatcherBinding, UnknownMacroVariable(MacroRulesNormalizedIdent), - // FIXME: combine with UnusedExternCrate? - UnusedExternCrate2 { + UnusedCrateDependency { extern_crate: Symbol, local_crate: Symbol, }, diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 394222cdb3573..770088e05f9bb 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -978,7 +978,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, - BuiltinLintDiag::UnusedExternCrate2 { + BuiltinLintDiag::UnusedCrateDependency { extern_crate: name_interned, local_crate: self.tcx.crate_name(LOCAL_CRATE), }, diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 37d2c6a707854..0451ab4a06b29 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -154,19 +154,6 @@ pub struct Deprecated { pub since_kind: DeprecatedSinceKind, } -impl Deprecated { - // FIXME: remove - pub fn msg_for_since_kind(since_kind: &DeprecatedSinceKind) -> rustc_errors::DiagMessage { - match since_kind { - DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated, - DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future, - DeprecatedSinceKind::InVersion(_) => { - crate::fluent_generated::middle_deprecated_in_version - } - } - } -} - impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { diag.arg("kind", self.kind); @@ -186,7 +173,13 @@ impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecate } fn msg(&self) -> rustc_errors::DiagMessage { - Self::msg_for_since_kind(&self.since_kind) + match &self.since_kind { + DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated, + DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future, + DeprecatedSinceKind::InVersion(_) => { + crate::fluent_generated::middle_deprecated_in_version + } + } } } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 55b2d91260e9e..93b53f510fca3 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -433,20 +433,12 @@ impl Resolver<'_, '_> { visitor.report_unused_extern_crate_items(maybe_unused_extern_crates); for unused in visitor.unused_imports.values() { - let mut fixes = Vec::new(); - let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { - UnusedSpanResult::Used => continue, - UnusedSpanResult::Unused { spans, remove } => { - fixes.push((remove, String::new())); - spans - } - UnusedSpanResult::PartialUnused { spans, remove } => { - for fix in &remove { - fixes.push((*fix, String::new())); - } - spans - } - }; + let (spans, remove_spans) = + match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { + UnusedSpanResult::Used => continue, + UnusedSpanResult::Unused { spans, remove } => (spans, vec![remove]), + UnusedSpanResult::PartialUnused { spans, remove } => (spans, remove), + }; let ms = MultiSpan::from_spans(spans); @@ -458,13 +450,8 @@ impl Resolver<'_, '_> { .collect::>(); span_snippets.sort(); - let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span { - "remove the whole `use` item" - } else if ms.primary_spans().len() > 1 { - "remove the unused imports" - } else { - "remove the unused import" - }; + let remove_whole_use = remove_spans.len() == 1 && remove_spans[0] == unused.item_span; + let num_to_remove = ms.primary_spans().len(); // If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]` // attribute; however, if not, suggest adding the attribute. There is no way to @@ -495,8 +482,9 @@ impl Resolver<'_, '_> { unused.use_tree_id, ms, BuiltinLintDiag::UnusedImports { - fix_msg: fix_msg.into(), - fixes, + remove_whole_use, + num_to_remove, + remove_spans, test_module_span, span_snippets, }, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 74f55d0a19ced..f7073ee9a01f2 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -847,7 +847,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { lint, node_id, span, - BuiltinLintDiag::UnstableFeature(msg), + BuiltinLintDiag::UnstableFeature( + // FIXME make this translatable + msg.into(), + ), ) }; stability::report_unstable( diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index bd3b69c2b4a6a..ca60bc62b5183 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -45,7 +45,7 @@ mod inline { //~| NOTE not a function or closure #[inline = "2100"] fn f() { } - //~^ ERROR attribute must be of the form + //~^ ERROR valid forms for the attribute are //~| WARN this was previously accepted //~| NOTE #[deny(ill_formed_attribute_input)]` on by default //~| NOTE for more information, see issue #57571 diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 89fa2abffc2fc..ac2bf78157d27 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -7,7 +7,7 @@ LL | #![rustc_main] = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: attribute must be of the form `#[inline]` or `#[inline(always|never)]` +error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]` --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:47:5 | LL | #[inline = "2100"] fn f() { } diff --git a/tests/ui/lint/anonymous-reexport.stderr b/tests/ui/lint/anonymous-reexport.stderr index e3854a5459ec0..c4ee18fe8da2a 100644 --- a/tests/ui/lint/anonymous-reexport.stderr +++ b/tests/ui/lint/anonymous-reexport.stderr @@ -34,7 +34,7 @@ error: unused import: `Bar as _` LL | pub use self::my_mod::{Bar as _, Foo as _}; | ^^^^^^^^ -error: unused imports: `Bar as _`, `TyBar as _` +error: unused imports: `Bar as _` and `TyBar as _` --> $DIR/anonymous-reexport.rs:17:24 | LL | pub use self::my_mod::{Bar as _, TyBar as _}; diff --git a/tests/ui/lint/unused/import_remove_line.stderr b/tests/ui/lint/unused/import_remove_line.stderr index 0e8c5de3558e5..b2a16669a9398 100644 --- a/tests/ui/lint/unused/import_remove_line.stderr +++ b/tests/ui/lint/unused/import_remove_line.stderr @@ -1,4 +1,4 @@ -warning: unused imports: `Duration`, `Instant` +warning: unused imports: `Duration` and `Instant` --> $DIR/import_remove_line.rs:7:17 | LL | use std::time::{Duration, Instant}; diff --git a/tests/ui/lint/unused/lint-unused-imports.rs b/tests/ui/lint/unused/lint-unused-imports.rs index 88f2baa5da9b3..710fb7a5ed12a 100644 --- a/tests/ui/lint/unused/lint-unused-imports.rs +++ b/tests/ui/lint/unused/lint-unused-imports.rs @@ -10,7 +10,7 @@ use std::fmt::{}; // Should get errors for both 'Some' and 'None' use std::option::Option::{Some, None}; -//~^ ERROR unused imports: `None`, `Some` +//~^ ERROR unused imports: `None` and `Some` use test::A; //~ ERROR unused import: `test::A` // Be sure that if we just bring some methods into scope that they're also diff --git a/tests/ui/lint/unused/lint-unused-imports.stderr b/tests/ui/lint/unused/lint-unused-imports.stderr index 07684a84a64ff..a848fb31ebaba 100644 --- a/tests/ui/lint/unused/lint-unused-imports.stderr +++ b/tests/ui/lint/unused/lint-unused-imports.stderr @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #![deny(unused_imports)] | ^^^^^^^^^^^^^^ -error: unused imports: `None`, `Some` +error: unused imports: `None` and `Some` --> $DIR/lint-unused-imports.rs:12:27 | LL | use std::option::Option::{Some, None}; diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs index ac1444bbaef4e..f0a7aac59c1cc 100644 --- a/tests/ui/malformed/malformed-regressions.rs +++ b/tests/ui/malformed/malformed-regressions.rs @@ -1,8 +1,8 @@ -#[doc] //~ ERROR attribute must be of the form +#[doc] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted -#[ignore()] //~ ERROR attribute must be of the form +#[ignore()] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted -#[inline = ""] //~ ERROR attribute must be of the form +#[inline = ""] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted #[link] //~ ERROR attribute must be of the form //~^ WARN this was previously accepted diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index 9bfbe7ebafd76..e1dbdb9ab3c66 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -1,4 +1,4 @@ -error: attribute must be of the form `#[doc(hidden|inline|...)]` or `#[doc = "string"]` +error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` --> $DIR/malformed-regressions.rs:1:1 | LL | #[doc] @@ -8,7 +8,7 @@ LL | #[doc] = note: for more information, see issue #57571 = note: `#[deny(ill_formed_attribute_input)]` on by default -error: attribute must be of the form `#[ignore]` or `#[ignore = "reason"]` +error: valid forms for the attribute are `#[ignore]` and `#[ignore = "reason"]` --> $DIR/malformed-regressions.rs:3:1 | LL | #[ignore()] @@ -17,7 +17,7 @@ LL | #[ignore()] = 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 #57571 -error: attribute must be of the form `#[inline]` or `#[inline(always|never)]` +error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]` --> $DIR/malformed-regressions.rs:5:1 | LL | #[inline = ""] diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs index 653dcab577148..796ba4d233201 100644 --- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs @@ -6,7 +6,7 @@ mod rank { pub use self::Lieutenant::{JuniorGrade, Full}; //~^ ERROR `JuniorGrade` is private, and cannot be re-exported //~| ERROR `Full` is private, and cannot be re-exported - //~| ERROR unused imports: `Full`, `JuniorGrade` + //~| ERROR unused imports: `Full` and `JuniorGrade` pub use self::PettyOfficer::*; //~^ ERROR glob import doesn't reexport anything //~| ERROR unused import: `self::PettyOfficer::*` diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr index 93a39edbb8232..f1701d547a62f 100644 --- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr @@ -46,7 +46,7 @@ error: unused import: `self::Professor::*` LL | pub use self::Professor::*; | ^^^^^^^^^^^^^^^^^^ -error: unused imports: `Full`, `JuniorGrade` +error: unused imports: `Full` and `JuniorGrade` --> $DIR/issue-46209-private-enum-variant-reexport.rs:6:32 | LL | pub use self::Lieutenant::{JuniorGrade, Full}; diff --git a/tests/ui/span/multispan-import-lint.stderr b/tests/ui/span/multispan-import-lint.stderr index 4a955d1b31f58..a4ea1af237bdd 100644 --- a/tests/ui/span/multispan-import-lint.stderr +++ b/tests/ui/span/multispan-import-lint.stderr @@ -1,4 +1,4 @@ -warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd` +warning: unused imports: `Eq`, `Ord`, `PartialEq`, and `PartialOrd` --> $DIR/multispan-import-lint.rs:5:16 | LL | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; diff --git a/tests/ui/suggestions/unused-imports.stderr b/tests/ui/suggestions/unused-imports.stderr index bf112608da7ed..31edb4e5ec20d 100644 --- a/tests/ui/suggestions/unused-imports.stderr +++ b/tests/ui/suggestions/unused-imports.stderr @@ -1,4 +1,4 @@ -warning: unused imports: `A`, `C` +warning: unused imports: `A` and `C` --> $DIR/unused-imports.rs:22:14 | LL | use nested::{A, B, C}; @@ -10,7 +10,7 @@ note: the lint level is defined here LL | #![warn(unused_imports)] | ^^^^^^^^^^^^^^ -warning: unused imports: `D`, `E`, `G` +warning: unused imports: `D`, `E`, and `G` --> $DIR/unused-imports.rs:26:5 | LL | D, diff --git a/tests/ui/use/use-nested-groups-unused-imports.rs b/tests/ui/use/use-nested-groups-unused-imports.rs index ca6b8ba94d1ca..0c8ae558a5971 100644 --- a/tests/ui/use/use-nested-groups-unused-imports.rs +++ b/tests/ui/use/use-nested-groups-unused-imports.rs @@ -13,7 +13,7 @@ mod foo { } use foo::{Foo, bar::{baz::{}, foobar::*}, *}; - //~^ ERROR unused imports: `*`, `Foo`, `baz::{}`, `foobar::*` + //~^ ERROR unused imports: `*`, `Foo`, `baz::{}`, and `foobar::*` use foo::bar::baz::{*, *}; //~^ ERROR unused import: `*` use foo::{}; diff --git a/tests/ui/use/use-nested-groups-unused-imports.stderr b/tests/ui/use/use-nested-groups-unused-imports.stderr index 6610f8ecd4a28..dd39a852772c0 100644 --- a/tests/ui/use/use-nested-groups-unused-imports.stderr +++ b/tests/ui/use/use-nested-groups-unused-imports.stderr @@ -1,4 +1,4 @@ -error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*` +error: unused imports: `*`, `Foo`, `baz::{}`, and `foobar::*` --> $DIR/use-nested-groups-unused-imports.rs:15:11 | LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *}; From c4f6502c6d0a31383d5b0f3280d97388897980d4 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 11 Apr 2024 17:46:00 +0000 Subject: [PATCH 11/12] Fix typo in deprecation lint message --- compiler/rustc_lint/messages.ftl | 4 ++-- .../future-compat-crate-attributes-using-cfg_attr.stderr | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 0cd6f1caebff8..6f6480a496413 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -193,10 +193,10 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i .other_use = other identifier used here lint_crate_name_in_cfg_attr_deprecated = - `crate_name` within an `#![cfg_attr] attribute is deprecated` + `crate_name` within an `#![cfg_attr]` attribute is deprecated lint_crate_type_in_cfg_attr_deprecated = - `crate_type` within an `#![cfg_attr] attribute is deprecated` + `crate_type` within an `#![cfg_attr]` attribute is deprecated lint_cstring_ptr = getting the inner pointer of a temporary `CString` .as_ptr_label = this pointer will be invalid diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr index 75df314e0baa7..82b2d7d1b1da6 100644 --- a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr +++ b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr @@ -1,4 +1,4 @@ -error: `crate_type` within an `#![cfg_attr] attribute is deprecated` +error: `crate_type` within an `#![cfg_attr]` attribute is deprecated --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18 | LL | #![cfg_attr(foo, crate_type="bin")] @@ -8,7 +8,7 @@ LL | #![cfg_attr(foo, crate_type="bin")] = note: for more information, see issue #91632 = note: `#[deny(deprecated_cfg_attr_crate_type_name)]` on by default -error: `crate_name` within an `#![cfg_attr] attribute is deprecated` +error: `crate_name` within an `#![cfg_attr]` attribute is deprecated --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 | LL | #![cfg_attr(foo, crate_name="bar")] @@ -17,7 +17,7 @@ LL | #![cfg_attr(foo, crate_name="bar")] = 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 #91632 -error: `crate_type` within an `#![cfg_attr] attribute is deprecated` +error: `crate_type` within an `#![cfg_attr]` attribute is deprecated --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18 | LL | #![cfg_attr(foo, crate_type="bin")] @@ -27,7 +27,7 @@ LL | #![cfg_attr(foo, crate_type="bin")] = note: for more information, see issue #91632 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: `crate_name` within an `#![cfg_attr] attribute is deprecated` +error: `crate_name` within an `#![cfg_attr]` attribute is deprecated --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 | LL | #![cfg_attr(foo, crate_name="bar")] From 98dd6c7e8f33966221216200182175672294a719 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Mon, 20 May 2024 17:47:54 +0000 Subject: [PATCH 12/12] Rename buffer_lint_with_diagnostic to buffer_lint --- compiler/rustc_ast_passes/src/ast_validation.rs | 6 +++--- compiler/rustc_attr/src/builtin.rs | 4 ++-- compiler/rustc_builtin_macros/src/asm.rs | 4 ++-- .../rustc_builtin_macros/src/deriving/generic/mod.rs | 2 +- compiler/rustc_builtin_macros/src/source_util.rs | 2 +- compiler/rustc_builtin_macros/src/test_harness.rs | 2 +- compiler/rustc_builtin_macros/src/util.rs | 2 +- compiler/rustc_expand/src/base.rs | 2 +- compiler/rustc_expand/src/config.rs | 6 +++--- compiler/rustc_expand/src/expand.rs | 4 ++-- compiler/rustc_expand/src/mbe/macro_check.rs | 4 ++-- compiler/rustc_expand/src/mbe/macro_rules.rs | 4 ++-- compiler/rustc_interface/src/util.rs | 2 +- compiler/rustc_lint_defs/src/lib.rs | 2 +- compiler/rustc_metadata/src/creader.rs | 4 ++-- compiler/rustc_middle/src/middle/stability.rs | 2 +- compiler/rustc_parse/src/lexer/mod.rs | 4 ++-- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/validate_attr.rs | 2 +- compiler/rustc_resolve/src/check_unused.rs | 12 ++++++------ compiler/rustc_resolve/src/diagnostics.rs | 6 +++--- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 8 ++++---- compiler/rustc_resolve/src/late.rs | 6 +++--- compiler/rustc_resolve/src/late/diagnostics.rs | 4 ++-- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 12 ++++++------ compiler/rustc_session/src/parse.rs | 2 +- 28 files changed, 57 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b1158dc6fcafe..c57be3cdf3532 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -765,7 +765,7 @@ impl<'a> AstValidator<'a> { .span_to_snippet(span) .is_ok_and(|snippet| !snippet.starts_with("#[")) { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( MISSING_ABI, id, span, @@ -1426,7 +1426,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) { if let Some(ident) = ident { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( PATTERNS_IN_FNS_WITHOUT_BODY, id, span, @@ -1506,7 +1506,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { Some((right, snippet)) } }; - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( DEPRECATED_WHERE_CLAUSE_LOCATION, item.id, err.span, diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 1ac2e15c32758..5113c5adc8f7a 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -528,7 +528,7 @@ pub fn cfg_matches( try_gate_cfg(cfg.name, cfg.span, sess, features); match sess.psess.check_config.expecteds.get(&cfg.name) { Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => { - sess.psess.buffer_lint_with_diagnostic( + sess.psess.buffer_lint( UNEXPECTED_CFGS, cfg.span, lint_node_id, @@ -539,7 +539,7 @@ pub fn cfg_matches( ); } None if sess.psess.check_config.exhaustive_names => { - sess.psess.buffer_lint_with_diagnostic( + sess.psess.buffer_lint( UNEXPECTED_CFGS, cfg.span, lint_node_id, diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index bf2a5813af60b..1a7961bf70c11 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -510,7 +510,7 @@ fn expand_preparsed_asm( }; if template_str.contains(".intel_syntax") { - ecx.psess().buffer_lint_with_diagnostic( + ecx.psess().buffer_lint( lint::builtin::BAD_ASM_STYLE, find_span(".intel_syntax"), ecx.current_expansion.lint_node_id, @@ -518,7 +518,7 @@ fn expand_preparsed_asm( ); } if template_str.contains(".att_syntax") { - ecx.psess().buffer_lint_with_diagnostic( + ecx.psess().buffer_lint( lint::builtin::BAD_ASM_STYLE, find_span(".att_syntax"), ecx.current_expansion.lint_node_id, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 18dca4b2615db..217fa5ff9f1e5 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1621,7 +1621,7 @@ impl<'a> TraitDef<'a> { }; if let Some(ty) = exception { - cx.sess.psess.buffer_lint_with_diagnostic( + cx.sess.psess.buffer_lint( BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE, sp, ast::CRATE_NODE_ID, diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 15d2546ba8669..29e991525a9be 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -144,7 +144,7 @@ pub(crate) fn expand_include<'cx>( fn make_expr(mut self: Box>) -> Option> { let expr = parse_expr(&mut self.p).ok()?; if self.p.token != token::Eof { - self.p.psess.buffer_lint_with_diagnostic( + self.p.psess.buffer_lint( INCOMPLETE_INCLUDE, self.p.token.span, self.node_id, diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index f6c35a75228a5..38ac2f15fe757 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -160,7 +160,7 @@ struct InnerItemLinter<'a> { impl<'a> Visitor<'a> for InnerItemLinter<'_> { fn visit_item(&mut self, i: &'a ast::Item) { if let Some(attr) = attr::find_by_name(&i.attrs, sym::rustc_test_marker) { - self.sess.psess.buffer_lint_with_diagnostic( + self.sess.psess.buffer_lint( UNNAMEABLE_TEST_ITEMS, attr.span, i.id, diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index f08238ad46061..652e34268ea92 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -42,7 +42,7 @@ pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, }; if let Some(attrs) = attrs { if let Some(attr) = attr::find_by_name(attrs, name) { - ecx.psess().buffer_lint_with_diagnostic( + ecx.psess().buffer_lint( DUPLICATE_MACRO_ATTRIBUTES, attr.span, ecx.current_expansion.lint_node_id, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 77db801c76f38..91af8758e5167 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1364,7 +1364,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { }; if crate_matches { - sess.psess.buffer_lint_with_diagnostic( + sess.psess.buffer_lint( PROC_MACRO_BACK_COMPAT, item.ident.span, ast::CRATE_NODE_ID, diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 45d87d5e5a5eb..badfa6d3aa323 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -258,7 +258,7 @@ impl<'a> StripUnconfigured<'a> { // Lint on zero attributes in source. if expanded_attrs.is_empty() { - self.sess.psess.buffer_lint_with_diagnostic( + self.sess.psess.buffer_lint( rustc_lint_defs::builtin::UNUSED_ATTRIBUTES, attr.span, ast::CRATE_NODE_ID, @@ -341,7 +341,7 @@ impl<'a> StripUnconfigured<'a> { item_span, ); if attr.has_name(sym::crate_type) { - self.sess.psess.buffer_lint_with_diagnostic( + self.sess.psess.buffer_lint( rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, attr.span, ast::CRATE_NODE_ID, @@ -349,7 +349,7 @@ impl<'a> StripUnconfigured<'a> { ); } if attr.has_name(sym::crate_name) { - self.sess.psess.buffer_lint_with_diagnostic( + self.sess.psess.buffer_lint( rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, attr.span, ast::CRATE_NODE_ID, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 02e4f5e0f9e11..d8f0f221189ad 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1799,7 +1799,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } if attr.is_doc_comment() { - self.cx.sess.psess.buffer_lint_with_diagnostic( + self.cx.sess.psess.buffer_lint( UNUSED_DOC_COMMENTS, current_span, self.cx.current_expansion.lint_node_id, @@ -1810,7 +1810,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // `#[cfg]` and `#[cfg_attr]` are special - they are // eagerly evaluated. if attr_name != sym::cfg && attr_name != sym::cfg_attr { - self.cx.sess.psess.buffer_lint_with_diagnostic( + self.cx.sess.psess.buffer_lint( UNUSED_ATTRIBUTES, attr.span, self.cx.current_expansion.lint_node_id, diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 63eeefa314c30..72dbbde54b310 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -268,7 +268,7 @@ 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_with_diagnostic( + psess.buffer_lint( MISSING_FRAGMENT_SPECIFIER, span, node_id, @@ -646,6 +646,6 @@ fn ops_is_prefix( fn buffer_lint(psess: &ParseSess, span: MultiSpan, node_id: NodeId, diag: BuiltinLintDiag) { // Macros loaded from other crates have dummy node ids. if node_id != DUMMY_NODE_ID { - psess.buffer_lint_with_diagnostic(META_VARIABLE_MISUSE, span, node_id, diag); + psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, diag); } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index fee7ba099aade..d99ecb6108520 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -79,7 +79,7 @@ impl<'a> ParserAnyMacro<'a> { // but `m!()` is allowed in expression positions (cf. issue #34706). if kind == AstFragmentKind::Expr && parser.token == token::Semi { if is_local { - parser.psess.buffer_lint_with_diagnostic( + parser.psess.buffer_lint( SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, parser.token.span, lint_node_id, @@ -1153,7 +1153,7 @@ fn check_matcher_core<'tt>( name, Some(NonterminalKind::PatParam { inferred: false }), )); - sess.psess.buffer_lint_with_diagnostic( + sess.psess.buffer_lint( RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, ast::CRATE_NODE_ID, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index cb25bcac36850..987e48a1a76ff 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -404,7 +404,7 @@ pub(crate) fn check_attr_crate_type( n, None, ); - lint_buffer.buffer_lint_with_diagnostic( + lint_buffer.buffer_lint( lint::builtin::UNKNOWN_CRATE_TYPES, ast::CRATE_NODE_ID, span, diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 8f3f6620cfcb6..1941b0b12643f 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -784,7 +784,7 @@ impl LintBuffer { self.map.swap_remove(&id).unwrap_or_default() } - pub fn buffer_lint_with_diagnostic( + pub fn buffer_lint( &mut self, lint: &'static Lint, id: NodeId, diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 770088e05f9bb..be1a73ef0a7d9 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -974,7 +974,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { continue; } - self.sess.psess.buffer_lint_with_diagnostic( + self.sess.psess.buffer_lint( lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, @@ -1015,7 +1015,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); - self.sess.psess.buffer_lint_with_diagnostic( + self.sess.psess.buffer_lint( lint::builtin::WASM_C_ABI, span, ast::CRATE_NODE_ID, diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 0451ab4a06b29..e5df05763b022 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -220,7 +220,7 @@ pub fn early_report_macro_deprecation( path, since_kind: deprecated_since_kind(is_in_effect, depr.since.clone()), }; - lint_buffer.buffer_lint_with_diagnostic(deprecation_lint(is_in_effect), node_id, span, diag); + lint_buffer.buffer_lint(deprecation_lint(is_in_effect), node_id, span, diag); } fn late_report_deprecation( diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index cdb1cf62cf782..6eb8bed6a8c4e 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -370,7 +370,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let content = self.str_from(content_start); if contains_text_flow_control_chars(content) { let span = self.mk_sp(start, self.pos); - self.psess.buffer_lint_with_diagnostic( + self.psess.buffer_lint( TEXT_DIRECTION_CODEPOINT_IN_COMMENT, span, ast::CRATE_NODE_ID, @@ -722,7 +722,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { self.dcx().emit_err(errors::UnknownPrefix { span: prefix_span, prefix, sugg }); } else { // Before Rust 2021, only emit a lint for migration. - self.psess.buffer_lint_with_diagnostic( + self.psess.buffer_lint( RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, prefix_span, ast::CRATE_NODE_ID, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index be4a52a9bc4e6..fd3f63a04de55 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1913,7 +1913,7 @@ impl<'a> Parser<'a> { | ExprKind::Block(_, None) ) { - self.psess.buffer_lint_with_diagnostic( + self.psess.buffer_lint( BREAK_WITH_LABEL_AND_LOOP, lo.to(expr.span), ast::CRATE_NODE_ID, diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 3cfc68507d5aa..b91ef1ae1f320 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -189,7 +189,7 @@ fn emit_malformed_attribute( suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); } if should_warn(name) { - psess.buffer_lint_with_diagnostic( + psess.buffer_lint( ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 93b53f510fca3..fc3669fecc2ad 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -151,7 +151,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { // We do this in any edition. if warn_if_unused { if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) { - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( UNUSED_EXTERN_CRATES, extern_crate.id, span, @@ -203,7 +203,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { .span .find_ancestor_inside(extern_crate.span) .unwrap_or(extern_crate.ident.span); - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( UNUSED_EXTERN_CRATES, extern_crate.id, extern_crate.span, @@ -388,7 +388,7 @@ impl Resolver<'_, '_> { { if let ImportKind::MacroUse { .. } = import.kind { if !import.span.is_dummy() { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( MACRO_USE_EXTERN_CRATE, import.root_id, import.span, @@ -409,7 +409,7 @@ impl Resolver<'_, '_> { } } ImportKind::MacroUse { .. } => { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( UNUSED_IMPORTS, import.root_id, import.span, @@ -477,7 +477,7 @@ impl Resolver<'_, '_> { } }; - visitor.r.lint_buffer.buffer_lint_with_diagnostic( + visitor.r.lint_buffer.buffer_lint( UNUSED_IMPORTS, unused.use_tree_id, ms, @@ -533,7 +533,7 @@ impl Resolver<'_, '_> { continue; } - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( UNUSED_QUALIFICATIONS, unn_qua.node_id, unn_qua.path_span, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 791d777b3d447..856cfbc01e8cd 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -128,7 +128,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.report_with_use_injections(krate); for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, CRATE_NODE_ID, span_use, @@ -142,7 +142,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else { unreachable!() }; - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( AMBIGUOUS_GLOB_IMPORTS, import.root_id, ambiguity_error.ident.span, @@ -522,7 +522,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let diag = BuiltinLintDiag::AbsPathWithModule(root_span); - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, node_id, root_span, diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index d1fd19e9953e0..57db765c07e55 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -524,7 +524,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match binding { Ok(binding) => { if let Some(lint_id) = derive_fallback_lint_id { - this.lint_buffer.buffer_lint_with_diagnostic( + this.lint_buffer.buffer_lint( PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, lint_id, orig_ident.span, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index fb734895049cc..51b87c5a9b038 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -619,7 +619,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && binding.res() != Res::Err && exported_ambiguities.contains(&binding) { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( AMBIGUOUS_GLOB_REEXPORTS, import.root_id, import.root_span, @@ -654,7 +654,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && glob_binding.vis.is_public() && !binding.vis.is_public() { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( HIDDEN_GLOB_REEXPORTS, binding_id, binding.span, @@ -1013,7 +1013,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && !max_vis.is_at_least(import_vis, self.tcx) { let def_id = self.local_def_id(id); - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( UNUSED_IMPORTS, id, import.span, @@ -1246,7 +1246,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !any_successful_reexport { let (ns, binding) = reexport_error.unwrap(); if pub_use_of_private_extern_crate_hack(import, binding) { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( PUB_USE_OF_PRIVATE_EXTERN_CRATE, import_id, import.span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 359e96775f8d0..d1d0e336cfe05 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1675,7 +1675,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { return; } LifetimeRibKind::AnonymousWarn(node_id) => { - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, node_id, lifetime.ident.span, @@ -1960,7 +1960,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } if should_lint { - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( lint::builtin::ELIDED_LIFETIMES_IN_PATHS, segment_id, elided_lifetime_span, @@ -4815,7 +4815,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( lint::builtin::UNUSED_LABELS, *id, *span, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ce14c98b0d615..cb063e370a3cc 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2651,7 +2651,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let deletion_span = if param.bounds.is_empty() { deletion_span() } else { None }; - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( lint::builtin::SINGLE_USE_LIFETIMES, param.id, param.ident.span, @@ -2669,7 +2669,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { // if the lifetime originates from expanded code, we won't be able to remove it #104432 if deletion_span.is_some_and(|sp| !sp.in_derive_expansion()) { - self.r.lint_buffer.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint( lint::builtin::UNUSED_LIFETIMES, param.id, param.ident.span, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dda31f82d2fdf..f4c5ad8f6721a 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1860,7 +1860,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let NameBindingKind::Import { import, binding } = used_binding.kind { if let ImportKind::MacroUse { warn_private: true } = import.kind { - self.lint_buffer().buffer_lint_with_diagnostic( + self.lint_buffer().buffer_lint( PRIVATE_MACRO_USE, import.root_id, ident.span, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index f7073ee9a01f2..092eb1ce2eed6 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -311,7 +311,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { fn check_unused_macros(&mut self) { for (_, &(node_id, ident)) in self.unused_macros.iter() { - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( UNUSED_MACROS, node_id, ident.span, @@ -324,7 +324,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { continue; } let node_id = self.def_id_to_node_id[def_id]; - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( UNUSED_MACRO_RULES, node_id, rule_span, @@ -558,7 +558,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => unreachable!(), }; if soft_custom_inner_attributes_gate { - self.tcx.sess.psess.buffer_lint_with_diagnostic( + self.tcx.sess.psess.buffer_lint( SOFT_UNSTABLE, path.span, node_id, @@ -585,7 +585,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let typo_name = distance.map(|_| sym::on_unimplemented); - self.tcx.sess.psess.buffer_lint_with_diagnostic( + self.tcx.sess.psess.buffer_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, attribute.span(), node_id, @@ -789,7 +789,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .invocation_parents .get(&parent_scope.expansion) .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]); - self.lint_buffer.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint( LEGACY_DERIVE_HELPERS, node_id, ident.span, @@ -843,7 +843,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !is_allowed(feature) && !allowed_by_implication { let lint_buffer = &mut self.lint_buffer; let soft_handler = |lint, span, msg: String| { - lint_buffer.buffer_lint_with_diagnostic( + lint_buffer.buffer_lint( lint, node_id, span, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 3db586622e594..df07f81bc4573 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -300,7 +300,7 @@ impl ParseSess { self.source_map.clone() } - pub fn buffer_lint_with_diagnostic( + pub fn buffer_lint( &self, lint: &'static Lint, span: impl Into,