X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_lint%2Fsrc%2Flints.rs;h=2e447b900e1174b79ed142bb3c1cbf0d664e34ba;hb=00efb0cb960e4b89a80cad7d44fa0eefd223f513;hp=196922b78c30c35f331c77eb315684e3e554c767;hpb=0b19227524622d953fbaefa272b36b0ef2fa263e;p=rust.git diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 196922b78c3..2e447b900e1 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,10 +1,20 @@ -use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage}; +#![allow(rustc::untranslatable_diagnostic)] +#![allow(rustc::diagnostic_outside_of_impl)] +use std::num::NonZeroU32; + +use rustc_errors::{ + fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, + DiagnosticStyledString, SuggestionStyle, +}; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{Predicate, Ty, TyCtxt}; -use rustc_span::{symbol::Ident, Span, Symbol}; +use rustc_session::parse::ParseSess; +use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol}; -use crate::{errors::OverruledAttributeSub, LateContext}; +use crate::{ + builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext, +}; // array_into_iter.rs #[derive(LintDiagnostic)] @@ -33,6 +43,532 @@ pub enum ArrayIntoIterDiagSub { }, } +// builtin.rs +#[derive(LintDiagnostic)] +#[diag(lint_builtin_while_true)] +pub struct BuiltinWhileTrue { + #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] + pub suggestion: Span, + pub replace: String, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_box_pointers)] +pub struct BuiltinBoxPointers<'a> { + pub ty: Ty<'a>, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_non_shorthand_field_patterns)] +pub struct BuiltinNonShorthandFieldPatterns { + pub ident: Ident, + #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")] + pub suggestion: Span, + pub prefix: &'static str, +} + +#[derive(LintDiagnostic)] +pub enum BuiltinUnsafe { + #[diag(lint_builtin_allow_internal_unsafe)] + AllowInternalUnsafe, + #[diag(lint_builtin_unsafe_block)] + UnsafeBlock, + #[diag(lint_builtin_unsafe_trait)] + UnsafeTrait, + #[diag(lint_builtin_unsafe_impl)] + UnsafeImpl, + #[diag(lint_builtin_no_mangle_fn)] + #[note(lint_builtin_overridden_symbol_name)] + NoMangleFn, + #[diag(lint_builtin_export_name_fn)] + #[note(lint_builtin_overridden_symbol_name)] + ExportNameFn, + #[diag(lint_builtin_link_section_fn)] + #[note(lint_builtin_overridden_symbol_section)] + LinkSectionFn, + #[diag(lint_builtin_no_mangle_static)] + #[note(lint_builtin_overridden_symbol_name)] + NoMangleStatic, + #[diag(lint_builtin_export_name_static)] + #[note(lint_builtin_overridden_symbol_name)] + ExportNameStatic, + #[diag(lint_builtin_link_section_static)] + #[note(lint_builtin_overridden_symbol_section)] + LinkSectionStatic, + #[diag(lint_builtin_no_mangle_method)] + #[note(lint_builtin_overridden_symbol_name)] + NoMangleMethod, + #[diag(lint_builtin_export_name_method)] + #[note(lint_builtin_overridden_symbol_name)] + ExportNameMethod, + #[diag(lint_builtin_decl_unsafe_fn)] + DeclUnsafeFn, + #[diag(lint_builtin_decl_unsafe_method)] + DeclUnsafeMethod, + #[diag(lint_builtin_impl_unsafe_method)] + ImplUnsafeMethod, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_missing_doc)] +pub struct BuiltinMissingDoc<'a> { + pub article: &'a str, + pub desc: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_missing_copy_impl)] +pub struct BuiltinMissingCopyImpl; + +pub struct BuiltinMissingDebugImpl<'a> { + pub tcx: TyCtxt<'a>, + pub def_id: DefId, +} + +// Needed for def_path_str +impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.set_arg("debug", self.tcx.def_path_str(self.def_id)); + diag + } + + fn msg(&self) -> DiagnosticMessage { + fluent::lint_builtin_missing_debug_impl + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_anonymous_params)] +pub struct BuiltinAnonymousParams<'a> { + #[suggestion(code = "_: {ty_snip}")] + pub suggestion: (Span, Applicability), + pub ty_snip: &'a str, +} + +// FIXME(davidtwco) translatable deprecated attr +#[derive(LintDiagnostic)] +#[diag(lint_builtin_deprecated_attr_link)] +pub struct BuiltinDeprecatedAttrLink<'a> { + pub name: Symbol, + pub reason: &'a str, + pub link: &'a str, + #[subdiagnostic] + pub suggestion: BuiltinDeprecatedAttrLinkSuggestion<'a>, +} + +#[derive(Subdiagnostic)] +pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> { + #[suggestion(msg_suggestion, code = "", applicability = "machine-applicable")] + Msg { + #[primary_span] + suggestion: Span, + msg: &'a str, + }, + #[suggestion(default_suggestion, code = "", applicability = "machine-applicable")] + Default { + #[primary_span] + suggestion: Span, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_deprecated_attr_used)] +pub struct BuiltinDeprecatedAttrUsed { + pub name: String, + #[suggestion( + lint_builtin_deprecated_attr_default_suggestion, + style = "short", + code = "", + applicability = "machine-applicable" + )] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unused_doc_comment)] +pub struct BuiltinUnusedDocComment<'a> { + pub kind: &'a str, + #[label] + pub label: Span, + #[subdiagnostic] + pub sub: BuiltinUnusedDocCommentSub, +} + +#[derive(Subdiagnostic)] +pub enum BuiltinUnusedDocCommentSub { + #[help(plain_help)] + PlainHelp, + #[help(block_help)] + BlockHelp, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_no_mangle_generic)] +pub struct BuiltinNoMangleGeneric { + // Use of `#[no_mangle]` suggests FFI intent; correct + // fix may be to monomorphize source by hand + #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_const_no_mangle)] +pub struct BuiltinConstNoMangle { + #[suggestion(code = "pub static", applicability = "machine-applicable")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_mutable_transmutes)] +pub struct BuiltinMutablesTransmutes; + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unstable_features)] +pub struct BuiltinUnstableFeatures; + +// lint_ungated_async_fn_track_caller +pub struct BuiltinUngatedAsyncFnTrackCaller<'a> { + pub label: Span, + pub parse_sess: &'a ParseSess, +} + +impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.span_label(self.label, fluent::label); + rustc_session::parse::add_feature_diagnostics( + diag, + &self.parse_sess, + sym::closure_track_caller, + ); + diag + } + + fn msg(&self) -> DiagnosticMessage { + fluent::lint_ungated_async_fn_track_caller + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unreachable_pub)] +pub struct BuiltinUnreachablePub<'a> { + pub what: &'a str, + #[suggestion(code = "pub(crate)")] + pub suggestion: (Span, Applicability), + #[help] + pub help: Option<()>, +} + +pub struct SuggestChangingAssocTypes<'a, 'b> { + pub ty: &'a rustc_hir::Ty<'b>, +} + +impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + // Access to associates types should use `::Assoc`, which does not need a + // bound. Let's see if this type does that. + + // We use a HIR visitor to walk the type. + use rustc_hir::intravisit::{self, Visitor}; + struct WalkAssocTypes<'a> { + err: &'a mut rustc_errors::Diagnostic, + } + impl Visitor<'_> for WalkAssocTypes<'_> { + fn visit_qpath( + &mut self, + qpath: &rustc_hir::QPath<'_>, + id: rustc_hir::HirId, + span: Span, + ) { + if TypeAliasBounds::is_type_variable_assoc(qpath) { + self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help); + } + intravisit::walk_qpath(self, qpath, id) + } + } + + // Let's go for a walk! + let mut visitor = WalkAssocTypes { err: diag }; + visitor.visit_ty(self.ty); + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_type_alias_where_clause)] +pub struct BuiltinTypeAliasWhereClause<'a, 'b> { + #[suggestion(code = "", applicability = "machine-applicable")] + pub suggestion: Span, + #[subdiagnostic] + pub sub: Option>, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_type_alias_generic_bounds)] +pub struct BuiltinTypeAliasGenericBounds<'a, 'b> { + #[subdiagnostic] + pub suggestion: BuiltinTypeAliasGenericBoundsSuggestion, + #[subdiagnostic] + pub sub: Option>, +} + +pub struct BuiltinTypeAliasGenericBoundsSuggestion { + pub suggestions: Vec<(Span, String)>, +} + +impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + diag.multipart_suggestion( + fluent::suggestion, + self.suggestions, + Applicability::MachineApplicable, + ); + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_trivial_bounds)] +pub struct BuiltinTrivialBounds<'a> { + pub predicate_kind_name: &'a str, + pub predicate: Predicate<'a>, +} + +#[derive(LintDiagnostic)] +pub enum BuiltinEllipsisInclusiveRangePatternsLint { + #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] + Parenthesise { + #[suggestion(code = "{replace}", applicability = "machine-applicable")] + suggestion: Span, + replace: String, + }, + #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] + NonParenthesise { + #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")] + suggestion: Span, + }, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unnameable_test_items)] +pub struct BuiltinUnnameableTestItems; + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_keyword_idents)] +pub struct BuiltinKeywordIdents { + pub kw: Ident, + pub next: Edition, + #[suggestion(code = "r#{kw}", applicability = "machine-applicable")] + pub suggestion: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_explicit_outlives)] +pub struct BuiltinExplicitOutlives { + pub count: usize, + #[subdiagnostic] + pub suggestion: BuiltinExplicitOutlivesSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(suggestion)] +pub struct BuiltinExplicitOutlivesSuggestion { + #[suggestion_part(code = "")] + pub spans: Vec, + #[applicability] + pub applicability: Applicability, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_incomplete_features)] +pub struct BuiltinIncompleteFeatures { + pub name: Symbol, + #[subdiagnostic] + pub note: Option, + #[subdiagnostic] + pub help: Option, +} + +#[derive(Subdiagnostic)] +#[help(help)] +pub struct BuiltinIncompleteFeaturesHelp; + +#[derive(Subdiagnostic)] +#[note(note)] +pub struct BuiltinIncompleteFeaturesNote { + pub n: NonZeroU32, +} + +pub struct BuiltinUnpermittedTypeInit<'a> { + pub msg: DiagnosticMessage, + pub ty: Ty<'a>, + pub label: Span, + pub sub: BuiltinUnpermittedTypeInitSub, +} + +impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { + fn decorate_lint<'b>( + self, + diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, + ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { + diag.set_arg("ty", self.ty); + diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); + diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label_suggestion); + self.sub.add_to_diagnostic(diag); + diag + } + + fn msg(&self) -> rustc_errors::DiagnosticMessage { + self.msg.clone() + } +} + +// FIXME(davidtwco): make translatable +pub struct BuiltinUnpermittedTypeInitSub { + pub err: InitError, +} + +impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + let mut err = self.err; + loop { + if let Some(span) = err.span { + diag.span_note(span, err.message); + } else { + diag.note(err.message); + } + if let Some(e) = err.nested { + err = *e; + } else { + break; + } + } + } +} + +#[derive(LintDiagnostic)] +pub enum BuiltinClashingExtern<'a> { + #[diag(lint_builtin_clashing_extern_same_name)] + SameName { + this: Symbol, + orig: Symbol, + #[label(previous_decl_label)] + previous_decl_label: Span, + #[label(mismatch_label)] + mismatch_label: Span, + #[subdiagnostic] + sub: BuiltinClashingExternSub<'a>, + }, + #[diag(lint_builtin_clashing_extern_diff_name)] + DiffName { + this: Symbol, + orig: Symbol, + #[label(previous_decl_label)] + previous_decl_label: Span, + #[label(mismatch_label)] + mismatch_label: Span, + #[subdiagnostic] + sub: BuiltinClashingExternSub<'a>, + }, +} + +// FIXME(davidtwco): translatable expected/found +pub struct BuiltinClashingExternSub<'a> { + pub tcx: TyCtxt<'a>, + pub expected: Ty<'a>, + pub found: Ty<'a>, +} + +impl AddToDiagnostic for BuiltinClashingExternSub<'_> { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + let mut expected_str = DiagnosticStyledString::new(); + expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); + let mut found_str = DiagnosticStyledString::new(); + found_str.push(self.found.fn_sig(self.tcx).to_string(), true); + diag.note_expected_found(&"", expected_str, &"", found_str); + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_deref_nullptr)] +pub struct BuiltinDerefNullptr { + #[label] + pub label: Span, +} + +// FIXME: migrate fluent::lint::builtin_asm_labels + +#[derive(LintDiagnostic)] +pub enum BuiltinSpecialModuleNameUsed { + #[diag(lint_builtin_special_module_name_used_lib)] + #[note] + #[help] + Lib, + #[diag(lint_builtin_special_module_name_used_main)] + #[note] + Main, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unexpected_cli_config_name)] +#[help] +pub struct BuiltinUnexpectedCliConfigName { + pub name: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_unexpected_cli_config_value)] +#[help] +pub struct BuiltinUnexpectedCliConfigValue { + pub name: Symbol, + pub value: Symbol, +} + +// deref_into_dyn_supertrait.rs +#[derive(LintDiagnostic)] +#[diag(lint_supertrait_as_deref_target)] +pub struct SupertraitAsDerefTarget<'a> { + pub t: Ty<'a>, + pub target_principal: String, + // pub target_principal: Binder<'a, ExistentialTraitRef<'b>>, + #[subdiagnostic] + pub label: Option, +} + +#[derive(Subdiagnostic)] +#[label(label)] +pub struct SupertraitAsDerefTargetLabel { + #[primary_span] + pub label: Span, +} + // enum_intrinsics_non_enums.rs #[derive(LintDiagnostic)] #[diag(lint_enum_intrinsics_mem_discriminant)] @@ -49,6 +585,157 @@ pub struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } +// expect.rs +#[derive(LintDiagnostic)] +#[diag(lint_expectation)] +pub struct Expectation { + #[subdiagnostic] + pub rationale: Option, + #[note] + pub note: Option<()>, +} + +#[derive(Subdiagnostic)] +#[note(rationale)] +pub struct ExpectationNote { + pub rationale: Symbol, +} + +// for_loops_over_fallibles.rs +#[derive(LintDiagnostic)] +#[diag(lint_for_loops_over_fallibles)] +pub struct ForLoopsOverFalliblesDiag<'a> { + pub article: &'static str, + pub ty: &'static str, + #[subdiagnostic] + pub sub: ForLoopsOverFalliblesLoopSub<'a>, + #[subdiagnostic] + pub question_mark: Option, + #[subdiagnostic] + pub suggestion: ForLoopsOverFalliblesSuggestion<'a>, +} + +#[derive(Subdiagnostic)] +pub enum ForLoopsOverFalliblesLoopSub<'a> { + #[suggestion(remove_next, code = ".by_ref()", applicability = "maybe-incorrect")] + RemoveNext { + #[primary_span] + suggestion: Span, + recv_snip: String, + }, + #[multipart_suggestion(use_while_let, applicability = "maybe-incorrect")] + UseWhileLet { + #[suggestion_part(code = "while let {var}(")] + start_span: Span, + #[suggestion_part(code = ") = ")] + end_span: Span, + var: &'a str, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion(use_question_mark, code = "?", applicability = "maybe-incorrect")] +pub struct ForLoopsOverFalliblesQuestionMark { + #[primary_span] + pub suggestion: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")] +pub struct ForLoopsOverFalliblesSuggestion<'a> { + pub var: &'a str, + #[suggestion_part(code = "if let {var}(")] + pub start_span: Span, + #[suggestion_part(code = ") = ")] + pub end_span: Span, +} + +// hidden_unicode_codepoints.rs +#[derive(LintDiagnostic)] +#[diag(lint_hidden_unicode_codepoints)] +#[note] +pub struct HiddenUnicodeCodepointsDiag<'a> { + pub label: &'a str, + pub count: usize, + #[label] + pub span_label: Span, + #[subdiagnostic] + pub labels: Option, + #[subdiagnostic] + pub sub: HiddenUnicodeCodepointsDiagSub, +} + +pub struct HiddenUnicodeCodepointsDiagLabels { + pub spans: Vec<(char, Span)>, +} + +impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + for (c, span) in self.spans { + diag.span_label(span, format!("{:?}", c)); + } + } +} + +pub enum HiddenUnicodeCodepointsDiagSub { + Escape { spans: Vec<(char, Span)> }, + NoEscape { spans: Vec<(char, Span)> }, +} + +// Used because of multiple multipart_suggestion and note +impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + match self { + HiddenUnicodeCodepointsDiagSub::Escape { spans } => { + diag.multipart_suggestion_with_style( + fluent::suggestion_remove, + spans.iter().map(|(_, span)| (*span, "".to_string())).collect(), + Applicability::MachineApplicable, + SuggestionStyle::HideCodeAlways, + ); + diag.multipart_suggestion( + fluent::suggestion_escape, + spans + .into_iter() + .map(|(c, span)| { + let c = format!("{:?}", c); + (span, c[1..c.len() - 1].to_string()) + }) + .collect(), + Applicability::MachineApplicable, + ); + } + HiddenUnicodeCodepointsDiagSub::NoEscape { spans } => { + // FIXME: in other suggestions we've reversed the inner spans of doc comments. We + // should do the same here to provide the same good suggestions as we do for + // literals above. + diag.set_arg( + "escaped", + spans + .into_iter() + .map(|(c, _)| format!("{:?}", c)) + .collect::>() + .join(", "), + ); + diag.note(fluent::suggestion_remove); + diag.note(fluent::no_suggestion_note_escape); + } + } + } +} + // internal.rs #[derive(LintDiagnostic)] #[diag(lint_default_hash_types)] @@ -178,59 +865,37 @@ pub struct DeprecatedLintName<'a> { pub replace: &'a str, } +// FIXME: Non-translatable msg +#[derive(LintDiagnostic)] +#[diag(lint_renamed_or_removed_lint)] pub struct RenamedOrRemovedLint<'a> { pub msg: &'a str, - pub suggestion: Span, - pub renamed: &'a Option, + #[subdiagnostic] + pub suggestion: Option>, } -impl<'a> DecorateLint<'a, ()> for RenamedOrRemovedLint<'_> { - fn decorate_lint<'b>( - self, - diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, - ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - if let Some(new_name) = self.renamed { - diag.span_suggestion( - self.suggestion, - fluent::lint_renamed_or_removed_lint_suggestion, - new_name, - Applicability::MachineApplicable, - ); - }; - diag - } - - fn msg(&self) -> rustc_errors::DiagnosticMessage { - rustc_errors::DiagnosticMessage::Str(self.msg.to_string()) - } +#[derive(Subdiagnostic)] +#[suggestion(suggestion, code = "{replace}", applicability = "machine-applicable")] +pub struct RenamedOrRemovedLintSuggestion<'a> { + #[primary_span] + pub suggestion: Span, + pub replace: &'a str, } -pub struct UnknownLint<'a> { +#[derive(LintDiagnostic)] +#[diag(lint_unknown_lint)] +pub struct UnknownLint { pub name: String, - pub suggestion: Span, - pub replace: &'a Option, + #[subdiagnostic] + pub suggestion: Option, } -impl<'a> DecorateLint<'a, ()> for UnknownLint<'_> { - fn decorate_lint<'b>( - self, - diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, - ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - diag.set_arg("name", self.name); - if let Some(replace) = self.replace { - diag.span_suggestion( - self.suggestion, - fluent::suggestion, - replace, - Applicability::MaybeIncorrect, - ); - }; - diag - } - - fn msg(&self) -> rustc_errors::DiagnosticMessage { - fluent::lint_unknown_lint - } +#[derive(Subdiagnostic)] +#[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")] +pub struct UnknownLintSuggestion { + #[primary_span] + pub suggestion: Span, + pub replace: Symbol, } #[derive(LintDiagnostic)] @@ -252,6 +917,13 @@ pub struct CStringPtr { pub unwrap: Span, } +// multiple_supertrait_upcastable.rs +#[derive(LintDiagnostic)] +#[diag(lint_multple_supertrait_upcastable)] +pub struct MultipleSupertraitUpcastable { + pub ident: Ident, +} + // non_ascii_idents.rs #[derive(LintDiagnostic)] #[diag(lint_identifier_non_ascii_char)] @@ -285,6 +957,7 @@ pub struct NonFmtPanicUnused { pub suggestion: Option, } +// Used because of two suggestions based on one Option impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { fn decorate_lint<'b>( self, @@ -470,6 +1143,7 @@ pub struct DropTraitConstraintsDiag<'a> { pub def_id: DefId, } +// Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> { fn decorate_lint<'b>( self, @@ -489,6 +1163,7 @@ pub struct DropGlue<'a> { pub def_id: DefId, } +// Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { fn decorate_lint<'b>( self, @@ -569,35 +1244,22 @@ pub enum OverflowingBinHexSub<'a> { Help { suggestion_ty: &'a str }, } +#[derive(LintDiagnostic)] +#[diag(lint_overflowing_int)] +#[note] pub struct OverflowingInt<'a> { pub ty: &'a str, pub lit: String, pub min: i128, pub max: u128, - pub suggestion_ty: Option<&'a str>, + #[subdiagnostic] + pub help: Option>, } -// FIXME: refactor with `Option<&'a str>` in macro -impl<'a> DecorateLint<'a, ()> for OverflowingInt<'_> { - fn decorate_lint<'b>( - self, - diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, - ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - diag.set_arg("ty", self.ty); - diag.set_arg("lit", self.lit); - diag.set_arg("min", self.min); - diag.set_arg("max", self.max); - diag.note(fluent::note); - if let Some(suggestion_ty) = self.suggestion_ty { - diag.set_arg("suggestion_ty", suggestion_ty); - diag.help(fluent::help); - } - diag - } - - fn msg(&self) -> rustc_errors::DiagnosticMessage { - fluent::lint_overflowing_int - } +#[derive(Subdiagnostic)] +#[help(help)] +pub struct OverflowingIntHelp<'a> { + pub suggestion_ty: &'a str, } #[derive(LintDiagnostic)] @@ -639,6 +1301,7 @@ pub struct ImproperCTypes<'a> { pub span_note: Option, } +// Used because of the complexity of Option, DiagnosticMessage, and Option impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { fn decorate_lint<'b>( self, @@ -739,9 +1402,24 @@ pub struct UnusedDef<'a, 'b> { pub cx: &'a LateContext<'b>, pub def_id: DefId, pub note: Option, + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +pub enum UnusedDefSuggestion { + #[suggestion( + suggestion, + style = "verbose", + code = "let _ = ", + applicability = "machine-applicable" + )] + Default { + #[primary_span] + span: Span, + }, } -// FIXME: refactor with `Option` in macro +// Needed because of def_path_str impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { fn decorate_lint<'b>( self, @@ -754,6 +1432,9 @@ fn decorate_lint<'b>( if let Some(note) = self.note { diag.note(note.as_str()); } + if let Some(sugg) = self.suggestion { + diag.subdiagnostic(sugg); + } diag }