rustc_lint/
lints.rs

1#![allow(rustc::diagnostic_outside_of_impl)]
2#![allow(rustc::untranslatable_diagnostic)]
3use std::num::NonZero;
4
5use rustc_abi::ExternAbi;
6use rustc_errors::codes::*;
7use rustc_errors::{
8    Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag,
9    EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle,
10};
11use rustc_hir::def::Namespace;
12use rustc_hir::def_id::DefId;
13use rustc_hir::intravisit::VisitorExt;
14use rustc_hir::{self as hir, MissingLifetimeKind};
15use rustc_macros::{LintDiagnostic, Subdiagnostic};
16use rustc_middle::ty::inhabitedness::InhabitedPredicate;
17use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt};
18use rustc_session::Session;
19use rustc_session::lint::AmbiguityErrorDiag;
20use rustc_span::edition::Edition;
21use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, kw, sym};
22
23use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds};
24use crate::errors::{OverruledAttributeSub, RequestedLevel};
25use crate::{LateContext, fluent_generated as fluent};
26
27// array_into_iter.rs
28#[derive(LintDiagnostic)]
29#[diag(lint_shadowed_into_iter)]
30pub(crate) struct ShadowedIntoIterDiag {
31    pub target: &'static str,
32    pub edition: &'static str,
33    #[suggestion(lint_use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
34    pub suggestion: Span,
35    #[subdiagnostic]
36    pub sub: Option<ShadowedIntoIterDiagSub>,
37}
38
39#[derive(Subdiagnostic)]
40pub(crate) enum ShadowedIntoIterDiagSub {
41    #[suggestion(lint_remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
42    RemoveIntoIter {
43        #[primary_span]
44        span: Span,
45    },
46    #[multipart_suggestion(
47        lint_use_explicit_into_iter_suggestion,
48        applicability = "maybe-incorrect"
49    )]
50    UseExplicitIntoIter {
51        #[suggestion_part(code = "IntoIterator::into_iter(")]
52        start_span: Span,
53        #[suggestion_part(code = ")")]
54        end_span: Span,
55    },
56}
57
58// autorefs.rs
59#[derive(LintDiagnostic)]
60#[diag(lint_implicit_unsafe_autorefs)]
61#[note]
62pub(crate) struct ImplicitUnsafeAutorefsDiag {
63    #[subdiagnostic]
64    pub suggestion: ImplicitUnsafeAutorefsSuggestion,
65}
66
67#[derive(Subdiagnostic)]
68#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
69pub(crate) struct ImplicitUnsafeAutorefsSuggestion {
70    pub mutbl: &'static str,
71    pub deref: &'static str,
72    #[suggestion_part(code = "({mutbl}{deref}")]
73    pub start_span: Span,
74    #[suggestion_part(code = ")")]
75    pub end_span: Span,
76}
77
78// builtin.rs
79#[derive(LintDiagnostic)]
80#[diag(lint_builtin_while_true)]
81pub(crate) struct BuiltinWhileTrue {
82    #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")]
83    pub suggestion: Span,
84    pub replace: String,
85}
86
87#[derive(LintDiagnostic)]
88#[diag(lint_builtin_non_shorthand_field_patterns)]
89pub(crate) struct BuiltinNonShorthandFieldPatterns {
90    pub ident: Ident,
91    #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")]
92    pub suggestion: Span,
93    pub prefix: &'static str,
94}
95
96#[derive(LintDiagnostic)]
97pub(crate) enum BuiltinUnsafe {
98    #[diag(lint_builtin_allow_internal_unsafe)]
99    AllowInternalUnsafe,
100    #[diag(lint_builtin_unsafe_block)]
101    UnsafeBlock,
102    #[diag(lint_builtin_unsafe_extern_block)]
103    UnsafeExternBlock,
104    #[diag(lint_builtin_unsafe_trait)]
105    UnsafeTrait,
106    #[diag(lint_builtin_unsafe_impl)]
107    UnsafeImpl,
108    #[diag(lint_builtin_no_mangle_fn)]
109    #[note(lint_builtin_overridden_symbol_name)]
110    NoMangleFn,
111    #[diag(lint_builtin_export_name_fn)]
112    #[note(lint_builtin_overridden_symbol_name)]
113    ExportNameFn,
114    #[diag(lint_builtin_link_section_fn)]
115    #[note(lint_builtin_overridden_symbol_section)]
116    LinkSectionFn,
117    #[diag(lint_builtin_no_mangle_static)]
118    #[note(lint_builtin_overridden_symbol_name)]
119    NoMangleStatic,
120    #[diag(lint_builtin_export_name_static)]
121    #[note(lint_builtin_overridden_symbol_name)]
122    ExportNameStatic,
123    #[diag(lint_builtin_link_section_static)]
124    #[note(lint_builtin_overridden_symbol_section)]
125    LinkSectionStatic,
126    #[diag(lint_builtin_no_mangle_method)]
127    #[note(lint_builtin_overridden_symbol_name)]
128    NoMangleMethod,
129    #[diag(lint_builtin_export_name_method)]
130    #[note(lint_builtin_overridden_symbol_name)]
131    ExportNameMethod,
132    #[diag(lint_builtin_decl_unsafe_fn)]
133    DeclUnsafeFn,
134    #[diag(lint_builtin_decl_unsafe_method)]
135    DeclUnsafeMethod,
136    #[diag(lint_builtin_impl_unsafe_method)]
137    ImplUnsafeMethod,
138    #[diag(lint_builtin_global_asm)]
139    #[note(lint_builtin_global_macro_unsafety)]
140    GlobalAsm,
141}
142
143#[derive(LintDiagnostic)]
144#[diag(lint_builtin_missing_doc)]
145pub(crate) struct BuiltinMissingDoc<'a> {
146    pub article: &'a str,
147    pub desc: &'a str,
148}
149
150#[derive(LintDiagnostic)]
151#[diag(lint_builtin_missing_copy_impl)]
152pub(crate) struct BuiltinMissingCopyImpl;
153
154pub(crate) struct BuiltinMissingDebugImpl<'a> {
155    pub tcx: TyCtxt<'a>,
156    pub def_id: DefId,
157}
158
159// Needed for def_path_str
160impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> {
161    fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
162        diag.primary_message(fluent::lint_builtin_missing_debug_impl);
163        diag.arg("debug", self.tcx.def_path_str(self.def_id));
164    }
165}
166
167#[derive(LintDiagnostic)]
168#[diag(lint_builtin_anonymous_params)]
169pub(crate) struct BuiltinAnonymousParams<'a> {
170    #[suggestion(code = "_: {ty_snip}")]
171    pub suggestion: (Span, Applicability),
172    pub ty_snip: &'a str,
173}
174
175// FIXME(davidtwco) translatable deprecated attr
176#[derive(LintDiagnostic)]
177#[diag(lint_builtin_deprecated_attr_link)]
178pub(crate) struct BuiltinDeprecatedAttrLink<'a> {
179    pub name: Symbol,
180    pub reason: &'a str,
181    pub link: &'a str,
182    #[subdiagnostic]
183    pub suggestion: BuiltinDeprecatedAttrLinkSuggestion<'a>,
184}
185
186#[derive(Subdiagnostic)]
187pub(crate) enum BuiltinDeprecatedAttrLinkSuggestion<'a> {
188    #[suggestion(lint_msg_suggestion, code = "", applicability = "machine-applicable")]
189    Msg {
190        #[primary_span]
191        suggestion: Span,
192        msg: &'a str,
193    },
194    #[suggestion(lint_default_suggestion, code = "", applicability = "machine-applicable")]
195    Default {
196        #[primary_span]
197        suggestion: Span,
198    },
199}
200
201#[derive(LintDiagnostic)]
202#[diag(lint_builtin_unused_doc_comment)]
203pub(crate) struct BuiltinUnusedDocComment<'a> {
204    pub kind: &'a str,
205    #[label]
206    pub label: Span,
207    #[subdiagnostic]
208    pub sub: BuiltinUnusedDocCommentSub,
209}
210
211#[derive(Subdiagnostic)]
212pub(crate) enum BuiltinUnusedDocCommentSub {
213    #[help(lint_plain_help)]
214    PlainHelp,
215    #[help(lint_block_help)]
216    BlockHelp,
217}
218
219#[derive(LintDiagnostic)]
220#[diag(lint_builtin_no_mangle_generic)]
221pub(crate) struct BuiltinNoMangleGeneric {
222    // Use of `#[no_mangle]` suggests FFI intent; correct
223    // fix may be to monomorphize source by hand
224    #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")]
225    pub suggestion: Span,
226}
227
228#[derive(LintDiagnostic)]
229#[diag(lint_builtin_const_no_mangle)]
230pub(crate) struct BuiltinConstNoMangle {
231    #[suggestion(code = "pub static", applicability = "machine-applicable")]
232    pub suggestion: Span,
233}
234
235#[derive(LintDiagnostic)]
236#[diag(lint_builtin_mutable_transmutes)]
237pub(crate) struct BuiltinMutablesTransmutes;
238
239#[derive(LintDiagnostic)]
240#[diag(lint_builtin_unstable_features)]
241pub(crate) struct BuiltinUnstableFeatures;
242
243// lint_ungated_async_fn_track_caller
244pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> {
245    pub label: Span,
246    pub session: &'a Session,
247}
248
249impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
250    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
251        diag.primary_message(fluent::lint_ungated_async_fn_track_caller);
252        diag.span_label(self.label, fluent::lint_label);
253        rustc_session::parse::add_feature_diagnostics(
254            diag,
255            self.session,
256            sym::async_fn_track_caller,
257        );
258    }
259}
260
261#[derive(LintDiagnostic)]
262#[diag(lint_builtin_unreachable_pub)]
263pub(crate) struct BuiltinUnreachablePub<'a> {
264    pub what: &'a str,
265    pub new_vis: &'a str,
266    #[suggestion(code = "{new_vis}")]
267    pub suggestion: (Span, Applicability),
268    #[help]
269    pub help: bool,
270}
271
272#[derive(LintDiagnostic)]
273#[diag(lint_macro_expr_fragment_specifier_2024_migration)]
274pub(crate) struct MacroExprFragment2024 {
275    #[suggestion(code = "expr_2021", applicability = "machine-applicable")]
276    pub suggestion: Span,
277}
278
279pub(crate) struct BuiltinTypeAliasBounds<'hir> {
280    pub in_where_clause: bool,
281    pub label: Span,
282    pub enable_feat_help: bool,
283    pub suggestions: Vec<(Span, String)>,
284    pub preds: &'hir [hir::WherePredicate<'hir>],
285    pub ty: Option<&'hir hir::Ty<'hir>>,
286}
287
288impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> {
289    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
290        diag.primary_message(if self.in_where_clause {
291            fluent::lint_builtin_type_alias_bounds_where_clause
292        } else {
293            fluent::lint_builtin_type_alias_bounds_param_bounds
294        });
295        diag.span_label(self.label, fluent::lint_builtin_type_alias_bounds_label);
296        diag.note(fluent::lint_builtin_type_alias_bounds_limitation_note);
297        if self.enable_feat_help {
298            diag.help(fluent::lint_builtin_type_alias_bounds_enable_feat_help);
299        }
300
301        // We perform the walk in here instead of in `<TypeAliasBounds as LateLintPass>` to
302        // avoid doing throwaway work in case the lint ends up getting suppressed.
303        let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() };
304        if let Some(ty) = self.ty {
305            collector.visit_ty_unambig(ty);
306        }
307
308        let affect_object_lifetime_defaults = self
309            .preds
310            .iter()
311            .filter(|pred| pred.kind.in_where_clause() == self.in_where_clause)
312            .any(|pred| TypeAliasBounds::affects_object_lifetime_defaults(pred));
313
314        // If there are any shorthand assoc tys, then the bounds can't be removed automatically.
315        // The user first needs to fully qualify the assoc tys.
316        let applicability = if !collector.qselves.is_empty() || affect_object_lifetime_defaults {
317            Applicability::MaybeIncorrect
318        } else {
319            Applicability::MachineApplicable
320        };
321
322        diag.arg("count", self.suggestions.len());
323        diag.multipart_suggestion(fluent::lint_suggestion, self.suggestions, applicability);
324
325        // Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via
326        // `<T as /* Trait */>::Assoc` to remove their reliance on any type param bounds.
327        //
328        // Instead of attempting to figure out the necessary trait ref, just use a
329        // placeholder. Since we don't record type-dependent resolutions for non-body
330        // items like type aliases, we can't simply deduce the corresp. trait from
331        // the HIR path alone without rerunning parts of HIR ty lowering here
332        // (namely `probe_single_ty_param_bound_for_assoc_ty`) which is infeasible.
333        //
334        // (We could employ some simple heuristics but that's likely not worth it).
335        for qself in collector.qselves {
336            diag.multipart_suggestion(
337                fluent::lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg,
338                vec![
339                    (qself.shrink_to_lo(), "<".into()),
340                    (qself.shrink_to_hi(), " as /* Trait */>".into()),
341                ],
342                Applicability::HasPlaceholders,
343            );
344        }
345    }
346}
347
348#[derive(LintDiagnostic)]
349#[diag(lint_builtin_trivial_bounds)]
350pub(crate) struct BuiltinTrivialBounds<'a> {
351    pub predicate_kind_name: &'a str,
352    pub predicate: Clause<'a>,
353}
354
355#[derive(LintDiagnostic)]
356#[diag(lint_builtin_double_negations)]
357#[note(lint_note)]
358#[note(lint_note_decrement)]
359pub(crate) struct BuiltinDoubleNegations {
360    #[subdiagnostic]
361    pub add_parens: BuiltinDoubleNegationsAddParens,
362}
363
364#[derive(Subdiagnostic)]
365#[multipart_suggestion(lint_add_parens_suggestion, applicability = "maybe-incorrect")]
366pub(crate) struct BuiltinDoubleNegationsAddParens {
367    #[suggestion_part(code = "(")]
368    pub start_span: Span,
369    #[suggestion_part(code = ")")]
370    pub end_span: Span,
371}
372
373#[derive(LintDiagnostic)]
374pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
375    #[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
376    Parenthesise {
377        #[suggestion(code = "{replace}", applicability = "machine-applicable")]
378        suggestion: Span,
379        replace: String,
380    },
381    #[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
382    NonParenthesise {
383        #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")]
384        suggestion: Span,
385    },
386}
387
388#[derive(LintDiagnostic)]
389#[diag(lint_builtin_keyword_idents)]
390pub(crate) struct BuiltinKeywordIdents {
391    pub kw: Ident,
392    pub next: Edition,
393    #[suggestion(code = "{prefix}r#{kw}", applicability = "machine-applicable")]
394    pub suggestion: Span,
395    pub prefix: &'static str,
396}
397
398#[derive(LintDiagnostic)]
399#[diag(lint_builtin_explicit_outlives)]
400pub(crate) struct BuiltinExplicitOutlives {
401    pub count: usize,
402    #[subdiagnostic]
403    pub suggestion: BuiltinExplicitOutlivesSuggestion,
404}
405
406#[derive(Subdiagnostic)]
407#[multipart_suggestion(lint_suggestion)]
408pub(crate) struct BuiltinExplicitOutlivesSuggestion {
409    #[suggestion_part(code = "")]
410    pub spans: Vec<Span>,
411    #[applicability]
412    pub applicability: Applicability,
413}
414
415#[derive(LintDiagnostic)]
416#[diag(lint_builtin_incomplete_features)]
417pub(crate) struct BuiltinIncompleteFeatures {
418    pub name: Symbol,
419    #[subdiagnostic]
420    pub note: Option<BuiltinFeatureIssueNote>,
421    #[subdiagnostic]
422    pub help: Option<BuiltinIncompleteFeaturesHelp>,
423}
424
425#[derive(LintDiagnostic)]
426#[diag(lint_builtin_internal_features)]
427#[note]
428pub(crate) struct BuiltinInternalFeatures {
429    pub name: Symbol,
430}
431
432#[derive(Subdiagnostic)]
433#[help(lint_help)]
434pub(crate) struct BuiltinIncompleteFeaturesHelp;
435
436#[derive(Subdiagnostic)]
437#[note(lint_note)]
438pub(crate) struct BuiltinFeatureIssueNote {
439    pub n: NonZero<u32>,
440}
441
442pub(crate) struct BuiltinUnpermittedTypeInit<'a> {
443    pub msg: DiagMessage,
444    pub ty: Ty<'a>,
445    pub label: Span,
446    pub sub: BuiltinUnpermittedTypeInitSub,
447    pub tcx: TyCtxt<'a>,
448}
449
450impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
451    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
452        diag.primary_message(self.msg);
453        diag.arg("ty", self.ty);
454        diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label);
455        if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) {
456            // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited.
457            diag.span_label(
458                self.label,
459                fluent::lint_builtin_unpermitted_type_init_label_suggestion,
460            );
461        }
462        self.sub.add_to_diag(diag);
463    }
464}
465
466// FIXME(davidtwco): make translatable
467pub(crate) struct BuiltinUnpermittedTypeInitSub {
468    pub err: InitError,
469}
470
471impl Subdiagnostic for BuiltinUnpermittedTypeInitSub {
472    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
473        let mut err = self.err;
474        loop {
475            if let Some(span) = err.span {
476                diag.span_note(span, err.message);
477            } else {
478                diag.note(err.message);
479            }
480            if let Some(e) = err.nested {
481                err = *e;
482            } else {
483                break;
484            }
485        }
486    }
487}
488
489#[derive(LintDiagnostic)]
490pub(crate) enum BuiltinClashingExtern<'a> {
491    #[diag(lint_builtin_clashing_extern_same_name)]
492    SameName {
493        this: Symbol,
494        orig: Symbol,
495        #[label(lint_previous_decl_label)]
496        previous_decl_label: Span,
497        #[label(lint_mismatch_label)]
498        mismatch_label: Span,
499        #[subdiagnostic]
500        sub: BuiltinClashingExternSub<'a>,
501    },
502    #[diag(lint_builtin_clashing_extern_diff_name)]
503    DiffName {
504        this: Symbol,
505        orig: Symbol,
506        #[label(lint_previous_decl_label)]
507        previous_decl_label: Span,
508        #[label(lint_mismatch_label)]
509        mismatch_label: Span,
510        #[subdiagnostic]
511        sub: BuiltinClashingExternSub<'a>,
512    },
513}
514
515// FIXME(davidtwco): translatable expected/found
516pub(crate) struct BuiltinClashingExternSub<'a> {
517    pub tcx: TyCtxt<'a>,
518    pub expected: Ty<'a>,
519    pub found: Ty<'a>,
520}
521
522impl Subdiagnostic for BuiltinClashingExternSub<'_> {
523    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
524        let mut expected_str = DiagStyledString::new();
525        expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
526        let mut found_str = DiagStyledString::new();
527        found_str.push(self.found.fn_sig(self.tcx).to_string(), true);
528        diag.note_expected_found("", expected_str, "", found_str);
529    }
530}
531
532#[derive(LintDiagnostic)]
533#[diag(lint_builtin_deref_nullptr)]
534pub(crate) struct BuiltinDerefNullptr {
535    #[label]
536    pub label: Span,
537}
538
539// FIXME: migrate fluent::lint::builtin_asm_labels
540
541#[derive(LintDiagnostic)]
542pub(crate) enum BuiltinSpecialModuleNameUsed {
543    #[diag(lint_builtin_special_module_name_used_lib)]
544    #[note]
545    #[help]
546    Lib,
547    #[diag(lint_builtin_special_module_name_used_main)]
548    #[note]
549    Main,
550}
551
552// deref_into_dyn_supertrait.rs
553#[derive(LintDiagnostic)]
554#[diag(lint_supertrait_as_deref_target)]
555pub(crate) struct SupertraitAsDerefTarget<'a> {
556    pub self_ty: Ty<'a>,
557    pub supertrait_principal: PolyExistentialTraitRef<'a>,
558    pub target_principal: PolyExistentialTraitRef<'a>,
559    #[label]
560    pub label: Span,
561    #[subdiagnostic]
562    pub label2: Option<SupertraitAsDerefTargetLabel>,
563}
564
565#[derive(Subdiagnostic)]
566#[label(lint_label2)]
567pub(crate) struct SupertraitAsDerefTargetLabel {
568    #[primary_span]
569    pub label: Span,
570}
571
572// enum_intrinsics_non_enums.rs
573#[derive(LintDiagnostic)]
574#[diag(lint_enum_intrinsics_mem_discriminant)]
575pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> {
576    pub ty_param: Ty<'a>,
577    #[note]
578    pub note: Span,
579}
580
581#[derive(LintDiagnostic)]
582#[diag(lint_enum_intrinsics_mem_variant)]
583#[note]
584pub(crate) struct EnumIntrinsicsMemVariant<'a> {
585    pub ty_param: Ty<'a>,
586}
587
588// expect.rs
589#[derive(LintDiagnostic)]
590#[diag(lint_expectation)]
591pub(crate) struct Expectation {
592    #[subdiagnostic]
593    pub rationale: Option<ExpectationNote>,
594    #[note]
595    pub note: bool,
596}
597
598#[derive(Subdiagnostic)]
599#[note(lint_rationale)]
600pub(crate) struct ExpectationNote {
601    pub rationale: Symbol,
602}
603
604// ptr_nulls.rs
605#[derive(LintDiagnostic)]
606pub(crate) enum UselessPtrNullChecksDiag<'a> {
607    #[diag(lint_useless_ptr_null_checks_fn_ptr)]
608    #[help]
609    FnPtr {
610        orig_ty: Ty<'a>,
611        #[label]
612        label: Span,
613    },
614    #[diag(lint_useless_ptr_null_checks_ref)]
615    Ref {
616        orig_ty: Ty<'a>,
617        #[label]
618        label: Span,
619    },
620    #[diag(lint_useless_ptr_null_checks_fn_ret)]
621    FnRet { fn_name: Ident },
622}
623
624#[derive(LintDiagnostic)]
625pub(crate) enum InvalidNullArgumentsDiag {
626    #[diag(lint_invalid_null_arguments)]
627    #[help(lint_doc)]
628    NullPtrInline {
629        #[label(lint_origin)]
630        null_span: Span,
631    },
632    #[diag(lint_invalid_null_arguments)]
633    #[help(lint_doc)]
634    NullPtrThroughBinding {
635        #[note(lint_origin)]
636        null_span: Span,
637    },
638}
639
640// for_loops_over_fallibles.rs
641#[derive(LintDiagnostic)]
642#[diag(lint_for_loops_over_fallibles)]
643pub(crate) struct ForLoopsOverFalliblesDiag<'a> {
644    pub article: &'static str,
645    pub ref_prefix: &'static str,
646    pub ty: &'static str,
647    #[subdiagnostic]
648    pub sub: ForLoopsOverFalliblesLoopSub<'a>,
649    #[subdiagnostic]
650    pub question_mark: Option<ForLoopsOverFalliblesQuestionMark>,
651    #[subdiagnostic]
652    pub suggestion: ForLoopsOverFalliblesSuggestion<'a>,
653}
654
655#[derive(Subdiagnostic)]
656pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> {
657    #[suggestion(lint_remove_next, code = ".by_ref()", applicability = "maybe-incorrect")]
658    RemoveNext {
659        #[primary_span]
660        suggestion: Span,
661        recv_snip: String,
662    },
663    #[multipart_suggestion(lint_use_while_let, applicability = "maybe-incorrect")]
664    UseWhileLet {
665        #[suggestion_part(code = "while let {var}(")]
666        start_span: Span,
667        #[suggestion_part(code = ") = ")]
668        end_span: Span,
669        var: &'a str,
670    },
671}
672
673#[derive(Subdiagnostic)]
674#[suggestion(lint_use_question_mark, code = "?", applicability = "maybe-incorrect")]
675pub(crate) struct ForLoopsOverFalliblesQuestionMark {
676    #[primary_span]
677    pub suggestion: Span,
678}
679
680#[derive(Subdiagnostic)]
681#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
682pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> {
683    pub var: &'a str,
684    #[suggestion_part(code = "if let {var}(")]
685    pub start_span: Span,
686    #[suggestion_part(code = ") = ")]
687    pub end_span: Span,
688}
689
690#[derive(Subdiagnostic)]
691pub(crate) enum UseLetUnderscoreIgnoreSuggestion {
692    #[note(lint_use_let_underscore_ignore_suggestion)]
693    Note,
694    #[multipart_suggestion(
695        lint_use_let_underscore_ignore_suggestion,
696        style = "verbose",
697        applicability = "maybe-incorrect"
698    )]
699    Suggestion {
700        #[suggestion_part(code = "let _ = ")]
701        start_span: Span,
702        #[suggestion_part(code = "")]
703        end_span: Span,
704    },
705}
706
707// drop_forget_useless.rs
708#[derive(LintDiagnostic)]
709#[diag(lint_dropping_references)]
710pub(crate) struct DropRefDiag<'a> {
711    pub arg_ty: Ty<'a>,
712    #[label]
713    pub label: Span,
714    #[subdiagnostic]
715    pub sugg: UseLetUnderscoreIgnoreSuggestion,
716}
717
718#[derive(LintDiagnostic)]
719#[diag(lint_dropping_copy_types)]
720pub(crate) struct DropCopyDiag<'a> {
721    pub arg_ty: Ty<'a>,
722    #[label]
723    pub label: Span,
724    #[subdiagnostic]
725    pub sugg: UseLetUnderscoreIgnoreSuggestion,
726}
727
728#[derive(LintDiagnostic)]
729#[diag(lint_forgetting_references)]
730pub(crate) struct ForgetRefDiag<'a> {
731    pub arg_ty: Ty<'a>,
732    #[label]
733    pub label: Span,
734    #[subdiagnostic]
735    pub sugg: UseLetUnderscoreIgnoreSuggestion,
736}
737
738#[derive(LintDiagnostic)]
739#[diag(lint_forgetting_copy_types)]
740pub(crate) struct ForgetCopyDiag<'a> {
741    pub arg_ty: Ty<'a>,
742    #[label]
743    pub label: Span,
744    #[subdiagnostic]
745    pub sugg: UseLetUnderscoreIgnoreSuggestion,
746}
747
748#[derive(LintDiagnostic)]
749#[diag(lint_undropped_manually_drops)]
750pub(crate) struct UndroppedManuallyDropsDiag<'a> {
751    pub arg_ty: Ty<'a>,
752    #[label]
753    pub label: Span,
754    #[subdiagnostic]
755    pub suggestion: UndroppedManuallyDropsSuggestion,
756}
757
758#[derive(Subdiagnostic)]
759#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
760pub(crate) struct UndroppedManuallyDropsSuggestion {
761    #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")]
762    pub start_span: Span,
763    #[suggestion_part(code = ")")]
764    pub end_span: Span,
765}
766
767// invalid_from_utf8.rs
768#[derive(LintDiagnostic)]
769pub(crate) enum InvalidFromUtf8Diag {
770    #[diag(lint_invalid_from_utf8_unchecked)]
771    Unchecked {
772        method: String,
773        valid_up_to: usize,
774        #[label]
775        label: Span,
776    },
777    #[diag(lint_invalid_from_utf8_checked)]
778    Checked {
779        method: String,
780        valid_up_to: usize,
781        #[label]
782        label: Span,
783    },
784}
785
786// reference_casting.rs
787#[derive(LintDiagnostic)]
788pub(crate) enum InvalidReferenceCastingDiag<'tcx> {
789    #[diag(lint_invalid_reference_casting_borrow_as_mut)]
790    #[note(lint_invalid_reference_casting_note_book)]
791    BorrowAsMut {
792        #[label]
793        orig_cast: Option<Span>,
794        #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
795        ty_has_interior_mutability: bool,
796    },
797    #[diag(lint_invalid_reference_casting_assign_to_ref)]
798    #[note(lint_invalid_reference_casting_note_book)]
799    AssignToRef {
800        #[label]
801        orig_cast: Option<Span>,
802        #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
803        ty_has_interior_mutability: bool,
804    },
805    #[diag(lint_invalid_reference_casting_bigger_layout)]
806    #[note(lint_layout)]
807    BiggerLayout {
808        #[label]
809        orig_cast: Option<Span>,
810        #[label(lint_alloc)]
811        alloc: Span,
812        from_ty: Ty<'tcx>,
813        from_size: u64,
814        to_ty: Ty<'tcx>,
815        to_size: u64,
816    },
817}
818
819// hidden_unicode_codepoints.rs
820#[derive(LintDiagnostic)]
821#[diag(lint_hidden_unicode_codepoints)]
822#[note]
823pub(crate) struct HiddenUnicodeCodepointsDiag<'a> {
824    pub label: &'a str,
825    pub count: usize,
826    #[label]
827    pub span_label: Span,
828    #[subdiagnostic]
829    pub labels: Option<HiddenUnicodeCodepointsDiagLabels>,
830    #[subdiagnostic]
831    pub sub: HiddenUnicodeCodepointsDiagSub,
832}
833
834pub(crate) struct HiddenUnicodeCodepointsDiagLabels {
835    pub spans: Vec<(char, Span)>,
836}
837
838impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels {
839    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
840        for (c, span) in self.spans {
841            diag.span_label(span, format!("{c:?}"));
842        }
843    }
844}
845
846pub(crate) enum HiddenUnicodeCodepointsDiagSub {
847    Escape { spans: Vec<(char, Span)> },
848    NoEscape { spans: Vec<(char, Span)> },
849}
850
851// Used because of multiple multipart_suggestion and note
852impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub {
853    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
854        match self {
855            HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
856                diag.multipart_suggestion_with_style(
857                    fluent::lint_suggestion_remove,
858                    spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
859                    Applicability::MachineApplicable,
860                    SuggestionStyle::HideCodeAlways,
861                );
862                diag.multipart_suggestion(
863                    fluent::lint_suggestion_escape,
864                    spans
865                        .into_iter()
866                        .map(|(c, span)| {
867                            let c = format!("{c:?}");
868                            (span, c[1..c.len() - 1].to_string())
869                        })
870                        .collect(),
871                    Applicability::MachineApplicable,
872                );
873            }
874            HiddenUnicodeCodepointsDiagSub::NoEscape { spans } => {
875                // FIXME: in other suggestions we've reversed the inner spans of doc comments. We
876                // should do the same here to provide the same good suggestions as we do for
877                // literals above.
878                diag.arg(
879                    "escaped",
880                    spans
881                        .into_iter()
882                        .map(|(c, _)| format!("{c:?}"))
883                        .collect::<Vec<String>>()
884                        .join(", "),
885                );
886                diag.note(fluent::lint_suggestion_remove);
887                diag.note(fluent::lint_no_suggestion_note_escape);
888            }
889        }
890    }
891}
892
893// map_unit_fn.rs
894#[derive(LintDiagnostic)]
895#[diag(lint_map_unit_fn)]
896#[note]
897pub(crate) struct MappingToUnit {
898    #[label(lint_function_label)]
899    pub function_label: Span,
900    #[label(lint_argument_label)]
901    pub argument_label: Span,
902    #[label(lint_map_label)]
903    pub map_label: Span,
904    #[suggestion(style = "verbose", code = "{replace}", applicability = "maybe-incorrect")]
905    pub suggestion: Span,
906    pub replace: String,
907}
908
909// internal.rs
910#[derive(LintDiagnostic)]
911#[diag(lint_default_hash_types)]
912#[note]
913pub(crate) struct DefaultHashTypesDiag<'a> {
914    pub preferred: &'a str,
915    pub used: Symbol,
916}
917
918#[derive(LintDiagnostic)]
919#[diag(lint_query_instability)]
920#[note]
921pub(crate) struct QueryInstability {
922    pub query: Symbol,
923}
924
925#[derive(LintDiagnostic)]
926#[diag(lint_query_untracked)]
927#[note]
928pub(crate) struct QueryUntracked {
929    pub method: Symbol,
930}
931
932#[derive(LintDiagnostic)]
933#[diag(lint_span_use_eq_ctxt)]
934pub(crate) struct SpanUseEqCtxtDiag;
935
936#[derive(LintDiagnostic)]
937#[diag(lint_symbol_intern_string_literal)]
938#[help]
939pub(crate) struct SymbolInternStringLiteralDiag;
940
941#[derive(LintDiagnostic)]
942#[diag(lint_tykind_kind)]
943pub(crate) struct TykindKind {
944    #[suggestion(code = "ty", applicability = "maybe-incorrect")]
945    pub suggestion: Span,
946}
947
948#[derive(LintDiagnostic)]
949#[diag(lint_tykind)]
950#[help]
951pub(crate) struct TykindDiag;
952
953#[derive(LintDiagnostic)]
954#[diag(lint_ty_qualified)]
955pub(crate) struct TyQualified {
956    pub ty: String,
957    #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
958    pub suggestion: Span,
959}
960
961#[derive(LintDiagnostic)]
962#[diag(lint_type_ir_inherent_usage)]
963#[note]
964pub(crate) struct TypeIrInherentUsage;
965
966#[derive(LintDiagnostic)]
967#[diag(lint_type_ir_trait_usage)]
968#[note]
969pub(crate) struct TypeIrTraitUsage;
970
971#[derive(LintDiagnostic)]
972#[diag(lint_non_glob_import_type_ir_inherent)]
973pub(crate) struct NonGlobImportTypeIrInherent {
974    #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")]
975    pub suggestion: Option<Span>,
976    pub snippet: &'static str,
977}
978
979#[derive(LintDiagnostic)]
980#[diag(lint_lintpass_by_hand)]
981#[help]
982pub(crate) struct LintPassByHand;
983
984#[derive(LintDiagnostic)]
985#[diag(lint_diag_out_of_impl)]
986pub(crate) struct DiagOutOfImpl;
987
988#[derive(LintDiagnostic)]
989#[diag(lint_untranslatable_diag)]
990pub(crate) struct UntranslatableDiag;
991
992#[derive(LintDiagnostic)]
993#[diag(lint_bad_opt_access)]
994pub(crate) struct BadOptAccessDiag<'a> {
995    pub msg: &'a str,
996}
997
998// let_underscore.rs
999#[derive(LintDiagnostic)]
1000pub(crate) enum NonBindingLet {
1001    #[diag(lint_non_binding_let_on_sync_lock)]
1002    SyncLock {
1003        #[label]
1004        pat: Span,
1005        #[subdiagnostic]
1006        sub: NonBindingLetSub,
1007    },
1008    #[diag(lint_non_binding_let_on_drop_type)]
1009    DropType {
1010        #[subdiagnostic]
1011        sub: NonBindingLetSub,
1012    },
1013}
1014
1015pub(crate) struct NonBindingLetSub {
1016    pub suggestion: Span,
1017    pub drop_fn_start_end: Option<(Span, Span)>,
1018    pub is_assign_desugar: bool,
1019}
1020
1021impl Subdiagnostic for NonBindingLetSub {
1022    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1023        let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
1024
1025        if can_suggest_binding {
1026            let prefix = if self.is_assign_desugar { "let " } else { "" };
1027            diag.span_suggestion_verbose(
1028                self.suggestion,
1029                fluent::lint_non_binding_let_suggestion,
1030                format!("{prefix}_unused"),
1031                Applicability::MachineApplicable,
1032            );
1033        } else {
1034            diag.span_help(self.suggestion, fluent::lint_non_binding_let_suggestion);
1035        }
1036        if let Some(drop_fn_start_end) = self.drop_fn_start_end {
1037            diag.multipart_suggestion(
1038                fluent::lint_non_binding_let_multi_suggestion,
1039                vec![
1040                    (drop_fn_start_end.0, "drop(".to_string()),
1041                    (drop_fn_start_end.1, ")".to_string()),
1042                ],
1043                Applicability::MachineApplicable,
1044            );
1045        } else {
1046            diag.help(fluent::lint_non_binding_let_multi_drop_fn);
1047        }
1048    }
1049}
1050
1051// levels.rs
1052#[derive(LintDiagnostic)]
1053#[diag(lint_overruled_attribute)]
1054pub(crate) struct OverruledAttributeLint<'a> {
1055    #[label]
1056    pub overruled: Span,
1057    pub lint_level: &'a str,
1058    pub lint_source: Symbol,
1059    #[subdiagnostic]
1060    pub sub: OverruledAttributeSub,
1061}
1062
1063#[derive(LintDiagnostic)]
1064#[diag(lint_deprecated_lint_name)]
1065pub(crate) struct DeprecatedLintName<'a> {
1066    pub name: String,
1067    #[suggestion(code = "{replace}", applicability = "machine-applicable")]
1068    pub suggestion: Span,
1069    pub replace: &'a str,
1070}
1071
1072#[derive(LintDiagnostic)]
1073#[diag(lint_deprecated_lint_name)]
1074#[help]
1075pub(crate) struct DeprecatedLintNameFromCommandLine<'a> {
1076    pub name: String,
1077    pub replace: &'a str,
1078    #[subdiagnostic]
1079    pub requested_level: RequestedLevel<'a>,
1080}
1081
1082#[derive(LintDiagnostic)]
1083#[diag(lint_renamed_lint)]
1084pub(crate) struct RenamedLint<'a> {
1085    pub name: &'a str,
1086    #[subdiagnostic]
1087    pub suggestion: RenamedLintSuggestion<'a>,
1088}
1089
1090#[derive(Subdiagnostic)]
1091pub(crate) enum RenamedLintSuggestion<'a> {
1092    #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
1093    WithSpan {
1094        #[primary_span]
1095        suggestion: Span,
1096        replace: &'a str,
1097    },
1098    #[help(lint_help)]
1099    WithoutSpan { replace: &'a str },
1100}
1101
1102#[derive(LintDiagnostic)]
1103#[diag(lint_renamed_lint)]
1104pub(crate) struct RenamedLintFromCommandLine<'a> {
1105    pub name: &'a str,
1106    #[subdiagnostic]
1107    pub suggestion: RenamedLintSuggestion<'a>,
1108    #[subdiagnostic]
1109    pub requested_level: RequestedLevel<'a>,
1110}
1111
1112#[derive(LintDiagnostic)]
1113#[diag(lint_removed_lint)]
1114pub(crate) struct RemovedLint<'a> {
1115    pub name: &'a str,
1116    pub reason: &'a str,
1117}
1118
1119#[derive(LintDiagnostic)]
1120#[diag(lint_removed_lint)]
1121pub(crate) struct RemovedLintFromCommandLine<'a> {
1122    pub name: &'a str,
1123    pub reason: &'a str,
1124    #[subdiagnostic]
1125    pub requested_level: RequestedLevel<'a>,
1126}
1127
1128#[derive(LintDiagnostic)]
1129#[diag(lint_unknown_lint)]
1130pub(crate) struct UnknownLint {
1131    pub name: String,
1132    #[subdiagnostic]
1133    pub suggestion: Option<UnknownLintSuggestion>,
1134}
1135
1136#[derive(Subdiagnostic)]
1137pub(crate) enum UnknownLintSuggestion {
1138    #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1139    WithSpan {
1140        #[primary_span]
1141        suggestion: Span,
1142        replace: Symbol,
1143        from_rustc: bool,
1144    },
1145    #[help(lint_help)]
1146    WithoutSpan { replace: Symbol, from_rustc: bool },
1147}
1148
1149#[derive(LintDiagnostic)]
1150#[diag(lint_unknown_lint, code = E0602)]
1151pub(crate) struct UnknownLintFromCommandLine<'a> {
1152    pub name: String,
1153    #[subdiagnostic]
1154    pub suggestion: Option<UnknownLintSuggestion>,
1155    #[subdiagnostic]
1156    pub requested_level: RequestedLevel<'a>,
1157}
1158
1159#[derive(LintDiagnostic)]
1160#[diag(lint_ignored_unless_crate_specified)]
1161pub(crate) struct IgnoredUnlessCrateSpecified<'a> {
1162    pub level: &'a str,
1163    pub name: Symbol,
1164}
1165
1166// dangling.rs
1167#[derive(LintDiagnostic)]
1168#[diag(lint_dangling_pointers_from_temporaries)]
1169#[note]
1170#[help(lint_help_bind)]
1171#[help(lint_help_returned)]
1172#[help(lint_help_visit)]
1173// FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts
1174pub(crate) struct DanglingPointersFromTemporaries<'tcx> {
1175    pub callee: Ident,
1176    pub ty: Ty<'tcx>,
1177    #[label(lint_label_ptr)]
1178    pub ptr_span: Span,
1179    #[label(lint_label_temporary)]
1180    pub temporary_span: Span,
1181}
1182
1183// multiple_supertrait_upcastable.rs
1184#[derive(LintDiagnostic)]
1185#[diag(lint_multiple_supertrait_upcastable)]
1186pub(crate) struct MultipleSupertraitUpcastable {
1187    pub ident: Ident,
1188}
1189
1190// non_ascii_idents.rs
1191#[derive(LintDiagnostic)]
1192#[diag(lint_identifier_non_ascii_char)]
1193pub(crate) struct IdentifierNonAsciiChar;
1194
1195#[derive(LintDiagnostic)]
1196#[diag(lint_identifier_uncommon_codepoints)]
1197#[note]
1198pub(crate) struct IdentifierUncommonCodepoints {
1199    pub codepoints: Vec<char>,
1200    pub codepoints_len: usize,
1201    pub identifier_type: &'static str,
1202}
1203
1204#[derive(LintDiagnostic)]
1205#[diag(lint_confusable_identifier_pair)]
1206pub(crate) struct ConfusableIdentifierPair {
1207    pub existing_sym: Symbol,
1208    pub sym: Symbol,
1209    #[label(lint_other_use)]
1210    pub label: Span,
1211    #[label(lint_current_use)]
1212    pub main_label: Span,
1213}
1214
1215#[derive(LintDiagnostic)]
1216#[diag(lint_mixed_script_confusables)]
1217#[note(lint_includes_note)]
1218#[note]
1219pub(crate) struct MixedScriptConfusables {
1220    pub set: String,
1221    pub includes: String,
1222}
1223
1224// non_fmt_panic.rs
1225pub(crate) struct NonFmtPanicUnused {
1226    pub count: usize,
1227    pub suggestion: Option<Span>,
1228}
1229
1230// Used because of two suggestions based on one Option<Span>
1231impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused {
1232    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1233        diag.primary_message(fluent::lint_non_fmt_panic_unused);
1234        diag.arg("count", self.count);
1235        diag.note(fluent::lint_note);
1236        if let Some(span) = self.suggestion {
1237            diag.span_suggestion(
1238                span.shrink_to_hi(),
1239                fluent::lint_add_args_suggestion,
1240                ", ...",
1241                Applicability::HasPlaceholders,
1242            );
1243            diag.span_suggestion(
1244                span.shrink_to_lo(),
1245                fluent::lint_add_fmt_suggestion,
1246                "\"{}\", ",
1247                Applicability::MachineApplicable,
1248            );
1249        }
1250    }
1251}
1252
1253#[derive(LintDiagnostic)]
1254#[diag(lint_non_fmt_panic_braces)]
1255#[note]
1256pub(crate) struct NonFmtPanicBraces {
1257    pub count: usize,
1258    #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
1259    pub suggestion: Option<Span>,
1260}
1261
1262// nonstandard_style.rs
1263#[derive(LintDiagnostic)]
1264#[diag(lint_non_camel_case_type)]
1265pub(crate) struct NonCamelCaseType<'a> {
1266    pub sort: &'a str,
1267    pub name: &'a str,
1268    #[subdiagnostic]
1269    pub sub: NonCamelCaseTypeSub,
1270}
1271
1272#[derive(Subdiagnostic)]
1273pub(crate) enum NonCamelCaseTypeSub {
1274    #[label(lint_label)]
1275    Label {
1276        #[primary_span]
1277        span: Span,
1278    },
1279    #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1280    Suggestion {
1281        #[primary_span]
1282        span: Span,
1283        replace: String,
1284    },
1285}
1286
1287#[derive(LintDiagnostic)]
1288#[diag(lint_non_snake_case)]
1289pub(crate) struct NonSnakeCaseDiag<'a> {
1290    pub sort: &'a str,
1291    pub name: &'a str,
1292    pub sc: String,
1293    #[subdiagnostic]
1294    pub sub: NonSnakeCaseDiagSub,
1295}
1296
1297pub(crate) enum NonSnakeCaseDiagSub {
1298    Label { span: Span },
1299    Help,
1300    RenameOrConvertSuggestion { span: Span, suggestion: Ident },
1301    ConvertSuggestion { span: Span, suggestion: String },
1302    SuggestionAndNote { span: Span },
1303}
1304
1305impl Subdiagnostic for NonSnakeCaseDiagSub {
1306    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1307        match self {
1308            NonSnakeCaseDiagSub::Label { span } => {
1309                diag.span_label(span, fluent::lint_label);
1310            }
1311            NonSnakeCaseDiagSub::Help => {
1312                diag.help(fluent::lint_help);
1313            }
1314            NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
1315                diag.span_suggestion(
1316                    span,
1317                    fluent::lint_convert_suggestion,
1318                    suggestion,
1319                    Applicability::MaybeIncorrect,
1320                );
1321            }
1322            NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
1323                diag.span_suggestion(
1324                    span,
1325                    fluent::lint_rename_or_convert_suggestion,
1326                    suggestion,
1327                    Applicability::MaybeIncorrect,
1328                );
1329            }
1330            NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
1331                diag.note(fluent::lint_cannot_convert_note);
1332                diag.span_suggestion(
1333                    span,
1334                    fluent::lint_rename_suggestion,
1335                    "",
1336                    Applicability::MaybeIncorrect,
1337                );
1338            }
1339        }
1340    }
1341}
1342
1343#[derive(LintDiagnostic)]
1344#[diag(lint_non_upper_case_global)]
1345pub(crate) struct NonUpperCaseGlobal<'a> {
1346    pub sort: &'a str,
1347    pub name: &'a str,
1348    #[subdiagnostic]
1349    pub sub: NonUpperCaseGlobalSub,
1350}
1351
1352#[derive(Subdiagnostic)]
1353pub(crate) enum NonUpperCaseGlobalSub {
1354    #[label(lint_label)]
1355    Label {
1356        #[primary_span]
1357        span: Span,
1358    },
1359    #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1360    Suggestion {
1361        #[primary_span]
1362        span: Span,
1363        replace: String,
1364    },
1365}
1366
1367// noop_method_call.rs
1368#[derive(LintDiagnostic)]
1369#[diag(lint_noop_method_call)]
1370#[note]
1371pub(crate) struct NoopMethodCallDiag<'a> {
1372    pub method: Ident,
1373    pub orig_ty: Ty<'a>,
1374    pub trait_: Symbol,
1375    #[suggestion(code = "", applicability = "machine-applicable")]
1376    pub label: Span,
1377    #[suggestion(
1378        lint_derive_suggestion,
1379        code = "#[derive(Clone)]\n",
1380        applicability = "maybe-incorrect"
1381    )]
1382    pub suggest_derive: Option<Span>,
1383}
1384
1385#[derive(LintDiagnostic)]
1386#[diag(lint_suspicious_double_ref_deref)]
1387pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> {
1388    pub ty: Ty<'a>,
1389}
1390
1391#[derive(LintDiagnostic)]
1392#[diag(lint_suspicious_double_ref_clone)]
1393pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> {
1394    pub ty: Ty<'a>,
1395}
1396
1397// non_local_defs.rs
1398pub(crate) enum NonLocalDefinitionsDiag {
1399    Impl {
1400        depth: u32,
1401        body_kind_descr: &'static str,
1402        body_name: String,
1403        cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
1404        const_anon: Option<Option<Span>>,
1405        doctest: bool,
1406        macro_to_change: Option<(String, &'static str)>,
1407    },
1408    MacroRules {
1409        depth: u32,
1410        body_kind_descr: &'static str,
1411        body_name: String,
1412        doctest: bool,
1413        cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
1414    },
1415}
1416
1417impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
1418    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1419        match self {
1420            NonLocalDefinitionsDiag::Impl {
1421                depth,
1422                body_kind_descr,
1423                body_name,
1424                cargo_update,
1425                const_anon,
1426                doctest,
1427                macro_to_change,
1428            } => {
1429                diag.primary_message(fluent::lint_non_local_definitions_impl);
1430                diag.arg("depth", depth);
1431                diag.arg("body_kind_descr", body_kind_descr);
1432                diag.arg("body_name", body_name);
1433
1434                if let Some((macro_to_change, macro_kind)) = macro_to_change {
1435                    diag.arg("macro_to_change", macro_to_change);
1436                    diag.arg("macro_kind", macro_kind);
1437                    diag.note(fluent::lint_macro_to_change);
1438                }
1439                if let Some(cargo_update) = cargo_update {
1440                    diag.subdiagnostic(cargo_update);
1441                }
1442
1443                diag.note(fluent::lint_non_local);
1444
1445                if doctest {
1446                    diag.help(fluent::lint_doctest);
1447                }
1448
1449                if let Some(const_anon) = const_anon {
1450                    diag.note(fluent::lint_exception);
1451                    if let Some(const_anon) = const_anon {
1452                        diag.span_suggestion(
1453                            const_anon,
1454                            fluent::lint_const_anon,
1455                            "_",
1456                            Applicability::MachineApplicable,
1457                        );
1458                    }
1459                }
1460            }
1461            NonLocalDefinitionsDiag::MacroRules {
1462                depth,
1463                body_kind_descr,
1464                body_name,
1465                doctest,
1466                cargo_update,
1467            } => {
1468                diag.primary_message(fluent::lint_non_local_definitions_macro_rules);
1469                diag.arg("depth", depth);
1470                diag.arg("body_kind_descr", body_kind_descr);
1471                diag.arg("body_name", body_name);
1472
1473                if doctest {
1474                    diag.help(fluent::lint_help_doctest);
1475                } else {
1476                    diag.help(fluent::lint_help);
1477                }
1478
1479                diag.note(fluent::lint_non_local);
1480
1481                if let Some(cargo_update) = cargo_update {
1482                    diag.subdiagnostic(cargo_update);
1483                }
1484            }
1485        }
1486    }
1487}
1488
1489#[derive(Subdiagnostic)]
1490#[note(lint_non_local_definitions_cargo_update)]
1491pub(crate) struct NonLocalDefinitionsCargoUpdateNote {
1492    pub macro_kind: &'static str,
1493    pub macro_name: Symbol,
1494    pub crate_name: Symbol,
1495}
1496
1497// precedence.rs
1498#[derive(LintDiagnostic)]
1499#[diag(lint_ambiguous_negative_literals)]
1500#[note(lint_example)]
1501pub(crate) struct AmbiguousNegativeLiteralsDiag {
1502    #[subdiagnostic]
1503    pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
1504    #[subdiagnostic]
1505    pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion,
1506}
1507
1508#[derive(Subdiagnostic)]
1509#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")]
1510pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
1511    #[suggestion_part(code = "(")]
1512    pub start_span: Span,
1513    #[suggestion_part(code = ")")]
1514    pub end_span: Span,
1515}
1516
1517#[derive(Subdiagnostic)]
1518#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")]
1519pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
1520    #[suggestion_part(code = "(")]
1521    pub start_span: Span,
1522    #[suggestion_part(code = ")")]
1523    pub end_span: Span,
1524}
1525
1526// pass_by_value.rs
1527#[derive(LintDiagnostic)]
1528#[diag(lint_pass_by_value)]
1529pub(crate) struct PassByValueDiag {
1530    pub ty: String,
1531    #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
1532    pub suggestion: Span,
1533}
1534
1535// redundant_semicolon.rs
1536#[derive(LintDiagnostic)]
1537#[diag(lint_redundant_semicolons)]
1538pub(crate) struct RedundantSemicolonsDiag {
1539    pub multiple: bool,
1540    #[suggestion(code = "", applicability = "maybe-incorrect")]
1541    pub suggestion: Span,
1542}
1543
1544// traits.rs
1545pub(crate) struct DropTraitConstraintsDiag<'a> {
1546    pub predicate: Clause<'a>,
1547    pub tcx: TyCtxt<'a>,
1548    pub def_id: DefId,
1549}
1550
1551// Needed for def_path_str
1552impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> {
1553    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1554        diag.primary_message(fluent::lint_drop_trait_constraints);
1555        diag.arg("predicate", self.predicate);
1556        diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
1557    }
1558}
1559
1560pub(crate) struct DropGlue<'a> {
1561    pub tcx: TyCtxt<'a>,
1562    pub def_id: DefId,
1563}
1564
1565// Needed for def_path_str
1566impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> {
1567    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1568        diag.primary_message(fluent::lint_drop_glue);
1569        diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
1570    }
1571}
1572
1573// types.rs
1574#[derive(LintDiagnostic)]
1575#[diag(lint_range_endpoint_out_of_range)]
1576pub(crate) struct RangeEndpointOutOfRange<'a> {
1577    pub ty: &'a str,
1578    #[subdiagnostic]
1579    pub sub: UseInclusiveRange<'a>,
1580}
1581
1582#[derive(Subdiagnostic)]
1583pub(crate) enum UseInclusiveRange<'a> {
1584    #[suggestion(
1585        lint_range_use_inclusive_range,
1586        code = "{start}..={literal}{suffix}",
1587        applicability = "machine-applicable"
1588    )]
1589    WithoutParen {
1590        #[primary_span]
1591        sugg: Span,
1592        start: String,
1593        literal: u128,
1594        suffix: &'a str,
1595    },
1596    #[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")]
1597    WithParen {
1598        #[suggestion_part(code = "=")]
1599        eq_sugg: Span,
1600        #[suggestion_part(code = "{literal}{suffix}")]
1601        lit_sugg: Span,
1602        literal: u128,
1603        suffix: &'a str,
1604    },
1605}
1606
1607#[derive(LintDiagnostic)]
1608#[diag(lint_overflowing_bin_hex)]
1609pub(crate) struct OverflowingBinHex<'a> {
1610    pub ty: &'a str,
1611    pub lit: String,
1612    pub dec: u128,
1613    pub actually: String,
1614    #[subdiagnostic]
1615    pub sign: OverflowingBinHexSign,
1616    #[subdiagnostic]
1617    pub sub: Option<OverflowingBinHexSub<'a>>,
1618    #[subdiagnostic]
1619    pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>,
1620}
1621
1622pub(crate) enum OverflowingBinHexSign {
1623    Positive,
1624    Negative,
1625}
1626
1627impl Subdiagnostic for OverflowingBinHexSign {
1628    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1629        match self {
1630            OverflowingBinHexSign::Positive => {
1631                diag.note(fluent::lint_positive_note);
1632            }
1633            OverflowingBinHexSign::Negative => {
1634                diag.note(fluent::lint_negative_note);
1635                diag.note(fluent::lint_negative_becomes_note);
1636            }
1637        }
1638    }
1639}
1640
1641#[derive(Subdiagnostic)]
1642pub(crate) enum OverflowingBinHexSub<'a> {
1643    #[suggestion(
1644        lint_suggestion,
1645        code = "{sans_suffix}{suggestion_ty}",
1646        applicability = "machine-applicable"
1647    )]
1648    Suggestion {
1649        #[primary_span]
1650        span: Span,
1651        suggestion_ty: &'a str,
1652        sans_suffix: &'a str,
1653    },
1654    #[help(lint_help)]
1655    Help { suggestion_ty: &'a str },
1656}
1657
1658#[derive(Subdiagnostic)]
1659#[suggestion(
1660    lint_sign_bit_suggestion,
1661    code = "{lit_no_suffix}{uint_ty} as {int_ty}",
1662    applicability = "maybe-incorrect"
1663)]
1664pub(crate) struct OverflowingBinHexSignBitSub<'a> {
1665    #[primary_span]
1666    pub span: Span,
1667    pub lit_no_suffix: &'a str,
1668    pub negative_val: String,
1669    pub uint_ty: &'a str,
1670    pub int_ty: &'a str,
1671}
1672
1673#[derive(LintDiagnostic)]
1674#[diag(lint_overflowing_int)]
1675#[note]
1676pub(crate) struct OverflowingInt<'a> {
1677    pub ty: &'a str,
1678    pub lit: String,
1679    pub min: i128,
1680    pub max: u128,
1681    #[subdiagnostic]
1682    pub help: Option<OverflowingIntHelp<'a>>,
1683}
1684
1685#[derive(Subdiagnostic)]
1686#[help(lint_help)]
1687pub(crate) struct OverflowingIntHelp<'a> {
1688    pub suggestion_ty: &'a str,
1689}
1690
1691#[derive(LintDiagnostic)]
1692#[diag(lint_only_cast_u8_to_char)]
1693pub(crate) struct OnlyCastu8ToChar {
1694    #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
1695    pub span: Span,
1696    pub literal: u128,
1697}
1698
1699#[derive(LintDiagnostic)]
1700#[diag(lint_overflowing_uint)]
1701#[note]
1702pub(crate) struct OverflowingUInt<'a> {
1703    pub ty: &'a str,
1704    pub lit: String,
1705    pub min: u128,
1706    pub max: u128,
1707}
1708
1709#[derive(LintDiagnostic)]
1710#[diag(lint_overflowing_literal)]
1711#[note]
1712pub(crate) struct OverflowingLiteral<'a> {
1713    pub ty: &'a str,
1714    pub lit: String,
1715}
1716
1717#[derive(LintDiagnostic)]
1718#[diag(lint_uses_power_alignment)]
1719pub(crate) struct UsesPowerAlignment;
1720
1721#[derive(LintDiagnostic)]
1722#[diag(lint_unused_comparisons)]
1723pub(crate) struct UnusedComparisons;
1724
1725#[derive(LintDiagnostic)]
1726pub(crate) enum InvalidNanComparisons {
1727    #[diag(lint_invalid_nan_comparisons_eq_ne)]
1728    EqNe {
1729        #[subdiagnostic]
1730        suggestion: InvalidNanComparisonsSuggestion,
1731    },
1732    #[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)]
1733    LtLeGtGe,
1734}
1735
1736#[derive(Subdiagnostic)]
1737pub(crate) enum InvalidNanComparisonsSuggestion {
1738    #[multipart_suggestion(
1739        lint_suggestion,
1740        style = "verbose",
1741        applicability = "machine-applicable"
1742    )]
1743    Spanful {
1744        #[suggestion_part(code = "!")]
1745        neg: Option<Span>,
1746        #[suggestion_part(code = ".is_nan()")]
1747        float: Span,
1748        #[suggestion_part(code = "")]
1749        nan_plus_binop: Span,
1750    },
1751    #[help(lint_suggestion)]
1752    Spanless,
1753}
1754
1755#[derive(LintDiagnostic)]
1756pub(crate) enum AmbiguousWidePointerComparisons<'a> {
1757    #[diag(lint_ambiguous_wide_pointer_comparisons)]
1758    Spanful {
1759        #[subdiagnostic]
1760        addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>,
1761        #[subdiagnostic]
1762        addr_metadata_suggestion: Option<AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a>>,
1763    },
1764    #[diag(lint_ambiguous_wide_pointer_comparisons)]
1765    #[help(lint_addr_metadata_suggestion)]
1766    #[help(lint_addr_suggestion)]
1767    Spanless,
1768}
1769
1770#[derive(Subdiagnostic)]
1771#[multipart_suggestion(
1772    lint_addr_metadata_suggestion,
1773    style = "verbose",
1774    // FIXME(#53934): make machine-applicable again
1775    applicability = "maybe-incorrect"
1776)]
1777pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> {
1778    pub ne: &'a str,
1779    pub deref_left: &'a str,
1780    pub deref_right: &'a str,
1781    pub l_modifiers: &'a str,
1782    pub r_modifiers: &'a str,
1783    #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")]
1784    pub left: Span,
1785    #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
1786    pub middle: Span,
1787    #[suggestion_part(code = "{r_modifiers})")]
1788    pub right: Span,
1789}
1790
1791#[derive(Subdiagnostic)]
1792pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
1793    #[multipart_suggestion(
1794        lint_addr_suggestion,
1795        style = "verbose",
1796        // FIXME(#53934): make machine-applicable again
1797        applicability = "maybe-incorrect"
1798    )]
1799    AddrEq {
1800        ne: &'a str,
1801        deref_left: &'a str,
1802        deref_right: &'a str,
1803        l_modifiers: &'a str,
1804        r_modifiers: &'a str,
1805        #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
1806        left: Span,
1807        #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
1808        middle: Span,
1809        #[suggestion_part(code = "{r_modifiers})")]
1810        right: Span,
1811    },
1812    #[multipart_suggestion(
1813        lint_addr_suggestion,
1814        style = "verbose",
1815        // FIXME(#53934): make machine-applicable again
1816        applicability = "maybe-incorrect"
1817    )]
1818    Cast {
1819        deref_left: &'a str,
1820        deref_right: &'a str,
1821        paren_left: &'a str,
1822        paren_right: &'a str,
1823        l_modifiers: &'a str,
1824        r_modifiers: &'a str,
1825        #[suggestion_part(code = "({deref_left}")]
1826        left_before: Option<Span>,
1827        #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")]
1828        left_after: Span,
1829        #[suggestion_part(code = "({deref_right}")]
1830        right_before: Option<Span>,
1831        #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")]
1832        right_after: Span,
1833    },
1834}
1835
1836#[derive(LintDiagnostic)]
1837pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> {
1838    #[diag(lint_unpredictable_fn_pointer_comparisons)]
1839    #[note(lint_note_duplicated_fn)]
1840    #[note(lint_note_deduplicated_fn)]
1841    #[note(lint_note_visit_fn_addr_eq)]
1842    Suggestion {
1843        #[subdiagnostic]
1844        sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>,
1845    },
1846    #[diag(lint_unpredictable_fn_pointer_comparisons)]
1847    #[note(lint_note_duplicated_fn)]
1848    #[note(lint_note_deduplicated_fn)]
1849    #[note(lint_note_visit_fn_addr_eq)]
1850    Warn,
1851}
1852
1853#[derive(Subdiagnostic)]
1854pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> {
1855    #[multipart_suggestion(
1856        lint_fn_addr_eq_suggestion,
1857        style = "verbose",
1858        applicability = "maybe-incorrect"
1859    )]
1860    FnAddrEq {
1861        ne: &'a str,
1862        deref_left: &'a str,
1863        deref_right: &'a str,
1864        #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
1865        left: Span,
1866        #[suggestion_part(code = ", {deref_right}")]
1867        middle: Span,
1868        #[suggestion_part(code = ")")]
1869        right: Span,
1870    },
1871    #[multipart_suggestion(
1872        lint_fn_addr_eq_suggestion,
1873        style = "verbose",
1874        applicability = "maybe-incorrect"
1875    )]
1876    FnAddrEqWithCast {
1877        ne: &'a str,
1878        deref_left: &'a str,
1879        deref_right: &'a str,
1880        fn_sig: rustc_middle::ty::PolyFnSig<'tcx>,
1881        #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
1882        left: Span,
1883        #[suggestion_part(code = ", {deref_right}")]
1884        middle: Span,
1885        #[suggestion_part(code = " as {fn_sig})")]
1886        right: Span,
1887    },
1888}
1889
1890pub(crate) struct ImproperCTypes<'a> {
1891    pub ty: Ty<'a>,
1892    pub desc: &'a str,
1893    pub label: Span,
1894    pub help: Option<DiagMessage>,
1895    pub note: DiagMessage,
1896    pub span_note: Option<Span>,
1897}
1898
1899// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
1900impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
1901    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1902        diag.primary_message(fluent::lint_improper_ctypes);
1903        diag.arg("ty", self.ty);
1904        diag.arg("desc", self.desc);
1905        diag.span_label(self.label, fluent::lint_label);
1906        if let Some(help) = self.help {
1907            diag.help(help);
1908        }
1909        diag.note(self.note);
1910        if let Some(note) = self.span_note {
1911            diag.span_note(note, fluent::lint_note);
1912        }
1913    }
1914}
1915
1916#[derive(LintDiagnostic)]
1917#[diag(lint_variant_size_differences)]
1918pub(crate) struct VariantSizeDifferencesDiag {
1919    pub largest: u64,
1920}
1921
1922#[derive(LintDiagnostic)]
1923#[diag(lint_atomic_ordering_load)]
1924#[help]
1925pub(crate) struct AtomicOrderingLoad;
1926
1927#[derive(LintDiagnostic)]
1928#[diag(lint_atomic_ordering_store)]
1929#[help]
1930pub(crate) struct AtomicOrderingStore;
1931
1932#[derive(LintDiagnostic)]
1933#[diag(lint_atomic_ordering_fence)]
1934#[help]
1935pub(crate) struct AtomicOrderingFence;
1936
1937#[derive(LintDiagnostic)]
1938#[diag(lint_atomic_ordering_invalid)]
1939#[help]
1940pub(crate) struct InvalidAtomicOrderingDiag {
1941    pub method: Symbol,
1942    #[label]
1943    pub fail_order_arg_span: Span,
1944}
1945
1946// unused.rs
1947#[derive(LintDiagnostic)]
1948#[diag(lint_unused_op)]
1949pub(crate) struct UnusedOp<'a> {
1950    pub op: &'a str,
1951    #[label]
1952    pub label: Span,
1953    #[subdiagnostic]
1954    pub suggestion: UnusedOpSuggestion,
1955}
1956
1957#[derive(Subdiagnostic)]
1958pub(crate) enum UnusedOpSuggestion {
1959    #[suggestion(
1960        lint_suggestion,
1961        style = "verbose",
1962        code = "let _ = ",
1963        applicability = "maybe-incorrect"
1964    )]
1965    NormalExpr {
1966        #[primary_span]
1967        span: Span,
1968    },
1969    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
1970    BlockTailExpr {
1971        #[suggestion_part(code = "let _ = ")]
1972        before_span: Span,
1973        #[suggestion_part(code = ";")]
1974        after_span: Span,
1975    },
1976}
1977
1978#[derive(LintDiagnostic)]
1979#[diag(lint_unused_result)]
1980pub(crate) struct UnusedResult<'a> {
1981    pub ty: Ty<'a>,
1982}
1983
1984// FIXME(davidtwco): this isn't properly translatable because of the
1985// pre/post strings
1986#[derive(LintDiagnostic)]
1987#[diag(lint_unused_closure)]
1988#[note]
1989pub(crate) struct UnusedClosure<'a> {
1990    pub count: usize,
1991    pub pre: &'a str,
1992    pub post: &'a str,
1993}
1994
1995// FIXME(davidtwco): this isn't properly translatable because of the
1996// pre/post strings
1997#[derive(LintDiagnostic)]
1998#[diag(lint_unused_coroutine)]
1999#[note]
2000pub(crate) struct UnusedCoroutine<'a> {
2001    pub count: usize,
2002    pub pre: &'a str,
2003    pub post: &'a str,
2004}
2005
2006// FIXME(davidtwco): this isn't properly translatable because of the pre/post
2007// strings
2008pub(crate) struct UnusedDef<'a, 'b> {
2009    pub pre: &'a str,
2010    pub post: &'a str,
2011    pub cx: &'a LateContext<'b>,
2012    pub def_id: DefId,
2013    pub note: Option<Symbol>,
2014    pub suggestion: Option<UnusedDefSuggestion>,
2015}
2016
2017#[derive(Subdiagnostic)]
2018
2019pub(crate) enum UnusedDefSuggestion {
2020    #[suggestion(
2021        lint_suggestion,
2022        style = "verbose",
2023        code = "let _ = ",
2024        applicability = "maybe-incorrect"
2025    )]
2026    NormalExpr {
2027        #[primary_span]
2028        span: Span,
2029    },
2030    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
2031    BlockTailExpr {
2032        #[suggestion_part(code = "let _ = ")]
2033        before_span: Span,
2034        #[suggestion_part(code = ";")]
2035        after_span: Span,
2036    },
2037}
2038
2039// Needed because of def_path_str
2040impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> {
2041    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2042        diag.primary_message(fluent::lint_unused_def);
2043        diag.arg("pre", self.pre);
2044        diag.arg("post", self.post);
2045        diag.arg("def", self.cx.tcx.def_path_str(self.def_id));
2046        // check for #[must_use = "..."]
2047        if let Some(note) = self.note {
2048            diag.note(note.to_string());
2049        }
2050        if let Some(sugg) = self.suggestion {
2051            diag.subdiagnostic(sugg);
2052        }
2053    }
2054}
2055
2056#[derive(LintDiagnostic)]
2057#[diag(lint_path_statement_drop)]
2058pub(crate) struct PathStatementDrop {
2059    #[subdiagnostic]
2060    pub sub: PathStatementDropSub,
2061}
2062
2063#[derive(Subdiagnostic)]
2064pub(crate) enum PathStatementDropSub {
2065    #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
2066    Suggestion {
2067        #[primary_span]
2068        span: Span,
2069        snippet: String,
2070    },
2071    #[help(lint_help)]
2072    Help {
2073        #[primary_span]
2074        span: Span,
2075    },
2076}
2077
2078#[derive(LintDiagnostic)]
2079#[diag(lint_path_statement_no_effect)]
2080pub(crate) struct PathStatementNoEffect;
2081
2082#[derive(LintDiagnostic)]
2083#[diag(lint_unused_delim)]
2084pub(crate) struct UnusedDelim<'a> {
2085    pub delim: &'static str,
2086    pub item: &'a str,
2087    #[subdiagnostic]
2088    pub suggestion: Option<UnusedDelimSuggestion>,
2089}
2090
2091#[derive(Subdiagnostic)]
2092#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2093pub(crate) struct UnusedDelimSuggestion {
2094    #[suggestion_part(code = "{start_replace}")]
2095    pub start_span: Span,
2096    pub start_replace: &'static str,
2097    #[suggestion_part(code = "{end_replace}")]
2098    pub end_span: Span,
2099    pub end_replace: &'static str,
2100}
2101
2102#[derive(LintDiagnostic)]
2103#[diag(lint_unused_import_braces)]
2104pub(crate) struct UnusedImportBracesDiag {
2105    pub node: Symbol,
2106}
2107
2108#[derive(LintDiagnostic)]
2109#[diag(lint_unused_allocation)]
2110pub(crate) struct UnusedAllocationDiag;
2111
2112#[derive(LintDiagnostic)]
2113#[diag(lint_unused_allocation_mut)]
2114pub(crate) struct UnusedAllocationMutDiag;
2115
2116pub(crate) struct AsyncFnInTraitDiag {
2117    pub sugg: Option<Vec<(Span, String)>>,
2118}
2119
2120impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag {
2121    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2122        diag.primary_message(fluent::lint_async_fn_in_trait);
2123        diag.note(fluent::lint_note);
2124        if let Some(sugg) = self.sugg {
2125            diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect);
2126        }
2127    }
2128}
2129
2130#[derive(LintDiagnostic)]
2131#[diag(lint_unit_bindings)]
2132pub(crate) struct UnitBindingsDiag {
2133    #[label]
2134    pub label: Span,
2135}
2136
2137#[derive(LintDiagnostic)]
2138pub(crate) enum InvalidAsmLabel {
2139    #[diag(lint_invalid_asm_label_named)]
2140    #[help]
2141    #[note]
2142    Named {
2143        #[note(lint_invalid_asm_label_no_span)]
2144        missing_precise_span: bool,
2145    },
2146    #[diag(lint_invalid_asm_label_format_arg)]
2147    #[help]
2148    #[note(lint_note1)]
2149    #[note(lint_note2)]
2150    FormatArg {
2151        #[note(lint_invalid_asm_label_no_span)]
2152        missing_precise_span: bool,
2153    },
2154    #[diag(lint_invalid_asm_label_binary)]
2155    #[help]
2156    #[note(lint_note1)]
2157    #[note(lint_note2)]
2158    Binary {
2159        #[note(lint_invalid_asm_label_no_span)]
2160        missing_precise_span: bool,
2161        // hack to get a label on the whole span, must match the emitted span
2162        #[label]
2163        span: Span,
2164    },
2165}
2166
2167#[derive(Subdiagnostic)]
2168pub(crate) enum UnexpectedCfgCargoHelp {
2169    #[help(lint_unexpected_cfg_add_cargo_feature)]
2170    #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
2171    LintCfg { cargo_toml_lint_cfg: String },
2172    #[help(lint_unexpected_cfg_add_cargo_feature)]
2173    #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
2174    #[help(lint_unexpected_cfg_add_build_rs_println)]
2175    LintCfgAndBuildRs { cargo_toml_lint_cfg: String, build_rs_println: String },
2176}
2177
2178impl UnexpectedCfgCargoHelp {
2179    fn cargo_toml_lint_cfg(unescaped: &str) -> String {
2180        format!(
2181            "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}"
2182        )
2183    }
2184
2185    pub(crate) fn lint_cfg(unescaped: &str) -> Self {
2186        UnexpectedCfgCargoHelp::LintCfg {
2187            cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
2188        }
2189    }
2190
2191    pub(crate) fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self {
2192        UnexpectedCfgCargoHelp::LintCfgAndBuildRs {
2193            cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
2194            build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");"),
2195        }
2196    }
2197}
2198
2199#[derive(Subdiagnostic)]
2200#[help(lint_unexpected_cfg_add_cmdline_arg)]
2201pub(crate) struct UnexpectedCfgRustcHelp {
2202    pub cmdline_arg: String,
2203}
2204
2205impl UnexpectedCfgRustcHelp {
2206    pub(crate) fn new(unescaped: &str) -> Self {
2207        Self { cmdline_arg: format!("--check-cfg={unescaped}") }
2208    }
2209}
2210
2211#[derive(Subdiagnostic)]
2212#[note(lint_unexpected_cfg_from_external_macro_origin)]
2213#[help(lint_unexpected_cfg_from_external_macro_refer)]
2214pub(crate) struct UnexpectedCfgRustcMacroHelp {
2215    pub macro_kind: &'static str,
2216    pub macro_name: Symbol,
2217}
2218
2219#[derive(Subdiagnostic)]
2220#[note(lint_unexpected_cfg_from_external_macro_origin)]
2221#[help(lint_unexpected_cfg_from_external_macro_refer)]
2222#[help(lint_unexpected_cfg_cargo_update)]
2223pub(crate) struct UnexpectedCfgCargoMacroHelp {
2224    pub macro_kind: &'static str,
2225    pub macro_name: Symbol,
2226    pub crate_name: Symbol,
2227}
2228
2229#[derive(LintDiagnostic)]
2230#[diag(lint_unexpected_cfg_name)]
2231pub(crate) struct UnexpectedCfgName {
2232    #[subdiagnostic]
2233    pub code_sugg: unexpected_cfg_name::CodeSuggestion,
2234    #[subdiagnostic]
2235    pub invocation_help: unexpected_cfg_name::InvocationHelp,
2236
2237    pub name: Symbol,
2238}
2239
2240pub(crate) mod unexpected_cfg_name {
2241    use rustc_errors::DiagSymbolList;
2242    use rustc_macros::Subdiagnostic;
2243    use rustc_span::{Ident, Span, Symbol};
2244
2245    #[derive(Subdiagnostic)]
2246    pub(crate) enum CodeSuggestion {
2247        #[help(lint_unexpected_cfg_define_features)]
2248        DefineFeatures,
2249        #[suggestion(
2250            lint_unexpected_cfg_name_similar_name_value,
2251            applicability = "maybe-incorrect",
2252            code = "{code}"
2253        )]
2254        SimilarNameAndValue {
2255            #[primary_span]
2256            span: Span,
2257            code: String,
2258        },
2259        #[suggestion(
2260            lint_unexpected_cfg_name_similar_name_no_value,
2261            applicability = "maybe-incorrect",
2262            code = "{code}"
2263        )]
2264        SimilarNameNoValue {
2265            #[primary_span]
2266            span: Span,
2267            code: String,
2268        },
2269        #[suggestion(
2270            lint_unexpected_cfg_name_similar_name_different_values,
2271            applicability = "maybe-incorrect",
2272            code = "{code}"
2273        )]
2274        SimilarNameDifferentValues {
2275            #[primary_span]
2276            span: Span,
2277            code: String,
2278            #[subdiagnostic]
2279            expected: Option<ExpectedValues>,
2280        },
2281        #[suggestion(
2282            lint_unexpected_cfg_name_similar_name,
2283            applicability = "maybe-incorrect",
2284            code = "{code}"
2285        )]
2286        SimilarName {
2287            #[primary_span]
2288            span: Span,
2289            code: String,
2290            #[subdiagnostic]
2291            expected: Option<ExpectedValues>,
2292        },
2293        SimilarValues {
2294            #[subdiagnostic]
2295            with_similar_values: Vec<FoundWithSimilarValue>,
2296            #[subdiagnostic]
2297            expected_names: Option<ExpectedNames>,
2298        },
2299    }
2300
2301    #[derive(Subdiagnostic)]
2302    #[help(lint_unexpected_cfg_name_expected_values)]
2303    pub(crate) struct ExpectedValues {
2304        pub best_match: Symbol,
2305        pub possibilities: DiagSymbolList,
2306    }
2307
2308    #[derive(Subdiagnostic)]
2309    #[suggestion(
2310        lint_unexpected_cfg_name_with_similar_value,
2311        applicability = "maybe-incorrect",
2312        code = "{code}"
2313    )]
2314    pub(crate) struct FoundWithSimilarValue {
2315        #[primary_span]
2316        pub span: Span,
2317        pub code: String,
2318    }
2319
2320    #[derive(Subdiagnostic)]
2321    #[help_once(lint_unexpected_cfg_name_expected_names)]
2322    pub(crate) struct ExpectedNames {
2323        pub possibilities: DiagSymbolList<Ident>,
2324        pub and_more: usize,
2325    }
2326
2327    #[derive(Subdiagnostic)]
2328    pub(crate) enum InvocationHelp {
2329        #[note(lint_unexpected_cfg_doc_cargo)]
2330        Cargo {
2331            #[subdiagnostic]
2332            macro_help: Option<super::UnexpectedCfgCargoMacroHelp>,
2333            #[subdiagnostic]
2334            help: Option<super::UnexpectedCfgCargoHelp>,
2335        },
2336        #[note(lint_unexpected_cfg_doc_rustc)]
2337        Rustc {
2338            #[subdiagnostic]
2339            macro_help: Option<super::UnexpectedCfgRustcMacroHelp>,
2340            #[subdiagnostic]
2341            help: super::UnexpectedCfgRustcHelp,
2342        },
2343    }
2344}
2345
2346#[derive(LintDiagnostic)]
2347#[diag(lint_unexpected_cfg_value)]
2348pub(crate) struct UnexpectedCfgValue {
2349    #[subdiagnostic]
2350    pub code_sugg: unexpected_cfg_value::CodeSuggestion,
2351    #[subdiagnostic]
2352    pub invocation_help: unexpected_cfg_value::InvocationHelp,
2353
2354    pub has_value: bool,
2355    pub value: String,
2356}
2357
2358pub(crate) mod unexpected_cfg_value {
2359    use rustc_errors::DiagSymbolList;
2360    use rustc_macros::Subdiagnostic;
2361    use rustc_span::{Span, Symbol};
2362
2363    #[derive(Subdiagnostic)]
2364    pub(crate) enum CodeSuggestion {
2365        ChangeValue {
2366            #[subdiagnostic]
2367            expected_values: ExpectedValues,
2368            #[subdiagnostic]
2369            suggestion: Option<ChangeValueSuggestion>,
2370        },
2371        #[note(lint_unexpected_cfg_value_no_expected_value)]
2372        RemoveValue {
2373            #[subdiagnostic]
2374            suggestion: Option<RemoveValueSuggestion>,
2375
2376            name: Symbol,
2377        },
2378        #[note(lint_unexpected_cfg_value_no_expected_values)]
2379        RemoveCondition {
2380            #[subdiagnostic]
2381            suggestion: RemoveConditionSuggestion,
2382
2383            name: Symbol,
2384        },
2385    }
2386
2387    #[derive(Subdiagnostic)]
2388    pub(crate) enum ChangeValueSuggestion {
2389        #[suggestion(
2390            lint_unexpected_cfg_value_similar_name,
2391            code = r#""{best_match}""#,
2392            applicability = "maybe-incorrect"
2393        )]
2394        SimilarName {
2395            #[primary_span]
2396            span: Span,
2397            best_match: Symbol,
2398        },
2399        #[suggestion(
2400            lint_unexpected_cfg_value_specify_value,
2401            code = r#" = "{first_possibility}""#,
2402            applicability = "maybe-incorrect"
2403        )]
2404        SpecifyValue {
2405            #[primary_span]
2406            span: Span,
2407            first_possibility: Symbol,
2408        },
2409    }
2410
2411    #[derive(Subdiagnostic)]
2412    #[suggestion(
2413        lint_unexpected_cfg_value_remove_value,
2414        code = "",
2415        applicability = "maybe-incorrect"
2416    )]
2417    pub(crate) struct RemoveValueSuggestion {
2418        #[primary_span]
2419        pub span: Span,
2420    }
2421
2422    #[derive(Subdiagnostic)]
2423    #[suggestion(
2424        lint_unexpected_cfg_value_remove_condition,
2425        code = "",
2426        applicability = "maybe-incorrect"
2427    )]
2428    pub(crate) struct RemoveConditionSuggestion {
2429        #[primary_span]
2430        pub span: Span,
2431    }
2432
2433    #[derive(Subdiagnostic)]
2434    #[note(lint_unexpected_cfg_value_expected_values)]
2435    pub(crate) struct ExpectedValues {
2436        pub name: Symbol,
2437        pub have_none_possibility: bool,
2438        pub possibilities: DiagSymbolList,
2439        pub and_more: usize,
2440    }
2441
2442    #[derive(Subdiagnostic)]
2443    pub(crate) enum InvocationHelp {
2444        #[note(lint_unexpected_cfg_doc_cargo)]
2445        Cargo {
2446            #[subdiagnostic]
2447            help: Option<CargoHelp>,
2448            #[subdiagnostic]
2449            macro_help: Option<super::UnexpectedCfgCargoMacroHelp>,
2450        },
2451        #[note(lint_unexpected_cfg_doc_rustc)]
2452        Rustc {
2453            #[subdiagnostic]
2454            help: Option<super::UnexpectedCfgRustcHelp>,
2455            #[subdiagnostic]
2456            macro_help: Option<super::UnexpectedCfgRustcMacroHelp>,
2457        },
2458    }
2459
2460    #[derive(Subdiagnostic)]
2461    pub(crate) enum CargoHelp {
2462        #[help(lint_unexpected_cfg_value_add_feature)]
2463        AddFeature {
2464            value: Symbol,
2465        },
2466        #[help(lint_unexpected_cfg_define_features)]
2467        DefineFeatures,
2468        Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp),
2469    }
2470}
2471
2472#[derive(LintDiagnostic)]
2473#[diag(lint_unexpected_builtin_cfg)]
2474#[note(lint_controlled_by)]
2475#[note(lint_incoherent)]
2476pub(crate) struct UnexpectedBuiltinCfg {
2477    pub(crate) cfg: String,
2478    pub(crate) cfg_name: Symbol,
2479    pub(crate) controlled_by: &'static str,
2480}
2481
2482#[derive(LintDiagnostic)]
2483#[diag(lint_macro_use_deprecated)]
2484#[help]
2485pub(crate) struct MacroUseDeprecated;
2486
2487#[derive(LintDiagnostic)]
2488#[diag(lint_unused_macro_use)]
2489pub(crate) struct UnusedMacroUse;
2490
2491#[derive(LintDiagnostic)]
2492#[diag(lint_private_extern_crate_reexport, code = E0365)]
2493pub(crate) struct PrivateExternCrateReexport {
2494    pub ident: Ident,
2495    #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")]
2496    pub sugg: Span,
2497}
2498
2499#[derive(LintDiagnostic)]
2500#[diag(lint_unused_label)]
2501pub(crate) struct UnusedLabel;
2502
2503#[derive(LintDiagnostic)]
2504#[diag(lint_macro_is_private)]
2505pub(crate) struct MacroIsPrivate {
2506    pub ident: Ident,
2507}
2508
2509#[derive(LintDiagnostic)]
2510#[diag(lint_unused_macro_definition)]
2511pub(crate) struct UnusedMacroDefinition {
2512    pub name: Symbol,
2513}
2514
2515#[derive(LintDiagnostic)]
2516#[diag(lint_macro_rule_never_used)]
2517pub(crate) struct MacroRuleNeverUsed {
2518    pub n: usize,
2519    pub name: Symbol,
2520}
2521
2522pub(crate) struct UnstableFeature {
2523    pub msg: DiagMessage,
2524}
2525
2526impl<'a> LintDiagnostic<'a, ()> for UnstableFeature {
2527    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2528        diag.primary_message(self.msg);
2529    }
2530}
2531
2532#[derive(LintDiagnostic)]
2533#[diag(lint_avoid_intel_syntax)]
2534pub(crate) struct AvoidIntelSyntax;
2535
2536#[derive(LintDiagnostic)]
2537#[diag(lint_avoid_att_syntax)]
2538pub(crate) struct AvoidAttSyntax;
2539
2540#[derive(LintDiagnostic)]
2541#[diag(lint_incomplete_include)]
2542pub(crate) struct IncompleteInclude;
2543
2544#[derive(LintDiagnostic)]
2545#[diag(lint_unnameable_test_items)]
2546pub(crate) struct UnnameableTestItems;
2547
2548#[derive(LintDiagnostic)]
2549#[diag(lint_duplicate_macro_attribute)]
2550pub(crate) struct DuplicateMacroAttribute;
2551
2552#[derive(LintDiagnostic)]
2553#[diag(lint_cfg_attr_no_attributes)]
2554pub(crate) struct CfgAttrNoAttributes;
2555
2556#[derive(LintDiagnostic)]
2557#[diag(lint_missing_fragment_specifier)]
2558pub(crate) struct MissingFragmentSpecifier;
2559
2560#[derive(LintDiagnostic)]
2561#[diag(lint_metavariable_still_repeating)]
2562pub(crate) struct MetaVariableStillRepeating {
2563    pub name: MacroRulesNormalizedIdent,
2564}
2565
2566#[derive(LintDiagnostic)]
2567#[diag(lint_metavariable_wrong_operator)]
2568pub(crate) struct MetaVariableWrongOperator;
2569
2570#[derive(LintDiagnostic)]
2571#[diag(lint_duplicate_matcher_binding)]
2572pub(crate) struct DuplicateMatcherBinding;
2573
2574#[derive(LintDiagnostic)]
2575#[diag(lint_unknown_macro_variable)]
2576pub(crate) struct UnknownMacroVariable {
2577    pub name: MacroRulesNormalizedIdent,
2578}
2579
2580#[derive(LintDiagnostic)]
2581#[diag(lint_unused_crate_dependency)]
2582#[help]
2583pub(crate) struct UnusedCrateDependency {
2584    pub extern_crate: Symbol,
2585    pub local_crate: Symbol,
2586}
2587
2588#[derive(LintDiagnostic)]
2589#[diag(lint_ill_formed_attribute_input)]
2590pub(crate) struct IllFormedAttributeInput {
2591    pub num_suggestions: usize,
2592    pub suggestions: DiagArgValue,
2593}
2594
2595#[derive(LintDiagnostic)]
2596pub(crate) enum InnerAttributeUnstable {
2597    #[diag(lint_inner_macro_attribute_unstable)]
2598    InnerMacroAttribute,
2599    #[diag(lint_custom_inner_attribute_unstable)]
2600    CustomInnerAttribute,
2601}
2602
2603#[derive(LintDiagnostic)]
2604#[diag(lint_unknown_diagnostic_attribute)]
2605pub(crate) struct UnknownDiagnosticAttribute {
2606    #[subdiagnostic]
2607    pub typo: Option<UnknownDiagnosticAttributeTypoSugg>,
2608}
2609
2610#[derive(Subdiagnostic)]
2611#[suggestion(
2612    lint_unknown_diagnostic_attribute_typo_sugg,
2613    style = "verbose",
2614    code = "{typo_name}",
2615    applicability = "machine-applicable"
2616)]
2617pub(crate) struct UnknownDiagnosticAttributeTypoSugg {
2618    #[primary_span]
2619    pub span: Span,
2620    pub typo_name: Symbol,
2621}
2622
2623#[derive(LintDiagnostic)]
2624#[diag(lint_unicode_text_flow)]
2625#[note]
2626pub(crate) struct UnicodeTextFlow {
2627    #[label]
2628    pub comment_span: Span,
2629    #[subdiagnostic]
2630    pub characters: Vec<UnicodeCharNoteSub>,
2631    #[subdiagnostic]
2632    pub suggestions: Option<UnicodeTextFlowSuggestion>,
2633
2634    pub num_codepoints: usize,
2635}
2636
2637#[derive(Subdiagnostic)]
2638#[label(lint_label_comment_char)]
2639pub(crate) struct UnicodeCharNoteSub {
2640    #[primary_span]
2641    pub span: Span,
2642    pub c_debug: String,
2643}
2644
2645#[derive(Subdiagnostic)]
2646#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")]
2647pub(crate) struct UnicodeTextFlowSuggestion {
2648    #[suggestion_part(code = "")]
2649    pub spans: Vec<Span>,
2650}
2651
2652#[derive(LintDiagnostic)]
2653#[diag(lint_abs_path_with_module)]
2654pub(crate) struct AbsPathWithModule {
2655    #[subdiagnostic]
2656    pub sugg: AbsPathWithModuleSugg,
2657}
2658
2659#[derive(Subdiagnostic)]
2660#[suggestion(lint_suggestion, code = "{replacement}")]
2661pub(crate) struct AbsPathWithModuleSugg {
2662    #[primary_span]
2663    pub span: Span,
2664    #[applicability]
2665    pub applicability: Applicability,
2666    pub replacement: String,
2667}
2668
2669#[derive(LintDiagnostic)]
2670#[diag(lint_proc_macro_derive_resolution_fallback)]
2671pub(crate) struct ProcMacroDeriveResolutionFallback {
2672    #[label]
2673    pub span: Span,
2674    pub ns: Namespace,
2675    pub ident: Ident,
2676}
2677
2678#[derive(LintDiagnostic)]
2679#[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)]
2680pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths {
2681    #[note]
2682    pub definition: Span,
2683}
2684
2685#[derive(LintDiagnostic)]
2686#[diag(lint_hidden_lifetime_parameters)]
2687pub(crate) struct ElidedLifetimesInPaths {
2688    #[subdiagnostic]
2689    pub subdiag: ElidedLifetimeInPathSubdiag,
2690}
2691
2692pub(crate) struct ElidedNamedLifetime {
2693    pub span: Span,
2694    pub kind: MissingLifetimeKind,
2695    pub name: Symbol,
2696    pub declaration: Option<Span>,
2697}
2698
2699impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime {
2700    fn decorate_lint(self, diag: &mut rustc_errors::Diag<'_, G>) {
2701        let Self { span, kind, name, declaration } = self;
2702        diag.primary_message(fluent::lint_elided_named_lifetime);
2703        diag.arg("name", name);
2704        diag.span_label(span, fluent::lint_label_elided);
2705        if let Some(declaration) = declaration {
2706            diag.span_label(declaration, fluent::lint_label_named);
2707        }
2708        // FIXME(GrigorenkoPV): this `if` and `return` should be removed,
2709        //  but currently this lint's suggestions can conflict with those of `clippy::needless_lifetimes`:
2710        //  https://github.com/rust-lang/rust/pull/129840#issuecomment-2323349119
2711        // HACK: `'static` suggestions will never sonflict, emit only those for now.
2712        if name != kw::StaticLifetime {
2713            return;
2714        }
2715        match kind {
2716            MissingLifetimeKind::Underscore => diag.span_suggestion_verbose(
2717                span,
2718                fluent::lint_suggestion,
2719                format!("{name}"),
2720                Applicability::MachineApplicable,
2721            ),
2722            MissingLifetimeKind::Ampersand => diag.span_suggestion_verbose(
2723                span.shrink_to_hi(),
2724                fluent::lint_suggestion,
2725                format!("{name} "),
2726                Applicability::MachineApplicable,
2727            ),
2728            MissingLifetimeKind::Comma => diag.span_suggestion_verbose(
2729                span.shrink_to_hi(),
2730                fluent::lint_suggestion,
2731                format!("{name}, "),
2732                Applicability::MachineApplicable,
2733            ),
2734            MissingLifetimeKind::Brackets => diag.span_suggestion_verbose(
2735                span.shrink_to_hi(),
2736                fluent::lint_suggestion,
2737                format!("<{name}>"),
2738                Applicability::MachineApplicable,
2739            ),
2740        };
2741    }
2742}
2743
2744#[derive(LintDiagnostic)]
2745#[diag(lint_invalid_crate_type_value)]
2746pub(crate) struct UnknownCrateTypes {
2747    #[subdiagnostic]
2748    pub sugg: Option<UnknownCrateTypesSub>,
2749}
2750
2751#[derive(Subdiagnostic)]
2752#[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")]
2753pub(crate) struct UnknownCrateTypesSub {
2754    #[primary_span]
2755    pub span: Span,
2756    pub candidate: Symbol,
2757}
2758
2759#[derive(LintDiagnostic)]
2760#[diag(lint_unused_imports)]
2761pub(crate) struct UnusedImports {
2762    #[subdiagnostic]
2763    pub sugg: UnusedImportsSugg,
2764    #[help]
2765    pub test_module_span: Option<Span>,
2766
2767    pub span_snippets: DiagArgValue,
2768    pub num_snippets: usize,
2769}
2770
2771#[derive(Subdiagnostic)]
2772pub(crate) enum UnusedImportsSugg {
2773    #[suggestion(
2774        lint_suggestion_remove_whole_use,
2775        applicability = "machine-applicable",
2776        code = "",
2777        style = "tool-only"
2778    )]
2779    RemoveWholeUse {
2780        #[primary_span]
2781        span: Span,
2782    },
2783    #[multipart_suggestion(
2784        lint_suggestion_remove_imports,
2785        applicability = "machine-applicable",
2786        style = "tool-only"
2787    )]
2788    RemoveImports {
2789        #[suggestion_part(code = "")]
2790        remove_spans: Vec<Span>,
2791        num_to_remove: usize,
2792    },
2793}
2794
2795#[derive(LintDiagnostic)]
2796#[diag(lint_redundant_import)]
2797pub(crate) struct RedundantImport {
2798    #[subdiagnostic]
2799    pub subs: Vec<RedundantImportSub>,
2800
2801    pub ident: Ident,
2802}
2803
2804#[derive(Subdiagnostic)]
2805pub(crate) enum RedundantImportSub {
2806    #[label(lint_label_imported_here)]
2807    ImportedHere(#[primary_span] Span),
2808    #[label(lint_label_defined_here)]
2809    DefinedHere(#[primary_span] Span),
2810    #[label(lint_label_imported_prelude)]
2811    ImportedPrelude(#[primary_span] Span),
2812    #[label(lint_label_defined_prelude)]
2813    DefinedPrelude(#[primary_span] Span),
2814}
2815
2816#[derive(LintDiagnostic)]
2817#[diag(lint_unused_doc_comment)]
2818#[help]
2819pub(crate) struct UnusedDocComment {
2820    #[label]
2821    pub span: Span,
2822}
2823
2824#[derive(LintDiagnostic)]
2825pub(crate) enum PatternsInFnsWithoutBody {
2826    #[diag(lint_pattern_in_foreign)]
2827    Foreign {
2828        #[subdiagnostic]
2829        sub: PatternsInFnsWithoutBodySub,
2830    },
2831    #[diag(lint_pattern_in_bodiless)]
2832    Bodiless {
2833        #[subdiagnostic]
2834        sub: PatternsInFnsWithoutBodySub,
2835    },
2836}
2837
2838#[derive(Subdiagnostic)]
2839#[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")]
2840pub(crate) struct PatternsInFnsWithoutBodySub {
2841    #[primary_span]
2842    pub span: Span,
2843
2844    pub ident: Ident,
2845}
2846
2847#[derive(LintDiagnostic)]
2848#[diag(lint_extern_without_abi)]
2849pub(crate) struct MissingAbi {
2850    #[suggestion(code = "extern {default_abi}", applicability = "machine-applicable")]
2851    pub span: Span,
2852    pub default_abi: ExternAbi,
2853}
2854
2855#[derive(LintDiagnostic)]
2856#[diag(lint_legacy_derive_helpers)]
2857pub(crate) struct LegacyDeriveHelpers {
2858    #[label]
2859    pub span: Span,
2860}
2861
2862#[derive(LintDiagnostic)]
2863#[diag(lint_or_patterns_back_compat)]
2864pub(crate) struct OrPatternsBackCompat {
2865    #[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
2866    pub span: Span,
2867    pub suggestion: String,
2868}
2869
2870#[derive(LintDiagnostic)]
2871#[diag(lint_reserved_prefix)]
2872pub(crate) struct ReservedPrefix {
2873    #[label]
2874    pub label: Span,
2875    #[suggestion(code = " ", applicability = "machine-applicable")]
2876    pub suggestion: Span,
2877
2878    pub prefix: String,
2879}
2880
2881#[derive(LintDiagnostic)]
2882#[diag(lint_raw_prefix)]
2883pub(crate) struct RawPrefix {
2884    #[label]
2885    pub label: Span,
2886    #[suggestion(code = " ", applicability = "machine-applicable")]
2887    pub suggestion: Span,
2888}
2889
2890#[derive(LintDiagnostic)]
2891#[diag(lint_unused_builtin_attribute)]
2892pub(crate) struct UnusedBuiltinAttribute {
2893    #[note]
2894    pub invoc_span: Span,
2895
2896    pub attr_name: Symbol,
2897    pub macro_name: String,
2898}
2899
2900#[derive(LintDiagnostic)]
2901#[diag(lint_trailing_semi_macro)]
2902pub(crate) struct TrailingMacro {
2903    #[note(lint_note1)]
2904    #[note(lint_note2)]
2905    pub is_trailing: bool,
2906
2907    pub name: Ident,
2908}
2909
2910#[derive(LintDiagnostic)]
2911#[diag(lint_break_with_label_and_loop)]
2912pub(crate) struct BreakWithLabelAndLoop {
2913    #[subdiagnostic]
2914    pub sub: BreakWithLabelAndLoopSub,
2915}
2916
2917#[derive(Subdiagnostic)]
2918#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2919pub(crate) struct BreakWithLabelAndLoopSub {
2920    #[suggestion_part(code = "(")]
2921    pub left: Span,
2922    #[suggestion_part(code = ")")]
2923    pub right: Span,
2924}
2925
2926#[derive(LintDiagnostic)]
2927#[diag(lint_deprecated_where_clause_location)]
2928#[note]
2929pub(crate) struct DeprecatedWhereClauseLocation {
2930    #[subdiagnostic]
2931    pub suggestion: DeprecatedWhereClauseLocationSugg,
2932}
2933
2934#[derive(Subdiagnostic)]
2935pub(crate) enum DeprecatedWhereClauseLocationSugg {
2936    #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")]
2937    MoveToEnd {
2938        #[suggestion_part(code = "")]
2939        left: Span,
2940        #[suggestion_part(code = "{sugg}")]
2941        right: Span,
2942
2943        sugg: String,
2944    },
2945    #[suggestion(lint_suggestion_remove_where, code = "", applicability = "machine-applicable")]
2946    RemoveWhere {
2947        #[primary_span]
2948        span: Span,
2949    },
2950}
2951
2952#[derive(LintDiagnostic)]
2953#[diag(lint_missing_unsafe_on_extern)]
2954pub(crate) struct MissingUnsafeOnExtern {
2955    #[suggestion(code = "unsafe ", applicability = "machine-applicable")]
2956    pub suggestion: Span,
2957}
2958
2959#[derive(LintDiagnostic)]
2960#[diag(lint_single_use_lifetime)]
2961pub(crate) struct SingleUseLifetime {
2962    #[label(lint_label_param)]
2963    pub param_span: Span,
2964    #[label(lint_label_use)]
2965    pub use_span: Span,
2966    #[subdiagnostic]
2967    pub suggestion: Option<SingleUseLifetimeSugg>,
2968
2969    pub ident: Ident,
2970}
2971
2972#[derive(Subdiagnostic)]
2973#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2974pub(crate) struct SingleUseLifetimeSugg {
2975    #[suggestion_part(code = "")]
2976    pub deletion_span: Option<Span>,
2977    #[suggestion_part(code = "{replace_lt}")]
2978    pub use_span: Span,
2979
2980    pub replace_lt: String,
2981}
2982
2983#[derive(LintDiagnostic)]
2984#[diag(lint_unused_lifetime)]
2985pub(crate) struct UnusedLifetime {
2986    #[suggestion(code = "", applicability = "machine-applicable")]
2987    pub deletion_span: Option<Span>,
2988
2989    pub ident: Ident,
2990}
2991
2992#[derive(LintDiagnostic)]
2993#[diag(lint_named_argument_used_positionally)]
2994pub(crate) struct NamedArgumentUsedPositionally {
2995    #[label(lint_label_named_arg)]
2996    pub named_arg_sp: Span,
2997    #[label(lint_label_position_arg)]
2998    pub position_label_sp: Option<Span>,
2999    #[suggestion(style = "verbose", code = "{name}", applicability = "maybe-incorrect")]
3000    pub suggestion: Option<Span>,
3001
3002    pub name: String,
3003    pub named_arg_name: String,
3004}
3005
3006#[derive(LintDiagnostic)]
3007#[diag(lint_byte_slice_in_packed_struct_with_derive)]
3008#[help]
3009pub(crate) struct ByteSliceInPackedStructWithDerive {
3010    // FIXME: make this translatable
3011    pub ty: String,
3012}
3013
3014#[derive(LintDiagnostic)]
3015#[diag(lint_unused_extern_crate)]
3016pub(crate) struct UnusedExternCrate {
3017    #[suggestion(code = "", applicability = "machine-applicable")]
3018    pub removal_span: Span,
3019}
3020
3021#[derive(LintDiagnostic)]
3022#[diag(lint_extern_crate_not_idiomatic)]
3023pub(crate) struct ExternCrateNotIdiomatic {
3024    #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")]
3025    pub span: Span,
3026
3027    pub code: &'static str,
3028}
3029
3030// FIXME: make this translatable
3031pub(crate) struct AmbiguousGlobImports {
3032    pub ambiguity: AmbiguityErrorDiag,
3033}
3034
3035impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports {
3036    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
3037        diag.primary_message(self.ambiguity.msg.clone());
3038        rustc_errors::report_ambiguity_error(diag, self.ambiguity);
3039    }
3040}
3041
3042#[derive(LintDiagnostic)]
3043#[diag(lint_ambiguous_glob_reexport)]
3044pub(crate) struct AmbiguousGlobReexports {
3045    #[label(lint_label_first_reexport)]
3046    pub first_reexport: Span,
3047    #[label(lint_label_duplicate_reexport)]
3048    pub duplicate_reexport: Span,
3049
3050    pub name: String,
3051    // FIXME: make this translatable
3052    pub namespace: String,
3053}
3054
3055#[derive(LintDiagnostic)]
3056#[diag(lint_hidden_glob_reexport)]
3057pub(crate) struct HiddenGlobReexports {
3058    #[note(lint_note_glob_reexport)]
3059    pub glob_reexport: Span,
3060    #[note(lint_note_private_item)]
3061    pub private_item: Span,
3062
3063    pub name: String,
3064    // FIXME: make this translatable
3065    pub namespace: String,
3066}
3067
3068#[derive(LintDiagnostic)]
3069#[diag(lint_unnecessary_qualification)]
3070pub(crate) struct UnusedQualifications {
3071    #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
3072    pub removal_span: Span,
3073}
3074
3075#[derive(LintDiagnostic)]
3076#[diag(lint_associated_const_elided_lifetime)]
3077pub(crate) struct AssociatedConstElidedLifetime {
3078    #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")]
3079    pub span: Span,
3080
3081    pub code: &'static str,
3082    pub elided: bool,
3083    #[note]
3084    pub lifetimes_in_scope: MultiSpan,
3085}
3086
3087#[derive(LintDiagnostic)]
3088#[diag(lint_redundant_import_visibility)]
3089pub(crate) struct RedundantImportVisibility {
3090    #[note]
3091    pub span: Span,
3092    #[help]
3093    pub help: (),
3094
3095    pub import_vis: String,
3096    pub max_vis: String,
3097}
3098
3099#[derive(LintDiagnostic)]
3100#[diag(lint_unsafe_attr_outside_unsafe)]
3101pub(crate) struct UnsafeAttrOutsideUnsafe {
3102    #[label]
3103    pub span: Span,
3104    #[subdiagnostic]
3105    pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
3106}
3107
3108#[derive(Subdiagnostic)]
3109#[multipart_suggestion(
3110    lint_unsafe_attr_outside_unsafe_suggestion,
3111    applicability = "machine-applicable"
3112)]
3113pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
3114    #[suggestion_part(code = "unsafe(")]
3115    pub left: Span,
3116    #[suggestion_part(code = ")")]
3117    pub right: Span,
3118}
3119
3120#[derive(LintDiagnostic)]
3121#[diag(lint_out_of_scope_macro_calls)]
3122#[help]
3123pub(crate) struct OutOfScopeMacroCalls {
3124    #[label]
3125    pub span: Span,
3126    pub path: String,
3127    pub location: String,
3128}
3129
3130#[derive(LintDiagnostic)]
3131#[diag(lint_static_mut_refs_lint)]
3132pub(crate) struct RefOfMutStatic<'a> {
3133    #[label]
3134    pub span: Span,
3135    #[subdiagnostic]
3136    pub sugg: Option<MutRefSugg>,
3137    pub shared_label: &'a str,
3138    #[note(lint_shared_note)]
3139    pub shared_note: bool,
3140    #[note(lint_mut_note)]
3141    pub mut_note: bool,
3142}
3143
3144#[derive(Subdiagnostic)]
3145pub(crate) enum MutRefSugg {
3146    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
3147    Shared {
3148        #[suggestion_part(code = "&raw const ")]
3149        span: Span,
3150    },
3151    #[multipart_suggestion(
3152        lint_suggestion_mut,
3153        style = "verbose",
3154        applicability = "maybe-incorrect"
3155    )]
3156    Mut {
3157        #[suggestion_part(code = "&raw mut ")]
3158        span: Span,
3159    },
3160}
3161
3162#[derive(LintDiagnostic)]
3163#[diag(lint_unqualified_local_imports)]
3164pub(crate) struct UnqualifiedLocalImportsDiag {}
3165
3166#[derive(LintDiagnostic)]
3167#[diag(lint_reserved_string)]
3168pub(crate) struct ReservedString {
3169    #[suggestion(code = " ", applicability = "machine-applicable")]
3170    pub suggestion: Span,
3171}
3172
3173#[derive(LintDiagnostic)]
3174#[diag(lint_reserved_multihash)]
3175pub(crate) struct ReservedMultihash {
3176    #[suggestion(code = " ", applicability = "machine-applicable")]
3177    pub suggestion: Span,
3178}