rustc_lint/
lints.rs

1// ignore-tidy-filelength
2
3#![allow(rustc::untranslatable_diagnostic)]
4use std::num::NonZero;
5
6use rustc_errors::codes::*;
7use rustc_errors::{
8    Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag,
9    EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle,
10};
11use rustc_hir as hir;
12use rustc_hir::def_id::DefId;
13use rustc_hir::intravisit::VisitorExt;
14use rustc_macros::{LintDiagnostic, Subdiagnostic};
15use rustc_middle::ty::inhabitedness::InhabitedPredicate;
16use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt};
17use rustc_session::Session;
18use rustc_span::edition::Edition;
19use rustc_span::{Ident, Span, Symbol, sym};
20
21use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds};
22use crate::errors::{OverruledAttributeSub, RequestedLevel};
23use crate::lifetime_syntax::LifetimeSyntaxCategories;
24use crate::{LateContext, fluent_generated as fluent};
25
26// array_into_iter.rs
27#[derive(LintDiagnostic)]
28#[diag(lint_shadowed_into_iter)]
29pub(crate) struct ShadowedIntoIterDiag {
30    pub target: &'static str,
31    pub edition: &'static str,
32    #[suggestion(lint_use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
33    pub suggestion: Span,
34    #[subdiagnostic]
35    pub sub: Option<ShadowedIntoIterDiagSub>,
36}
37
38#[derive(Subdiagnostic)]
39pub(crate) enum ShadowedIntoIterDiagSub {
40    #[suggestion(lint_remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
41    RemoveIntoIter {
42        #[primary_span]
43        span: Span,
44    },
45    #[multipart_suggestion(
46        lint_use_explicit_into_iter_suggestion,
47        applicability = "maybe-incorrect"
48    )]
49    UseExplicitIntoIter {
50        #[suggestion_part(code = "IntoIterator::into_iter(")]
51        start_span: Span,
52        #[suggestion_part(code = ")")]
53        end_span: Span,
54    },
55}
56
57// autorefs.rs
58#[derive(LintDiagnostic)]
59#[diag(lint_implicit_unsafe_autorefs)]
60#[note]
61pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> {
62    #[label(lint_raw_ptr)]
63    pub raw_ptr_span: Span,
64    pub raw_ptr_ty: Ty<'a>,
65    #[subdiagnostic]
66    pub origin: ImplicitUnsafeAutorefsOrigin<'a>,
67    #[subdiagnostic]
68    pub method: Option<ImplicitUnsafeAutorefsMethodNote>,
69    #[subdiagnostic]
70    pub suggestion: ImplicitUnsafeAutorefsSuggestion,
71}
72
73#[derive(Subdiagnostic)]
74pub(crate) enum ImplicitUnsafeAutorefsOrigin<'a> {
75    #[note(lint_autoref)]
76    Autoref {
77        #[primary_span]
78        autoref_span: Span,
79        autoref_ty: Ty<'a>,
80    },
81    #[note(lint_overloaded_deref)]
82    OverloadedDeref,
83}
84
85#[derive(Subdiagnostic)]
86#[note(lint_method_def)]
87pub(crate) struct ImplicitUnsafeAutorefsMethodNote {
88    #[primary_span]
89    pub def_span: Span,
90    pub method_name: Symbol,
91}
92
93#[derive(Subdiagnostic)]
94#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
95pub(crate) struct ImplicitUnsafeAutorefsSuggestion {
96    pub mutbl: &'static str,
97    pub deref: &'static str,
98    #[suggestion_part(code = "({mutbl}{deref}")]
99    pub start_span: Span,
100    #[suggestion_part(code = ")")]
101    pub end_span: Span,
102}
103
104// builtin.rs
105#[derive(LintDiagnostic)]
106#[diag(lint_builtin_while_true)]
107pub(crate) struct BuiltinWhileTrue {
108    #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")]
109    pub suggestion: Span,
110    pub replace: String,
111}
112
113#[derive(LintDiagnostic)]
114#[diag(lint_builtin_non_shorthand_field_patterns)]
115pub(crate) struct BuiltinNonShorthandFieldPatterns {
116    pub ident: Ident,
117    #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")]
118    pub suggestion: Span,
119    pub prefix: &'static str,
120}
121
122#[derive(LintDiagnostic)]
123pub(crate) enum BuiltinUnsafe {
124    #[diag(lint_builtin_allow_internal_unsafe)]
125    AllowInternalUnsafe,
126    #[diag(lint_builtin_unsafe_block)]
127    UnsafeBlock,
128    #[diag(lint_builtin_unsafe_extern_block)]
129    UnsafeExternBlock,
130    #[diag(lint_builtin_unsafe_trait)]
131    UnsafeTrait,
132    #[diag(lint_builtin_unsafe_impl)]
133    UnsafeImpl,
134    #[diag(lint_builtin_no_mangle_fn)]
135    #[note(lint_builtin_overridden_symbol_name)]
136    NoMangleFn,
137    #[diag(lint_builtin_export_name_fn)]
138    #[note(lint_builtin_overridden_symbol_name)]
139    ExportNameFn,
140    #[diag(lint_builtin_link_section_fn)]
141    #[note(lint_builtin_overridden_symbol_section)]
142    LinkSectionFn,
143    #[diag(lint_builtin_no_mangle_static)]
144    #[note(lint_builtin_overridden_symbol_name)]
145    NoMangleStatic,
146    #[diag(lint_builtin_export_name_static)]
147    #[note(lint_builtin_overridden_symbol_name)]
148    ExportNameStatic,
149    #[diag(lint_builtin_link_section_static)]
150    #[note(lint_builtin_overridden_symbol_section)]
151    LinkSectionStatic,
152    #[diag(lint_builtin_no_mangle_method)]
153    #[note(lint_builtin_overridden_symbol_name)]
154    NoMangleMethod,
155    #[diag(lint_builtin_export_name_method)]
156    #[note(lint_builtin_overridden_symbol_name)]
157    ExportNameMethod,
158    #[diag(lint_builtin_decl_unsafe_fn)]
159    DeclUnsafeFn,
160    #[diag(lint_builtin_decl_unsafe_method)]
161    DeclUnsafeMethod,
162    #[diag(lint_builtin_impl_unsafe_method)]
163    ImplUnsafeMethod,
164    #[diag(lint_builtin_global_asm)]
165    #[note(lint_builtin_global_macro_unsafety)]
166    GlobalAsm,
167}
168
169#[derive(LintDiagnostic)]
170#[diag(lint_builtin_missing_doc)]
171pub(crate) struct BuiltinMissingDoc<'a> {
172    pub article: &'a str,
173    pub desc: &'a str,
174}
175
176#[derive(LintDiagnostic)]
177#[diag(lint_builtin_missing_copy_impl)]
178pub(crate) struct BuiltinMissingCopyImpl;
179
180pub(crate) struct BuiltinMissingDebugImpl<'a> {
181    pub tcx: TyCtxt<'a>,
182    pub def_id: DefId,
183}
184
185// Needed for def_path_str
186impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> {
187    fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
188        diag.primary_message(fluent::lint_builtin_missing_debug_impl);
189        diag.arg("debug", self.tcx.def_path_str(self.def_id));
190    }
191}
192
193#[derive(LintDiagnostic)]
194#[diag(lint_builtin_anonymous_params)]
195pub(crate) struct BuiltinAnonymousParams<'a> {
196    #[suggestion(code = "_: {ty_snip}")]
197    pub suggestion: (Span, Applicability),
198    pub ty_snip: &'a str,
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: Option<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// interior_mutable_consts.rs
787#[derive(LintDiagnostic)]
788#[diag(lint_const_item_interior_mutations)]
789#[note(lint_temporary)]
790#[note(lint_never_original)]
791#[help]
792pub(crate) struct ConstItemInteriorMutationsDiag<'tcx> {
793    pub method_name: Ident,
794    pub const_name: Ident,
795    pub const_ty: Ty<'tcx>,
796    #[label]
797    pub receiver_span: Span,
798    #[subdiagnostic]
799    pub sugg_static: Option<ConstItemInteriorMutationsSuggestionStatic>,
800}
801
802#[derive(Subdiagnostic)]
803pub(crate) enum ConstItemInteriorMutationsSuggestionStatic {
804    #[suggestion(
805        lint_suggestion_static,
806        code = "{before}static ",
807        style = "verbose",
808        applicability = "maybe-incorrect"
809    )]
810    Spanful {
811        #[primary_span]
812        const_: Span,
813        before: &'static str,
814    },
815    #[help(lint_suggestion_static)]
816    Spanless,
817}
818
819// reference_casting.rs
820#[derive(LintDiagnostic)]
821pub(crate) enum InvalidReferenceCastingDiag<'tcx> {
822    #[diag(lint_invalid_reference_casting_borrow_as_mut)]
823    #[note(lint_invalid_reference_casting_note_book)]
824    BorrowAsMut {
825        #[label]
826        orig_cast: Option<Span>,
827        #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
828        ty_has_interior_mutability: bool,
829    },
830    #[diag(lint_invalid_reference_casting_assign_to_ref)]
831    #[note(lint_invalid_reference_casting_note_book)]
832    AssignToRef {
833        #[label]
834        orig_cast: Option<Span>,
835        #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
836        ty_has_interior_mutability: bool,
837    },
838    #[diag(lint_invalid_reference_casting_bigger_layout)]
839    #[note(lint_layout)]
840    BiggerLayout {
841        #[label]
842        orig_cast: Option<Span>,
843        #[label(lint_alloc)]
844        alloc: Span,
845        from_ty: Ty<'tcx>,
846        from_size: u64,
847        to_ty: Ty<'tcx>,
848        to_size: u64,
849    },
850}
851
852// map_unit_fn.rs
853#[derive(LintDiagnostic)]
854#[diag(lint_map_unit_fn)]
855#[note]
856pub(crate) struct MappingToUnit {
857    #[label(lint_function_label)]
858    pub function_label: Span,
859    #[label(lint_argument_label)]
860    pub argument_label: Span,
861    #[label(lint_map_label)]
862    pub map_label: Span,
863    #[suggestion(style = "verbose", code = "for_each", applicability = "maybe-incorrect")]
864    pub suggestion: Span,
865}
866
867// internal.rs
868#[derive(LintDiagnostic)]
869#[diag(lint_default_hash_types)]
870#[note]
871pub(crate) struct DefaultHashTypesDiag<'a> {
872    pub preferred: &'a str,
873    pub used: Symbol,
874}
875
876#[derive(LintDiagnostic)]
877#[diag(lint_query_instability)]
878#[note]
879pub(crate) struct QueryInstability {
880    pub query: Symbol,
881}
882
883#[derive(LintDiagnostic)]
884#[diag(lint_query_untracked)]
885#[note]
886pub(crate) struct QueryUntracked {
887    pub method: Symbol,
888}
889
890#[derive(LintDiagnostic)]
891#[diag(lint_span_use_eq_ctxt)]
892pub(crate) struct SpanUseEqCtxtDiag;
893
894#[derive(LintDiagnostic)]
895#[diag(lint_symbol_intern_string_literal)]
896#[help]
897pub(crate) struct SymbolInternStringLiteralDiag;
898
899#[derive(LintDiagnostic)]
900#[diag(lint_tykind_kind)]
901pub(crate) struct TykindKind {
902    #[suggestion(code = "ty", applicability = "maybe-incorrect")]
903    pub suggestion: Span,
904}
905
906#[derive(LintDiagnostic)]
907#[diag(lint_tykind)]
908#[help]
909pub(crate) struct TykindDiag;
910
911#[derive(LintDiagnostic)]
912#[diag(lint_ty_qualified)]
913pub(crate) struct TyQualified {
914    pub ty: String,
915    #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
916    pub suggestion: Span,
917}
918
919#[derive(LintDiagnostic)]
920#[diag(lint_type_ir_inherent_usage)]
921#[note]
922pub(crate) struct TypeIrInherentUsage;
923
924#[derive(LintDiagnostic)]
925#[diag(lint_type_ir_trait_usage)]
926#[note]
927pub(crate) struct TypeIrTraitUsage;
928
929#[derive(LintDiagnostic)]
930#[diag(lint_type_ir_direct_use)]
931#[note]
932pub(crate) struct TypeIrDirectUse;
933
934#[derive(LintDiagnostic)]
935#[diag(lint_non_glob_import_type_ir_inherent)]
936pub(crate) struct NonGlobImportTypeIrInherent {
937    #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")]
938    pub suggestion: Option<Span>,
939    pub snippet: &'static str,
940}
941
942#[derive(LintDiagnostic)]
943#[diag(lint_lintpass_by_hand)]
944#[help]
945pub(crate) struct LintPassByHand;
946
947#[derive(LintDiagnostic)]
948#[diag(lint_diag_out_of_impl)]
949pub(crate) struct DiagOutOfImpl;
950
951#[derive(LintDiagnostic)]
952#[diag(lint_untranslatable_diag)]
953pub(crate) struct UntranslatableDiag;
954
955#[derive(LintDiagnostic)]
956#[diag(lint_bad_opt_access)]
957pub(crate) struct BadOptAccessDiag<'a> {
958    pub msg: &'a str,
959}
960
961#[derive(LintDiagnostic)]
962#[diag(lint_implicit_sysroot_crate_import)]
963#[help]
964pub(crate) struct ImplicitSysrootCrateImportDiag<'a> {
965    pub name: &'a str,
966}
967
968// let_underscore.rs
969#[derive(LintDiagnostic)]
970pub(crate) enum NonBindingLet {
971    #[diag(lint_non_binding_let_on_sync_lock)]
972    SyncLock {
973        #[label]
974        pat: Span,
975        #[subdiagnostic]
976        sub: NonBindingLetSub,
977    },
978    #[diag(lint_non_binding_let_on_drop_type)]
979    DropType {
980        #[subdiagnostic]
981        sub: NonBindingLetSub,
982    },
983}
984
985pub(crate) struct NonBindingLetSub {
986    pub suggestion: Span,
987    pub drop_fn_start_end: Option<(Span, Span)>,
988    pub is_assign_desugar: bool,
989}
990
991impl Subdiagnostic for NonBindingLetSub {
992    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
993        let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
994
995        if can_suggest_binding {
996            let prefix = if self.is_assign_desugar { "let " } else { "" };
997            diag.span_suggestion_verbose(
998                self.suggestion,
999                fluent::lint_non_binding_let_suggestion,
1000                format!("{prefix}_unused"),
1001                Applicability::MachineApplicable,
1002            );
1003        } else {
1004            diag.span_help(self.suggestion, fluent::lint_non_binding_let_suggestion);
1005        }
1006        if let Some(drop_fn_start_end) = self.drop_fn_start_end {
1007            diag.multipart_suggestion(
1008                fluent::lint_non_binding_let_multi_suggestion,
1009                vec![
1010                    (drop_fn_start_end.0, "drop(".to_string()),
1011                    (drop_fn_start_end.1, ")".to_string()),
1012                ],
1013                Applicability::MachineApplicable,
1014            );
1015        } else {
1016            diag.help(fluent::lint_non_binding_let_multi_drop_fn);
1017        }
1018    }
1019}
1020
1021// levels.rs
1022#[derive(LintDiagnostic)]
1023#[diag(lint_overruled_attribute)]
1024pub(crate) struct OverruledAttributeLint<'a> {
1025    #[label]
1026    pub overruled: Span,
1027    pub lint_level: &'a str,
1028    pub lint_source: Symbol,
1029    #[subdiagnostic]
1030    pub sub: OverruledAttributeSub,
1031}
1032
1033#[derive(LintDiagnostic)]
1034#[diag(lint_deprecated_lint_name)]
1035pub(crate) struct DeprecatedLintName<'a> {
1036    pub name: String,
1037    #[suggestion(code = "{replace}", applicability = "machine-applicable")]
1038    pub suggestion: Span,
1039    pub replace: &'a str,
1040}
1041
1042#[derive(LintDiagnostic)]
1043#[diag(lint_deprecated_lint_name)]
1044#[help]
1045pub(crate) struct DeprecatedLintNameFromCommandLine<'a> {
1046    pub name: String,
1047    pub replace: &'a str,
1048    #[subdiagnostic]
1049    pub requested_level: RequestedLevel<'a>,
1050}
1051
1052#[derive(LintDiagnostic)]
1053#[diag(lint_renamed_lint)]
1054pub(crate) struct RenamedLint<'a> {
1055    pub name: &'a str,
1056    pub replace: &'a str,
1057    #[subdiagnostic]
1058    pub suggestion: RenamedLintSuggestion<'a>,
1059}
1060
1061#[derive(Subdiagnostic)]
1062pub(crate) enum RenamedLintSuggestion<'a> {
1063    #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
1064    WithSpan {
1065        #[primary_span]
1066        suggestion: Span,
1067        replace: &'a str,
1068    },
1069    #[help(lint_help)]
1070    WithoutSpan { replace: &'a str },
1071}
1072
1073#[derive(LintDiagnostic)]
1074#[diag(lint_renamed_lint)]
1075pub(crate) struct RenamedLintFromCommandLine<'a> {
1076    pub name: &'a str,
1077    pub replace: &'a str,
1078    #[subdiagnostic]
1079    pub suggestion: RenamedLintSuggestion<'a>,
1080    #[subdiagnostic]
1081    pub requested_level: RequestedLevel<'a>,
1082}
1083
1084#[derive(LintDiagnostic)]
1085#[diag(lint_removed_lint)]
1086pub(crate) struct RemovedLint<'a> {
1087    pub name: &'a str,
1088    pub reason: &'a str,
1089}
1090
1091#[derive(LintDiagnostic)]
1092#[diag(lint_removed_lint)]
1093pub(crate) struct RemovedLintFromCommandLine<'a> {
1094    pub name: &'a str,
1095    pub reason: &'a str,
1096    #[subdiagnostic]
1097    pub requested_level: RequestedLevel<'a>,
1098}
1099
1100#[derive(LintDiagnostic)]
1101#[diag(lint_unknown_lint)]
1102pub(crate) struct UnknownLint {
1103    pub name: String,
1104    #[subdiagnostic]
1105    pub suggestion: Option<UnknownLintSuggestion>,
1106}
1107
1108#[derive(Subdiagnostic)]
1109pub(crate) enum UnknownLintSuggestion {
1110    #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1111    WithSpan {
1112        #[primary_span]
1113        suggestion: Span,
1114        replace: Symbol,
1115        from_rustc: bool,
1116    },
1117    #[help(lint_help)]
1118    WithoutSpan { replace: Symbol, from_rustc: bool },
1119}
1120
1121#[derive(LintDiagnostic)]
1122#[diag(lint_unknown_lint, code = E0602)]
1123pub(crate) struct UnknownLintFromCommandLine<'a> {
1124    pub name: String,
1125    #[subdiagnostic]
1126    pub suggestion: Option<UnknownLintSuggestion>,
1127    #[subdiagnostic]
1128    pub requested_level: RequestedLevel<'a>,
1129}
1130
1131#[derive(LintDiagnostic)]
1132#[diag(lint_ignored_unless_crate_specified)]
1133pub(crate) struct IgnoredUnlessCrateSpecified<'a> {
1134    pub level: &'a str,
1135    pub name: Symbol,
1136}
1137
1138// dangling.rs
1139#[derive(LintDiagnostic)]
1140#[diag(lint_dangling_pointers_from_temporaries)]
1141#[note]
1142#[help(lint_help_bind)]
1143#[help(lint_help_returned)]
1144#[help(lint_help_visit)]
1145// FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts
1146pub(crate) struct DanglingPointersFromTemporaries<'tcx> {
1147    pub callee: Ident,
1148    pub ty: Ty<'tcx>,
1149    #[label(lint_label_ptr)]
1150    pub ptr_span: Span,
1151    #[label(lint_label_temporary)]
1152    pub temporary_span: Span,
1153}
1154
1155#[derive(LintDiagnostic)]
1156#[diag(lint_dangling_pointers_from_locals)]
1157#[note]
1158pub(crate) struct DanglingPointersFromLocals<'tcx> {
1159    pub ret_ty: Ty<'tcx>,
1160    #[label(lint_ret_ty)]
1161    pub ret_ty_span: Span,
1162    pub fn_kind: &'static str,
1163    #[label(lint_local_var)]
1164    pub local_var: Span,
1165    pub local_var_name: Ident,
1166    pub local_var_ty: Ty<'tcx>,
1167    #[label(lint_created_at)]
1168    pub created_at: Option<Span>,
1169}
1170
1171// multiple_supertrait_upcastable.rs
1172#[derive(LintDiagnostic)]
1173#[diag(lint_multiple_supertrait_upcastable)]
1174pub(crate) struct MultipleSupertraitUpcastable {
1175    pub ident: Ident,
1176}
1177
1178// non_ascii_idents.rs
1179#[derive(LintDiagnostic)]
1180#[diag(lint_identifier_non_ascii_char)]
1181pub(crate) struct IdentifierNonAsciiChar;
1182
1183#[derive(LintDiagnostic)]
1184#[diag(lint_identifier_uncommon_codepoints)]
1185#[note]
1186pub(crate) struct IdentifierUncommonCodepoints {
1187    pub codepoints: Vec<char>,
1188    pub codepoints_len: usize,
1189    pub identifier_type: &'static str,
1190}
1191
1192#[derive(LintDiagnostic)]
1193#[diag(lint_confusable_identifier_pair)]
1194pub(crate) struct ConfusableIdentifierPair {
1195    pub existing_sym: Symbol,
1196    pub sym: Symbol,
1197    #[label(lint_other_use)]
1198    pub label: Span,
1199    #[label(lint_current_use)]
1200    pub main_label: Span,
1201}
1202
1203#[derive(LintDiagnostic)]
1204#[diag(lint_mixed_script_confusables)]
1205#[note(lint_includes_note)]
1206#[note]
1207pub(crate) struct MixedScriptConfusables {
1208    pub set: String,
1209    pub includes: String,
1210}
1211
1212// non_fmt_panic.rs
1213pub(crate) struct NonFmtPanicUnused {
1214    pub count: usize,
1215    pub suggestion: Option<Span>,
1216}
1217
1218// Used because of two suggestions based on one Option<Span>
1219impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused {
1220    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1221        diag.primary_message(fluent::lint_non_fmt_panic_unused);
1222        diag.arg("count", self.count);
1223        diag.note(fluent::lint_note);
1224        if let Some(span) = self.suggestion {
1225            diag.span_suggestion(
1226                span.shrink_to_hi(),
1227                fluent::lint_add_args_suggestion,
1228                ", ...",
1229                Applicability::HasPlaceholders,
1230            );
1231            diag.span_suggestion(
1232                span.shrink_to_lo(),
1233                fluent::lint_add_fmt_suggestion,
1234                "\"{}\", ",
1235                Applicability::MachineApplicable,
1236            );
1237        }
1238    }
1239}
1240
1241#[derive(LintDiagnostic)]
1242#[diag(lint_non_fmt_panic_braces)]
1243#[note]
1244pub(crate) struct NonFmtPanicBraces {
1245    pub count: usize,
1246    #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
1247    pub suggestion: Option<Span>,
1248}
1249
1250// nonstandard_style.rs
1251#[derive(LintDiagnostic)]
1252#[diag(lint_non_camel_case_type)]
1253pub(crate) struct NonCamelCaseType<'a> {
1254    pub sort: &'a str,
1255    pub name: &'a str,
1256    #[subdiagnostic]
1257    pub sub: NonCamelCaseTypeSub,
1258}
1259
1260#[derive(Subdiagnostic)]
1261pub(crate) enum NonCamelCaseTypeSub {
1262    #[label(lint_label)]
1263    Label {
1264        #[primary_span]
1265        span: Span,
1266    },
1267    #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1268    Suggestion {
1269        #[primary_span]
1270        span: Span,
1271        replace: String,
1272    },
1273}
1274
1275#[derive(LintDiagnostic)]
1276#[diag(lint_non_snake_case)]
1277pub(crate) struct NonSnakeCaseDiag<'a> {
1278    pub sort: &'a str,
1279    pub name: &'a str,
1280    pub sc: String,
1281    #[subdiagnostic]
1282    pub sub: NonSnakeCaseDiagSub,
1283}
1284
1285pub(crate) enum NonSnakeCaseDiagSub {
1286    Label { span: Span },
1287    Help,
1288    RenameOrConvertSuggestion { span: Span, suggestion: Ident },
1289    ConvertSuggestion { span: Span, suggestion: String },
1290    SuggestionAndNote { span: Span },
1291}
1292
1293impl Subdiagnostic for NonSnakeCaseDiagSub {
1294    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1295        match self {
1296            NonSnakeCaseDiagSub::Label { span } => {
1297                diag.span_label(span, fluent::lint_label);
1298            }
1299            NonSnakeCaseDiagSub::Help => {
1300                diag.help(fluent::lint_help);
1301            }
1302            NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
1303                diag.span_suggestion(
1304                    span,
1305                    fluent::lint_convert_suggestion,
1306                    suggestion,
1307                    Applicability::MaybeIncorrect,
1308                );
1309            }
1310            NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
1311                diag.span_suggestion(
1312                    span,
1313                    fluent::lint_rename_or_convert_suggestion,
1314                    suggestion,
1315                    Applicability::MaybeIncorrect,
1316                );
1317            }
1318            NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
1319                diag.note(fluent::lint_cannot_convert_note);
1320                diag.span_suggestion(
1321                    span,
1322                    fluent::lint_rename_suggestion,
1323                    "",
1324                    Applicability::MaybeIncorrect,
1325                );
1326            }
1327        }
1328    }
1329}
1330
1331#[derive(LintDiagnostic)]
1332#[diag(lint_non_upper_case_global)]
1333pub(crate) struct NonUpperCaseGlobal<'a> {
1334    pub sort: &'a str,
1335    pub name: &'a str,
1336    #[subdiagnostic]
1337    pub sub: NonUpperCaseGlobalSub,
1338    #[subdiagnostic]
1339    pub usages: Vec<NonUpperCaseGlobalSubTool>,
1340}
1341
1342#[derive(Subdiagnostic)]
1343pub(crate) enum NonUpperCaseGlobalSub {
1344    #[label(lint_label)]
1345    Label {
1346        #[primary_span]
1347        span: Span,
1348    },
1349    #[suggestion(lint_suggestion, code = "{replace}")]
1350    Suggestion {
1351        #[primary_span]
1352        span: Span,
1353        #[applicability]
1354        applicability: Applicability,
1355        replace: String,
1356    },
1357}
1358
1359#[derive(Subdiagnostic)]
1360#[suggestion(
1361    lint_suggestion,
1362    code = "{replace}",
1363    applicability = "machine-applicable",
1364    style = "tool-only"
1365)]
1366pub(crate) struct NonUpperCaseGlobalSubTool {
1367    #[primary_span]
1368    pub(crate) span: Span,
1369    pub(crate) replace: String,
1370}
1371
1372// noop_method_call.rs
1373#[derive(LintDiagnostic)]
1374#[diag(lint_noop_method_call)]
1375#[note]
1376pub(crate) struct NoopMethodCallDiag<'a> {
1377    pub method: Ident,
1378    pub orig_ty: Ty<'a>,
1379    pub trait_: Symbol,
1380    #[suggestion(code = "", applicability = "machine-applicable")]
1381    pub label: Span,
1382    #[suggestion(
1383        lint_derive_suggestion,
1384        code = "#[derive(Clone)]\n",
1385        applicability = "maybe-incorrect"
1386    )]
1387    pub suggest_derive: Option<Span>,
1388}
1389
1390#[derive(LintDiagnostic)]
1391#[diag(lint_suspicious_double_ref_deref)]
1392pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> {
1393    pub ty: Ty<'a>,
1394}
1395
1396#[derive(LintDiagnostic)]
1397#[diag(lint_suspicious_double_ref_clone)]
1398pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> {
1399    pub ty: Ty<'a>,
1400}
1401
1402// non_local_defs.rs
1403pub(crate) enum NonLocalDefinitionsDiag {
1404    Impl {
1405        depth: u32,
1406        body_kind_descr: &'static str,
1407        body_name: String,
1408        cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
1409        const_anon: Option<Option<Span>>,
1410        doctest: bool,
1411        macro_to_change: Option<(String, &'static str)>,
1412    },
1413    MacroRules {
1414        depth: u32,
1415        body_kind_descr: &'static str,
1416        body_name: String,
1417        doctest: bool,
1418        cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
1419    },
1420}
1421
1422impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
1423    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1424        match self {
1425            NonLocalDefinitionsDiag::Impl {
1426                depth,
1427                body_kind_descr,
1428                body_name,
1429                cargo_update,
1430                const_anon,
1431                doctest,
1432                macro_to_change,
1433            } => {
1434                diag.primary_message(fluent::lint_non_local_definitions_impl);
1435                diag.arg("depth", depth);
1436                diag.arg("body_kind_descr", body_kind_descr);
1437                diag.arg("body_name", body_name);
1438
1439                if let Some((macro_to_change, macro_kind)) = macro_to_change {
1440                    diag.arg("macro_to_change", macro_to_change);
1441                    diag.arg("macro_kind", macro_kind);
1442                    diag.note(fluent::lint_macro_to_change);
1443                }
1444                if let Some(cargo_update) = cargo_update {
1445                    diag.subdiagnostic(cargo_update);
1446                }
1447
1448                diag.note(fluent::lint_non_local);
1449
1450                if doctest {
1451                    diag.help(fluent::lint_doctest);
1452                }
1453
1454                if let Some(const_anon) = const_anon {
1455                    diag.note(fluent::lint_exception);
1456                    if let Some(const_anon) = const_anon {
1457                        diag.span_suggestion(
1458                            const_anon,
1459                            fluent::lint_const_anon,
1460                            "_",
1461                            Applicability::MachineApplicable,
1462                        );
1463                    }
1464                }
1465            }
1466            NonLocalDefinitionsDiag::MacroRules {
1467                depth,
1468                body_kind_descr,
1469                body_name,
1470                doctest,
1471                cargo_update,
1472            } => {
1473                diag.primary_message(fluent::lint_non_local_definitions_macro_rules);
1474                diag.arg("depth", depth);
1475                diag.arg("body_kind_descr", body_kind_descr);
1476                diag.arg("body_name", body_name);
1477
1478                if doctest {
1479                    diag.help(fluent::lint_help_doctest);
1480                } else {
1481                    diag.help(fluent::lint_help);
1482                }
1483
1484                diag.note(fluent::lint_non_local);
1485
1486                if let Some(cargo_update) = cargo_update {
1487                    diag.subdiagnostic(cargo_update);
1488                }
1489            }
1490        }
1491    }
1492}
1493
1494#[derive(Subdiagnostic)]
1495#[note(lint_non_local_definitions_cargo_update)]
1496pub(crate) struct NonLocalDefinitionsCargoUpdateNote {
1497    pub macro_kind: &'static str,
1498    pub macro_name: Symbol,
1499    pub crate_name: Symbol,
1500}
1501
1502// precedence.rs
1503#[derive(LintDiagnostic)]
1504#[diag(lint_ambiguous_negative_literals)]
1505#[note(lint_example)]
1506pub(crate) struct AmbiguousNegativeLiteralsDiag {
1507    #[subdiagnostic]
1508    pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
1509    #[subdiagnostic]
1510    pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion,
1511}
1512
1513#[derive(Subdiagnostic)]
1514#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")]
1515pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
1516    #[suggestion_part(code = "(")]
1517    pub start_span: Span,
1518    #[suggestion_part(code = ")")]
1519    pub end_span: Span,
1520}
1521
1522#[derive(Subdiagnostic)]
1523#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")]
1524pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
1525    #[suggestion_part(code = "(")]
1526    pub start_span: Span,
1527    #[suggestion_part(code = ")")]
1528    pub end_span: Span,
1529}
1530
1531// pass_by_value.rs
1532#[derive(LintDiagnostic)]
1533#[diag(lint_pass_by_value)]
1534pub(crate) struct PassByValueDiag {
1535    pub ty: String,
1536    #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
1537    pub suggestion: Span,
1538}
1539
1540// redundant_semicolon.rs
1541#[derive(LintDiagnostic)]
1542#[diag(lint_redundant_semicolons)]
1543pub(crate) struct RedundantSemicolonsDiag {
1544    pub multiple: bool,
1545    #[subdiagnostic]
1546    pub suggestion: Option<RedundantSemicolonsSuggestion>,
1547}
1548
1549#[derive(Subdiagnostic)]
1550#[suggestion(lint_redundant_semicolons_suggestion, code = "", applicability = "maybe-incorrect")]
1551pub(crate) struct RedundantSemicolonsSuggestion {
1552    pub multiple_semicolons: bool,
1553    #[primary_span]
1554    pub span: Span,
1555}
1556
1557// traits.rs
1558pub(crate) struct DropTraitConstraintsDiag<'a> {
1559    pub predicate: Clause<'a>,
1560    pub tcx: TyCtxt<'a>,
1561    pub def_id: DefId,
1562}
1563
1564// Needed for def_path_str
1565impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> {
1566    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1567        diag.primary_message(fluent::lint_drop_trait_constraints);
1568        diag.arg("predicate", self.predicate);
1569        diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
1570    }
1571}
1572
1573pub(crate) struct DropGlue<'a> {
1574    pub tcx: TyCtxt<'a>,
1575    pub def_id: DefId,
1576}
1577
1578// Needed for def_path_str
1579impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> {
1580    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1581        diag.primary_message(fluent::lint_drop_glue);
1582        diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
1583    }
1584}
1585
1586// transmute.rs
1587#[derive(LintDiagnostic)]
1588#[diag(lint_int_to_ptr_transmutes)]
1589#[note]
1590#[note(lint_note_exposed_provenance)]
1591#[help(lint_suggestion_without_provenance_mut)]
1592#[help(lint_help_transmute)]
1593#[help(lint_help_exposed_provenance)]
1594pub(crate) struct IntegerToPtrTransmutes<'tcx> {
1595    #[subdiagnostic]
1596    pub suggestion: Option<IntegerToPtrTransmutesSuggestion<'tcx>>,
1597}
1598
1599#[derive(Subdiagnostic)]
1600pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> {
1601    #[multipart_suggestion(
1602        lint_suggestion_with_exposed_provenance,
1603        applicability = "machine-applicable",
1604        style = "verbose"
1605    )]
1606    ToPtr {
1607        dst: Ty<'tcx>,
1608        suffix: &'static str,
1609        #[suggestion_part(code = "std::ptr::with_exposed_provenance{suffix}::<{dst}>(")]
1610        start_call: Span,
1611    },
1612    #[multipart_suggestion(
1613        lint_suggestion_with_exposed_provenance,
1614        applicability = "machine-applicable",
1615        style = "verbose"
1616    )]
1617    ToRef {
1618        dst: Ty<'tcx>,
1619        suffix: &'static str,
1620        ref_mutbl: &'static str,
1621        #[suggestion_part(
1622            code = "&{ref_mutbl}*std::ptr::with_exposed_provenance{suffix}::<{dst}>("
1623        )]
1624        start_call: Span,
1625    },
1626}
1627
1628// types.rs
1629#[derive(LintDiagnostic)]
1630#[diag(lint_range_endpoint_out_of_range)]
1631pub(crate) struct RangeEndpointOutOfRange<'a> {
1632    pub ty: &'a str,
1633    #[subdiagnostic]
1634    pub sub: UseInclusiveRange<'a>,
1635}
1636
1637#[derive(Subdiagnostic)]
1638pub(crate) enum UseInclusiveRange<'a> {
1639    #[suggestion(
1640        lint_range_use_inclusive_range,
1641        code = "{start}..={literal}{suffix}",
1642        applicability = "machine-applicable"
1643    )]
1644    WithoutParen {
1645        #[primary_span]
1646        sugg: Span,
1647        start: String,
1648        literal: u128,
1649        suffix: &'a str,
1650    },
1651    #[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")]
1652    WithParen {
1653        #[suggestion_part(code = "=")]
1654        eq_sugg: Span,
1655        #[suggestion_part(code = "{literal}{suffix}")]
1656        lit_sugg: Span,
1657        literal: u128,
1658        suffix: &'a str,
1659    },
1660}
1661
1662#[derive(LintDiagnostic)]
1663#[diag(lint_overflowing_bin_hex)]
1664pub(crate) struct OverflowingBinHex<'a> {
1665    pub ty: &'a str,
1666    pub lit: String,
1667    pub dec: u128,
1668    pub actually: String,
1669    #[subdiagnostic]
1670    pub sign: OverflowingBinHexSign,
1671    #[subdiagnostic]
1672    pub sub: Option<OverflowingBinHexSub<'a>>,
1673    #[subdiagnostic]
1674    pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>,
1675}
1676
1677pub(crate) enum OverflowingBinHexSign {
1678    Positive,
1679    Negative,
1680}
1681
1682impl Subdiagnostic for OverflowingBinHexSign {
1683    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1684        match self {
1685            OverflowingBinHexSign::Positive => {
1686                diag.note(fluent::lint_positive_note);
1687            }
1688            OverflowingBinHexSign::Negative => {
1689                diag.note(fluent::lint_negative_note);
1690                diag.note(fluent::lint_negative_becomes_note);
1691            }
1692        }
1693    }
1694}
1695
1696#[derive(Subdiagnostic)]
1697pub(crate) enum OverflowingBinHexSub<'a> {
1698    #[suggestion(
1699        lint_suggestion,
1700        code = "{sans_suffix}{suggestion_ty}",
1701        applicability = "machine-applicable"
1702    )]
1703    Suggestion {
1704        #[primary_span]
1705        span: Span,
1706        suggestion_ty: &'a str,
1707        sans_suffix: &'a str,
1708    },
1709    #[help(lint_help)]
1710    Help { suggestion_ty: &'a str },
1711}
1712
1713#[derive(Subdiagnostic)]
1714#[suggestion(
1715    lint_sign_bit_suggestion,
1716    code = "{lit_no_suffix}{uint_ty} as {int_ty}",
1717    applicability = "maybe-incorrect"
1718)]
1719pub(crate) struct OverflowingBinHexSignBitSub<'a> {
1720    #[primary_span]
1721    pub span: Span,
1722    pub lit_no_suffix: &'a str,
1723    pub negative_val: String,
1724    pub uint_ty: &'a str,
1725    pub int_ty: &'a str,
1726}
1727
1728#[derive(LintDiagnostic)]
1729#[diag(lint_overflowing_int)]
1730#[note]
1731pub(crate) struct OverflowingInt<'a> {
1732    pub ty: &'a str,
1733    pub lit: String,
1734    pub min: i128,
1735    pub max: u128,
1736    #[subdiagnostic]
1737    pub help: Option<OverflowingIntHelp<'a>>,
1738}
1739
1740#[derive(Subdiagnostic)]
1741#[help(lint_help)]
1742pub(crate) struct OverflowingIntHelp<'a> {
1743    pub suggestion_ty: &'a str,
1744}
1745
1746#[derive(LintDiagnostic)]
1747#[diag(lint_only_cast_u8_to_char)]
1748pub(crate) struct OnlyCastu8ToChar {
1749    #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
1750    pub span: Span,
1751    pub literal: u128,
1752}
1753
1754#[derive(LintDiagnostic)]
1755#[diag(lint_overflowing_uint)]
1756#[note]
1757pub(crate) struct OverflowingUInt<'a> {
1758    pub ty: &'a str,
1759    pub lit: String,
1760    pub min: u128,
1761    pub max: u128,
1762}
1763
1764#[derive(LintDiagnostic)]
1765#[diag(lint_overflowing_literal)]
1766#[note]
1767pub(crate) struct OverflowingLiteral<'a> {
1768    pub ty: &'a str,
1769    pub lit: String,
1770}
1771
1772#[derive(LintDiagnostic)]
1773#[diag(lint_surrogate_char_cast)]
1774#[note]
1775pub(crate) struct SurrogateCharCast {
1776    pub literal: u128,
1777}
1778
1779#[derive(LintDiagnostic)]
1780#[diag(lint_too_large_char_cast)]
1781#[note]
1782pub(crate) struct TooLargeCharCast {
1783    pub literal: u128,
1784}
1785
1786#[derive(LintDiagnostic)]
1787#[diag(lint_uses_power_alignment)]
1788pub(crate) struct UsesPowerAlignment;
1789
1790#[derive(LintDiagnostic)]
1791#[diag(lint_unused_comparisons)]
1792pub(crate) struct UnusedComparisons;
1793
1794#[derive(LintDiagnostic)]
1795pub(crate) enum InvalidNanComparisons {
1796    #[diag(lint_invalid_nan_comparisons_eq_ne)]
1797    EqNe {
1798        #[subdiagnostic]
1799        suggestion: InvalidNanComparisonsSuggestion,
1800    },
1801    #[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)]
1802    LtLeGtGe,
1803}
1804
1805#[derive(Subdiagnostic)]
1806pub(crate) enum InvalidNanComparisonsSuggestion {
1807    #[multipart_suggestion(
1808        lint_suggestion,
1809        style = "verbose",
1810        applicability = "machine-applicable"
1811    )]
1812    Spanful {
1813        #[suggestion_part(code = "!")]
1814        neg: Option<Span>,
1815        #[suggestion_part(code = ".is_nan()")]
1816        float: Span,
1817        #[suggestion_part(code = "")]
1818        nan_plus_binop: Span,
1819    },
1820    #[help(lint_suggestion)]
1821    Spanless,
1822}
1823
1824#[derive(LintDiagnostic)]
1825pub(crate) enum AmbiguousWidePointerComparisons<'a> {
1826    #[diag(lint_ambiguous_wide_pointer_comparisons)]
1827    SpanfulEq {
1828        #[subdiagnostic]
1829        addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>,
1830        #[subdiagnostic]
1831        addr_metadata_suggestion: Option<AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a>>,
1832    },
1833    #[diag(lint_ambiguous_wide_pointer_comparisons)]
1834    SpanfulCmp {
1835        #[subdiagnostic]
1836        cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion<'a>,
1837        #[subdiagnostic]
1838        expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion<'a>,
1839    },
1840    #[diag(lint_ambiguous_wide_pointer_comparisons)]
1841    #[help(lint_addr_metadata_suggestion)]
1842    #[help(lint_addr_suggestion)]
1843    Spanless,
1844}
1845
1846#[derive(Subdiagnostic)]
1847#[multipart_suggestion(
1848    lint_addr_metadata_suggestion,
1849    style = "verbose",
1850    // FIXME(#53934): make machine-applicable again
1851    applicability = "maybe-incorrect"
1852)]
1853pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> {
1854    pub ne: &'a str,
1855    pub deref_left: &'a str,
1856    pub deref_right: &'a str,
1857    pub l_modifiers: &'a str,
1858    pub r_modifiers: &'a str,
1859    #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")]
1860    pub left: Span,
1861    #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
1862    pub middle: Span,
1863    #[suggestion_part(code = "{r_modifiers})")]
1864    pub right: Span,
1865}
1866
1867#[derive(Subdiagnostic)]
1868#[multipart_suggestion(
1869    lint_addr_suggestion,
1870    style = "verbose",
1871    // FIXME(#53934): make machine-applicable again
1872    applicability = "maybe-incorrect"
1873)]
1874pub(crate) struct AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
1875    pub(crate) ne: &'a str,
1876    pub(crate) deref_left: &'a str,
1877    pub(crate) deref_right: &'a str,
1878    pub(crate) l_modifiers: &'a str,
1879    pub(crate) r_modifiers: &'a str,
1880    #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
1881    pub(crate) left: Span,
1882    #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
1883    pub(crate) middle: Span,
1884    #[suggestion_part(code = "{r_modifiers})")]
1885    pub(crate) right: Span,
1886}
1887
1888#[derive(Subdiagnostic)]
1889#[multipart_suggestion(
1890    lint_cast_suggestion,
1891    style = "verbose",
1892    // FIXME(#53934): make machine-applicable again
1893    applicability = "maybe-incorrect"
1894)]
1895pub(crate) struct AmbiguousWidePointerComparisonsCastSuggestion<'a> {
1896    pub(crate) deref_left: &'a str,
1897    pub(crate) deref_right: &'a str,
1898    pub(crate) paren_left: &'a str,
1899    pub(crate) paren_right: &'a str,
1900    pub(crate) l_modifiers: &'a str,
1901    pub(crate) r_modifiers: &'a str,
1902    #[suggestion_part(code = "({deref_left}")]
1903    pub(crate) left_before: Option<Span>,
1904    #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")]
1905    pub(crate) left_after: Span,
1906    #[suggestion_part(code = "({deref_right}")]
1907    pub(crate) right_before: Option<Span>,
1908    #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")]
1909    pub(crate) right_after: Span,
1910}
1911
1912#[derive(Subdiagnostic)]
1913#[multipart_suggestion(
1914    lint_expect_suggestion,
1915    style = "verbose",
1916    // FIXME(#53934): make machine-applicable again
1917    applicability = "maybe-incorrect"
1918)]
1919pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> {
1920    pub(crate) paren_left: &'a str,
1921    pub(crate) paren_right: &'a str,
1922    // FIXME(#127436): Adjust once resolved
1923    #[suggestion_part(
1924        code = r#"{{ #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] {paren_left}"#
1925    )]
1926    pub(crate) before: Span,
1927    #[suggestion_part(code = "{paren_right} }}")]
1928    pub(crate) after: Span,
1929}
1930
1931#[derive(LintDiagnostic)]
1932pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> {
1933    #[diag(lint_unpredictable_fn_pointer_comparisons)]
1934    #[note(lint_note_duplicated_fn)]
1935    #[note(lint_note_deduplicated_fn)]
1936    #[note(lint_note_visit_fn_addr_eq)]
1937    Suggestion {
1938        #[subdiagnostic]
1939        sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>,
1940    },
1941    #[diag(lint_unpredictable_fn_pointer_comparisons)]
1942    #[note(lint_note_duplicated_fn)]
1943    #[note(lint_note_deduplicated_fn)]
1944    #[note(lint_note_visit_fn_addr_eq)]
1945    Warn,
1946}
1947
1948#[derive(Subdiagnostic)]
1949pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> {
1950    #[multipart_suggestion(
1951        lint_fn_addr_eq_suggestion,
1952        style = "verbose",
1953        applicability = "maybe-incorrect"
1954    )]
1955    FnAddrEq {
1956        ne: &'a str,
1957        deref_left: &'a str,
1958        deref_right: &'a str,
1959        #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
1960        left: Span,
1961        #[suggestion_part(code = ", {deref_right}")]
1962        middle: Span,
1963        #[suggestion_part(code = ")")]
1964        right: Span,
1965    },
1966    #[multipart_suggestion(
1967        lint_fn_addr_eq_suggestion,
1968        style = "verbose",
1969        applicability = "maybe-incorrect"
1970    )]
1971    FnAddrEqWithCast {
1972        ne: &'a str,
1973        deref_left: &'a str,
1974        deref_right: &'a str,
1975        fn_sig: rustc_middle::ty::PolyFnSig<'tcx>,
1976        #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
1977        left: Span,
1978        #[suggestion_part(code = ", {deref_right}")]
1979        middle: Span,
1980        #[suggestion_part(code = " as {fn_sig})")]
1981        right: Span,
1982    },
1983}
1984
1985pub(crate) struct ImproperCTypes<'a> {
1986    pub ty: Ty<'a>,
1987    pub desc: &'a str,
1988    pub label: Span,
1989    pub help: Option<DiagMessage>,
1990    pub note: DiagMessage,
1991    pub span_note: Option<Span>,
1992}
1993
1994// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
1995impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
1996    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1997        diag.primary_message(fluent::lint_improper_ctypes);
1998        diag.arg("ty", self.ty);
1999        diag.arg("desc", self.desc);
2000        diag.span_label(self.label, fluent::lint_label);
2001        if let Some(help) = self.help {
2002            diag.help(help);
2003        }
2004        diag.note(self.note);
2005        if let Some(note) = self.span_note {
2006            diag.span_note(note, fluent::lint_note);
2007        }
2008    }
2009}
2010
2011#[derive(LintDiagnostic)]
2012#[diag(lint_variant_size_differences)]
2013pub(crate) struct VariantSizeDifferencesDiag {
2014    pub largest: u64,
2015}
2016
2017#[derive(LintDiagnostic)]
2018#[diag(lint_atomic_ordering_load)]
2019#[help]
2020pub(crate) struct AtomicOrderingLoad;
2021
2022#[derive(LintDiagnostic)]
2023#[diag(lint_atomic_ordering_store)]
2024#[help]
2025pub(crate) struct AtomicOrderingStore;
2026
2027#[derive(LintDiagnostic)]
2028#[diag(lint_atomic_ordering_fence)]
2029#[help]
2030pub(crate) struct AtomicOrderingFence;
2031
2032#[derive(LintDiagnostic)]
2033#[diag(lint_atomic_ordering_invalid)]
2034#[help]
2035pub(crate) struct InvalidAtomicOrderingDiag {
2036    pub method: Symbol,
2037    #[label]
2038    pub fail_order_arg_span: Span,
2039}
2040
2041// unused.rs
2042#[derive(LintDiagnostic)]
2043#[diag(lint_unused_op)]
2044pub(crate) struct UnusedOp<'a> {
2045    pub op: &'a str,
2046    #[label]
2047    pub label: Span,
2048    #[subdiagnostic]
2049    pub suggestion: UnusedOpSuggestion,
2050}
2051
2052#[derive(Subdiagnostic)]
2053pub(crate) enum UnusedOpSuggestion {
2054    #[suggestion(
2055        lint_suggestion,
2056        style = "verbose",
2057        code = "let _ = ",
2058        applicability = "maybe-incorrect"
2059    )]
2060    NormalExpr {
2061        #[primary_span]
2062        span: Span,
2063    },
2064    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
2065    BlockTailExpr {
2066        #[suggestion_part(code = "let _ = ")]
2067        before_span: Span,
2068        #[suggestion_part(code = ";")]
2069        after_span: Span,
2070    },
2071}
2072
2073#[derive(LintDiagnostic)]
2074#[diag(lint_unused_result)]
2075pub(crate) struct UnusedResult<'a> {
2076    pub ty: Ty<'a>,
2077}
2078
2079// FIXME(davidtwco): this isn't properly translatable because of the
2080// pre/post strings
2081#[derive(LintDiagnostic)]
2082#[diag(lint_unused_closure)]
2083#[note]
2084pub(crate) struct UnusedClosure<'a> {
2085    pub count: usize,
2086    pub pre: &'a str,
2087    pub post: &'a str,
2088}
2089
2090// FIXME(davidtwco): this isn't properly translatable because of the
2091// pre/post strings
2092#[derive(LintDiagnostic)]
2093#[diag(lint_unused_coroutine)]
2094#[note]
2095pub(crate) struct UnusedCoroutine<'a> {
2096    pub count: usize,
2097    pub pre: &'a str,
2098    pub post: &'a str,
2099}
2100
2101// FIXME(davidtwco): this isn't properly translatable because of the pre/post
2102// strings
2103pub(crate) struct UnusedDef<'a, 'b> {
2104    pub pre: &'a str,
2105    pub post: &'a str,
2106    pub cx: &'a LateContext<'b>,
2107    pub def_id: DefId,
2108    pub note: Option<Symbol>,
2109    pub suggestion: Option<UnusedDefSuggestion>,
2110}
2111
2112#[derive(Subdiagnostic)]
2113
2114pub(crate) enum UnusedDefSuggestion {
2115    #[suggestion(
2116        lint_suggestion,
2117        style = "verbose",
2118        code = "let _ = ",
2119        applicability = "maybe-incorrect"
2120    )]
2121    NormalExpr {
2122        #[primary_span]
2123        span: Span,
2124    },
2125    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
2126    BlockTailExpr {
2127        #[suggestion_part(code = "let _ = ")]
2128        before_span: Span,
2129        #[suggestion_part(code = ";")]
2130        after_span: Span,
2131    },
2132}
2133
2134// Needed because of def_path_str
2135impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> {
2136    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2137        diag.primary_message(fluent::lint_unused_def);
2138        diag.arg("pre", self.pre);
2139        diag.arg("post", self.post);
2140        diag.arg("def", self.cx.tcx.def_path_str(self.def_id));
2141        // check for #[must_use = "..."]
2142        if let Some(note) = self.note {
2143            diag.note(note.to_string());
2144        }
2145        if let Some(sugg) = self.suggestion {
2146            diag.subdiagnostic(sugg);
2147        }
2148    }
2149}
2150
2151#[derive(LintDiagnostic)]
2152#[diag(lint_path_statement_drop)]
2153pub(crate) struct PathStatementDrop {
2154    #[subdiagnostic]
2155    pub sub: PathStatementDropSub,
2156}
2157
2158#[derive(Subdiagnostic)]
2159pub(crate) enum PathStatementDropSub {
2160    #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
2161    Suggestion {
2162        #[primary_span]
2163        span: Span,
2164        snippet: String,
2165    },
2166    #[help(lint_help)]
2167    Help {
2168        #[primary_span]
2169        span: Span,
2170    },
2171}
2172
2173#[derive(LintDiagnostic)]
2174#[diag(lint_path_statement_no_effect)]
2175pub(crate) struct PathStatementNoEffect;
2176
2177#[derive(LintDiagnostic)]
2178#[diag(lint_unused_delim)]
2179pub(crate) struct UnusedDelim<'a> {
2180    pub delim: &'static str,
2181    pub item: &'a str,
2182    #[subdiagnostic]
2183    pub suggestion: Option<UnusedDelimSuggestion>,
2184}
2185
2186#[derive(Subdiagnostic)]
2187#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2188pub(crate) struct UnusedDelimSuggestion {
2189    #[suggestion_part(code = "{start_replace}")]
2190    pub start_span: Span,
2191    pub start_replace: &'static str,
2192    #[suggestion_part(code = "{end_replace}")]
2193    pub end_span: Span,
2194    pub end_replace: &'static str,
2195}
2196
2197#[derive(LintDiagnostic)]
2198#[diag(lint_unused_import_braces)]
2199pub(crate) struct UnusedImportBracesDiag {
2200    pub node: Symbol,
2201}
2202
2203#[derive(LintDiagnostic)]
2204#[diag(lint_unused_allocation)]
2205pub(crate) struct UnusedAllocationDiag;
2206
2207#[derive(LintDiagnostic)]
2208#[diag(lint_unused_allocation_mut)]
2209pub(crate) struct UnusedAllocationMutDiag;
2210
2211pub(crate) struct AsyncFnInTraitDiag {
2212    pub sugg: Option<Vec<(Span, String)>>,
2213}
2214
2215impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag {
2216    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2217        diag.primary_message(fluent::lint_async_fn_in_trait);
2218        diag.note(fluent::lint_note);
2219        if let Some(sugg) = self.sugg {
2220            diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect);
2221        }
2222    }
2223}
2224
2225#[derive(LintDiagnostic)]
2226#[diag(lint_unit_bindings)]
2227pub(crate) struct UnitBindingsDiag {
2228    #[label]
2229    pub label: Span,
2230}
2231
2232#[derive(LintDiagnostic)]
2233pub(crate) enum InvalidAsmLabel {
2234    #[diag(lint_invalid_asm_label_named)]
2235    #[help]
2236    #[note]
2237    Named {
2238        #[note(lint_invalid_asm_label_no_span)]
2239        missing_precise_span: bool,
2240    },
2241    #[diag(lint_invalid_asm_label_format_arg)]
2242    #[help]
2243    #[note(lint_note1)]
2244    #[note(lint_note2)]
2245    FormatArg {
2246        #[note(lint_invalid_asm_label_no_span)]
2247        missing_precise_span: bool,
2248    },
2249    #[diag(lint_invalid_asm_label_binary)]
2250    #[help]
2251    #[note(lint_note1)]
2252    #[note(lint_note2)]
2253    Binary {
2254        #[note(lint_invalid_asm_label_no_span)]
2255        missing_precise_span: bool,
2256        // hack to get a label on the whole span, must match the emitted span
2257        #[label]
2258        span: Span,
2259    },
2260}
2261
2262#[derive(Subdiagnostic)]
2263pub(crate) enum UnexpectedCfgCargoHelp {
2264    #[help(lint_unexpected_cfg_add_cargo_feature)]
2265    #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
2266    LintCfg { cargo_toml_lint_cfg: String },
2267    #[help(lint_unexpected_cfg_add_cargo_feature)]
2268    #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
2269    #[help(lint_unexpected_cfg_add_build_rs_println)]
2270    LintCfgAndBuildRs { cargo_toml_lint_cfg: String, build_rs_println: String },
2271}
2272
2273impl UnexpectedCfgCargoHelp {
2274    fn cargo_toml_lint_cfg(unescaped: &str) -> String {
2275        format!(
2276            "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}"
2277        )
2278    }
2279
2280    pub(crate) fn lint_cfg(unescaped: &str) -> Self {
2281        UnexpectedCfgCargoHelp::LintCfg {
2282            cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
2283        }
2284    }
2285
2286    pub(crate) fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self {
2287        UnexpectedCfgCargoHelp::LintCfgAndBuildRs {
2288            cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
2289            build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");"),
2290        }
2291    }
2292}
2293
2294#[derive(Subdiagnostic)]
2295#[help(lint_unexpected_cfg_add_cmdline_arg)]
2296pub(crate) struct UnexpectedCfgRustcHelp {
2297    pub cmdline_arg: String,
2298}
2299
2300impl UnexpectedCfgRustcHelp {
2301    pub(crate) fn new(unescaped: &str) -> Self {
2302        Self { cmdline_arg: format!("--check-cfg={unescaped}") }
2303    }
2304}
2305
2306#[derive(Subdiagnostic)]
2307#[note(lint_unexpected_cfg_from_external_macro_origin)]
2308#[help(lint_unexpected_cfg_from_external_macro_refer)]
2309pub(crate) struct UnexpectedCfgRustcMacroHelp {
2310    pub macro_kind: &'static str,
2311    pub macro_name: Symbol,
2312}
2313
2314#[derive(Subdiagnostic)]
2315#[note(lint_unexpected_cfg_from_external_macro_origin)]
2316#[help(lint_unexpected_cfg_from_external_macro_refer)]
2317#[help(lint_unexpected_cfg_cargo_update)]
2318pub(crate) struct UnexpectedCfgCargoMacroHelp {
2319    pub macro_kind: &'static str,
2320    pub macro_name: Symbol,
2321    pub crate_name: Symbol,
2322}
2323
2324#[derive(LintDiagnostic)]
2325#[diag(lint_unexpected_cfg_name)]
2326pub(crate) struct UnexpectedCfgName {
2327    #[subdiagnostic]
2328    pub code_sugg: unexpected_cfg_name::CodeSuggestion,
2329    #[subdiagnostic]
2330    pub invocation_help: unexpected_cfg_name::InvocationHelp,
2331
2332    pub name: Symbol,
2333}
2334
2335pub(crate) mod unexpected_cfg_name {
2336    use rustc_errors::DiagSymbolList;
2337    use rustc_macros::Subdiagnostic;
2338    use rustc_span::{Ident, Span, Symbol};
2339
2340    #[derive(Subdiagnostic)]
2341    pub(crate) enum CodeSuggestion {
2342        #[help(lint_unexpected_cfg_define_features)]
2343        DefineFeatures,
2344        #[multipart_suggestion(
2345            lint_unexpected_cfg_name_version_syntax,
2346            applicability = "machine-applicable"
2347        )]
2348        VersionSyntax {
2349            #[suggestion_part(code = "(")]
2350            between_name_and_value: Span,
2351            #[suggestion_part(code = ")")]
2352            after_value: Span,
2353        },
2354        #[suggestion(
2355            lint_unexpected_cfg_name_similar_name_value,
2356            applicability = "maybe-incorrect",
2357            code = "{code}"
2358        )]
2359        SimilarNameAndValue {
2360            #[primary_span]
2361            span: Span,
2362            code: String,
2363        },
2364        #[suggestion(
2365            lint_unexpected_cfg_name_similar_name_no_value,
2366            applicability = "maybe-incorrect",
2367            code = "{code}"
2368        )]
2369        SimilarNameNoValue {
2370            #[primary_span]
2371            span: Span,
2372            code: String,
2373        },
2374        #[suggestion(
2375            lint_unexpected_cfg_name_similar_name_different_values,
2376            applicability = "maybe-incorrect",
2377            code = "{code}"
2378        )]
2379        SimilarNameDifferentValues {
2380            #[primary_span]
2381            span: Span,
2382            code: String,
2383            #[subdiagnostic]
2384            expected: Option<ExpectedValues>,
2385        },
2386        #[suggestion(
2387            lint_unexpected_cfg_name_similar_name,
2388            applicability = "maybe-incorrect",
2389            code = "{code}"
2390        )]
2391        SimilarName {
2392            #[primary_span]
2393            span: Span,
2394            code: String,
2395            #[subdiagnostic]
2396            expected: Option<ExpectedValues>,
2397        },
2398        SimilarValues {
2399            #[subdiagnostic]
2400            with_similar_values: Vec<FoundWithSimilarValue>,
2401            #[subdiagnostic]
2402            expected_names: Option<ExpectedNames>,
2403        },
2404        #[suggestion(
2405            lint_unexpected_cfg_boolean,
2406            applicability = "machine-applicable",
2407            style = "verbose",
2408            code = "{literal}"
2409        )]
2410        BooleanLiteral {
2411            #[primary_span]
2412            span: Span,
2413            literal: bool,
2414        },
2415    }
2416
2417    #[derive(Subdiagnostic)]
2418    #[help(lint_unexpected_cfg_name_expected_values)]
2419    pub(crate) struct ExpectedValues {
2420        pub best_match: Symbol,
2421        pub possibilities: DiagSymbolList,
2422    }
2423
2424    #[derive(Subdiagnostic)]
2425    #[suggestion(
2426        lint_unexpected_cfg_name_with_similar_value,
2427        applicability = "maybe-incorrect",
2428        code = "{code}"
2429    )]
2430    pub(crate) struct FoundWithSimilarValue {
2431        #[primary_span]
2432        pub span: Span,
2433        pub code: String,
2434    }
2435
2436    #[derive(Subdiagnostic)]
2437    #[help_once(lint_unexpected_cfg_name_expected_names)]
2438    pub(crate) struct ExpectedNames {
2439        pub possibilities: DiagSymbolList<Ident>,
2440        pub and_more: usize,
2441    }
2442
2443    #[derive(Subdiagnostic)]
2444    pub(crate) enum InvocationHelp {
2445        #[note(lint_unexpected_cfg_doc_cargo)]
2446        Cargo {
2447            #[subdiagnostic]
2448            macro_help: Option<super::UnexpectedCfgCargoMacroHelp>,
2449            #[subdiagnostic]
2450            help: Option<super::UnexpectedCfgCargoHelp>,
2451        },
2452        #[note(lint_unexpected_cfg_doc_rustc)]
2453        Rustc {
2454            #[subdiagnostic]
2455            macro_help: Option<super::UnexpectedCfgRustcMacroHelp>,
2456            #[subdiagnostic]
2457            help: super::UnexpectedCfgRustcHelp,
2458        },
2459    }
2460}
2461
2462#[derive(LintDiagnostic)]
2463#[diag(lint_unexpected_cfg_value)]
2464pub(crate) struct UnexpectedCfgValue {
2465    #[subdiagnostic]
2466    pub code_sugg: unexpected_cfg_value::CodeSuggestion,
2467    #[subdiagnostic]
2468    pub invocation_help: unexpected_cfg_value::InvocationHelp,
2469
2470    pub has_value: bool,
2471    pub value: String,
2472}
2473
2474pub(crate) mod unexpected_cfg_value {
2475    use rustc_errors::DiagSymbolList;
2476    use rustc_macros::Subdiagnostic;
2477    use rustc_span::{Span, Symbol};
2478
2479    #[derive(Subdiagnostic)]
2480    pub(crate) enum CodeSuggestion {
2481        ChangeValue {
2482            #[subdiagnostic]
2483            expected_values: ExpectedValues,
2484            #[subdiagnostic]
2485            suggestion: Option<ChangeValueSuggestion>,
2486        },
2487        #[note(lint_unexpected_cfg_value_no_expected_value)]
2488        RemoveValue {
2489            #[subdiagnostic]
2490            suggestion: Option<RemoveValueSuggestion>,
2491
2492            name: Symbol,
2493        },
2494        #[note(lint_unexpected_cfg_value_no_expected_values)]
2495        RemoveCondition {
2496            #[subdiagnostic]
2497            suggestion: RemoveConditionSuggestion,
2498
2499            name: Symbol,
2500        },
2501    }
2502
2503    #[derive(Subdiagnostic)]
2504    pub(crate) enum ChangeValueSuggestion {
2505        #[suggestion(
2506            lint_unexpected_cfg_value_similar_name,
2507            code = r#""{best_match}""#,
2508            applicability = "maybe-incorrect"
2509        )]
2510        SimilarName {
2511            #[primary_span]
2512            span: Span,
2513            best_match: Symbol,
2514        },
2515        #[suggestion(
2516            lint_unexpected_cfg_value_specify_value,
2517            code = r#" = "{first_possibility}""#,
2518            applicability = "maybe-incorrect"
2519        )]
2520        SpecifyValue {
2521            #[primary_span]
2522            span: Span,
2523            first_possibility: Symbol,
2524        },
2525    }
2526
2527    #[derive(Subdiagnostic)]
2528    #[suggestion(
2529        lint_unexpected_cfg_value_remove_value,
2530        code = "",
2531        applicability = "maybe-incorrect"
2532    )]
2533    pub(crate) struct RemoveValueSuggestion {
2534        #[primary_span]
2535        pub span: Span,
2536    }
2537
2538    #[derive(Subdiagnostic)]
2539    #[suggestion(
2540        lint_unexpected_cfg_value_remove_condition,
2541        code = "",
2542        applicability = "maybe-incorrect"
2543    )]
2544    pub(crate) struct RemoveConditionSuggestion {
2545        #[primary_span]
2546        pub span: Span,
2547    }
2548
2549    #[derive(Subdiagnostic)]
2550    #[note(lint_unexpected_cfg_value_expected_values)]
2551    pub(crate) struct ExpectedValues {
2552        pub name: Symbol,
2553        pub have_none_possibility: bool,
2554        pub possibilities: DiagSymbolList,
2555        pub and_more: usize,
2556    }
2557
2558    #[derive(Subdiagnostic)]
2559    pub(crate) enum InvocationHelp {
2560        #[note(lint_unexpected_cfg_doc_cargo)]
2561        Cargo {
2562            #[subdiagnostic]
2563            help: Option<CargoHelp>,
2564            #[subdiagnostic]
2565            macro_help: Option<super::UnexpectedCfgCargoMacroHelp>,
2566        },
2567        #[note(lint_unexpected_cfg_doc_rustc)]
2568        Rustc {
2569            #[subdiagnostic]
2570            help: Option<super::UnexpectedCfgRustcHelp>,
2571            #[subdiagnostic]
2572            macro_help: Option<super::UnexpectedCfgRustcMacroHelp>,
2573        },
2574    }
2575
2576    #[derive(Subdiagnostic)]
2577    pub(crate) enum CargoHelp {
2578        #[help(lint_unexpected_cfg_value_add_feature)]
2579        AddFeature {
2580            value: Symbol,
2581        },
2582        #[help(lint_unexpected_cfg_define_features)]
2583        DefineFeatures,
2584        Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp),
2585    }
2586}
2587
2588#[derive(LintDiagnostic)]
2589#[diag(lint_unused_crate_dependency)]
2590#[help]
2591pub(crate) struct UnusedCrateDependency {
2592    pub extern_crate: Symbol,
2593    pub local_crate: Symbol,
2594}
2595
2596// FIXME(jdonszelmann): duplicated in rustc_attr_parsing, should be moved there completely.
2597#[derive(LintDiagnostic)]
2598#[diag(lint_ill_formed_attribute_input)]
2599pub(crate) struct IllFormedAttributeInput {
2600    pub num_suggestions: usize,
2601    pub suggestions: DiagArgValue,
2602    #[note]
2603    pub has_docs: bool,
2604    pub docs: &'static str,
2605}
2606
2607#[derive(LintDiagnostic)]
2608#[diag(lint_unicode_text_flow)]
2609#[note]
2610pub(crate) struct UnicodeTextFlow {
2611    #[label]
2612    pub comment_span: Span,
2613    #[subdiagnostic]
2614    pub characters: Vec<UnicodeCharNoteSub>,
2615    #[subdiagnostic]
2616    pub suggestions: Option<UnicodeTextFlowSuggestion>,
2617
2618    pub num_codepoints: usize,
2619}
2620
2621#[derive(Subdiagnostic)]
2622#[label(lint_label_comment_char)]
2623pub(crate) struct UnicodeCharNoteSub {
2624    #[primary_span]
2625    pub span: Span,
2626    pub c_debug: String,
2627}
2628
2629#[derive(Subdiagnostic)]
2630#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")]
2631pub(crate) struct UnicodeTextFlowSuggestion {
2632    #[suggestion_part(code = "")]
2633    pub spans: Vec<Span>,
2634}
2635
2636#[derive(LintDiagnostic)]
2637#[diag(lint_abs_path_with_module)]
2638pub(crate) struct AbsPathWithModule {
2639    #[subdiagnostic]
2640    pub sugg: AbsPathWithModuleSugg,
2641}
2642
2643#[derive(Subdiagnostic)]
2644#[suggestion(lint_suggestion, code = "{replacement}")]
2645pub(crate) struct AbsPathWithModuleSugg {
2646    #[primary_span]
2647    pub span: Span,
2648    #[applicability]
2649    pub applicability: Applicability,
2650    pub replacement: String,
2651}
2652
2653#[derive(LintDiagnostic)]
2654#[diag(lint_hidden_lifetime_parameters)]
2655pub(crate) struct ElidedLifetimesInPaths {
2656    #[subdiagnostic]
2657    pub subdiag: ElidedLifetimeInPathSubdiag,
2658}
2659
2660#[derive(LintDiagnostic)]
2661#[diag(lint_unused_imports)]
2662pub(crate) struct UnusedImports {
2663    #[subdiagnostic]
2664    pub sugg: UnusedImportsSugg,
2665    #[help]
2666    pub test_module_span: Option<Span>,
2667
2668    pub span_snippets: DiagArgValue,
2669    pub num_snippets: usize,
2670}
2671
2672#[derive(Subdiagnostic)]
2673pub(crate) enum UnusedImportsSugg {
2674    #[suggestion(
2675        lint_suggestion_remove_whole_use,
2676        applicability = "machine-applicable",
2677        code = "",
2678        style = "tool-only"
2679    )]
2680    RemoveWholeUse {
2681        #[primary_span]
2682        span: Span,
2683    },
2684    #[multipart_suggestion(
2685        lint_suggestion_remove_imports,
2686        applicability = "machine-applicable",
2687        style = "tool-only"
2688    )]
2689    RemoveImports {
2690        #[suggestion_part(code = "")]
2691        remove_spans: Vec<Span>,
2692        num_to_remove: usize,
2693    },
2694}
2695
2696#[derive(LintDiagnostic)]
2697#[diag(lint_redundant_import)]
2698pub(crate) struct RedundantImport {
2699    #[subdiagnostic]
2700    pub subs: Vec<RedundantImportSub>,
2701
2702    pub ident: Ident,
2703}
2704
2705#[derive(Subdiagnostic)]
2706pub(crate) enum RedundantImportSub {
2707    #[label(lint_label_imported_here)]
2708    ImportedHere(#[primary_span] Span),
2709    #[label(lint_label_defined_here)]
2710    DefinedHere(#[primary_span] Span),
2711    #[label(lint_label_imported_prelude)]
2712    ImportedPrelude(#[primary_span] Span),
2713    #[label(lint_label_defined_prelude)]
2714    DefinedPrelude(#[primary_span] Span),
2715}
2716
2717#[derive(LintDiagnostic)]
2718pub(crate) enum PatternsInFnsWithoutBody {
2719    #[diag(lint_pattern_in_foreign)]
2720    Foreign {
2721        #[subdiagnostic]
2722        sub: PatternsInFnsWithoutBodySub,
2723    },
2724    #[diag(lint_pattern_in_bodiless)]
2725    Bodiless {
2726        #[subdiagnostic]
2727        sub: PatternsInFnsWithoutBodySub,
2728    },
2729}
2730
2731#[derive(Subdiagnostic)]
2732#[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")]
2733pub(crate) struct PatternsInFnsWithoutBodySub {
2734    #[primary_span]
2735    pub span: Span,
2736
2737    pub ident: Ident,
2738}
2739
2740#[derive(LintDiagnostic)]
2741#[diag(lint_reserved_prefix)]
2742pub(crate) struct ReservedPrefix {
2743    #[label]
2744    pub label: Span,
2745    #[suggestion(code = " ", applicability = "machine-applicable")]
2746    pub suggestion: Span,
2747
2748    pub prefix: String,
2749}
2750
2751#[derive(LintDiagnostic)]
2752#[diag(lint_raw_prefix)]
2753pub(crate) struct RawPrefix {
2754    #[label]
2755    pub label: Span,
2756    #[suggestion(code = " ", applicability = "machine-applicable")]
2757    pub suggestion: Span,
2758}
2759
2760#[derive(LintDiagnostic)]
2761#[diag(lint_break_with_label_and_loop)]
2762pub(crate) struct BreakWithLabelAndLoop {
2763    #[subdiagnostic]
2764    pub sub: BreakWithLabelAndLoopSub,
2765}
2766
2767#[derive(Subdiagnostic)]
2768#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2769pub(crate) struct BreakWithLabelAndLoopSub {
2770    #[suggestion_part(code = "(")]
2771    pub left: Span,
2772    #[suggestion_part(code = ")")]
2773    pub right: Span,
2774}
2775
2776#[derive(LintDiagnostic)]
2777#[diag(lint_deprecated_where_clause_location)]
2778#[note]
2779pub(crate) struct DeprecatedWhereClauseLocation {
2780    #[subdiagnostic]
2781    pub suggestion: DeprecatedWhereClauseLocationSugg,
2782}
2783
2784#[derive(Subdiagnostic)]
2785pub(crate) enum DeprecatedWhereClauseLocationSugg {
2786    #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")]
2787    MoveToEnd {
2788        #[suggestion_part(code = "")]
2789        left: Span,
2790        #[suggestion_part(code = "{sugg}")]
2791        right: Span,
2792
2793        sugg: String,
2794    },
2795    #[suggestion(lint_suggestion_remove_where, code = "", applicability = "machine-applicable")]
2796    RemoveWhere {
2797        #[primary_span]
2798        span: Span,
2799    },
2800}
2801
2802#[derive(LintDiagnostic)]
2803#[diag(lint_single_use_lifetime)]
2804pub(crate) struct SingleUseLifetime {
2805    #[label(lint_label_param)]
2806    pub param_span: Span,
2807    #[label(lint_label_use)]
2808    pub use_span: Span,
2809    #[subdiagnostic]
2810    pub suggestion: Option<SingleUseLifetimeSugg>,
2811
2812    pub ident: Ident,
2813}
2814
2815#[derive(Subdiagnostic)]
2816#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2817pub(crate) struct SingleUseLifetimeSugg {
2818    #[suggestion_part(code = "")]
2819    pub deletion_span: Option<Span>,
2820    #[suggestion_part(code = "{replace_lt}")]
2821    pub use_span: Span,
2822
2823    pub replace_lt: String,
2824}
2825
2826#[derive(LintDiagnostic)]
2827#[diag(lint_unused_lifetime)]
2828pub(crate) struct UnusedLifetime {
2829    #[suggestion(code = "", applicability = "machine-applicable")]
2830    pub deletion_span: Option<Span>,
2831
2832    pub ident: Ident,
2833}
2834
2835#[derive(LintDiagnostic)]
2836#[diag(lint_named_argument_used_positionally)]
2837pub(crate) struct NamedArgumentUsedPositionally {
2838    #[label(lint_label_named_arg)]
2839    pub named_arg_sp: Span,
2840    #[label(lint_label_position_arg)]
2841    pub position_label_sp: Option<Span>,
2842    #[suggestion(style = "verbose", code = "{name}", applicability = "maybe-incorrect")]
2843    pub suggestion: Option<Span>,
2844
2845    pub name: String,
2846    pub named_arg_name: String,
2847}
2848
2849#[derive(LintDiagnostic)]
2850#[diag(lint_ambiguous_glob_reexport)]
2851pub(crate) struct AmbiguousGlobReexports {
2852    #[label(lint_label_first_reexport)]
2853    pub first_reexport: Span,
2854    #[label(lint_label_duplicate_reexport)]
2855    pub duplicate_reexport: Span,
2856
2857    pub name: String,
2858    // FIXME: make this translatable
2859    pub namespace: String,
2860}
2861
2862#[derive(LintDiagnostic)]
2863#[diag(lint_hidden_glob_reexport)]
2864pub(crate) struct HiddenGlobReexports {
2865    #[note(lint_note_glob_reexport)]
2866    pub glob_reexport: Span,
2867    #[note(lint_note_private_item)]
2868    pub private_item: Span,
2869
2870    pub name: String,
2871    // FIXME: make this translatable
2872    pub namespace: String,
2873}
2874
2875#[derive(LintDiagnostic)]
2876#[diag(lint_unnecessary_qualification)]
2877pub(crate) struct UnusedQualifications {
2878    #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
2879    pub removal_span: Span,
2880}
2881
2882#[derive(LintDiagnostic)]
2883#[diag(lint_associated_const_elided_lifetime)]
2884pub(crate) struct AssociatedConstElidedLifetime {
2885    #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")]
2886    pub span: Span,
2887
2888    pub code: &'static str,
2889    pub elided: bool,
2890    #[note]
2891    pub lifetimes_in_scope: MultiSpan,
2892}
2893
2894#[derive(LintDiagnostic)]
2895#[diag(lint_static_mut_refs_lint)]
2896pub(crate) struct RefOfMutStatic<'a> {
2897    #[label]
2898    pub span: Span,
2899    #[subdiagnostic]
2900    pub sugg: Option<MutRefSugg>,
2901    pub shared_label: &'a str,
2902    #[note(lint_shared_note)]
2903    pub shared_note: bool,
2904    #[note(lint_mut_note)]
2905    pub mut_note: bool,
2906}
2907
2908#[derive(Subdiagnostic)]
2909pub(crate) enum MutRefSugg {
2910    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
2911    Shared {
2912        #[suggestion_part(code = "&raw const ")]
2913        span: Span,
2914    },
2915    #[multipart_suggestion(
2916        lint_suggestion_mut,
2917        style = "verbose",
2918        applicability = "maybe-incorrect"
2919    )]
2920    Mut {
2921        #[suggestion_part(code = "&raw mut ")]
2922        span: Span,
2923    },
2924}
2925
2926#[derive(LintDiagnostic)]
2927#[diag(lint_unqualified_local_imports)]
2928pub(crate) struct UnqualifiedLocalImportsDiag {}
2929
2930#[derive(LintDiagnostic)]
2931#[diag(lint_reserved_string)]
2932pub(crate) struct ReservedString {
2933    #[suggestion(code = " ", applicability = "machine-applicable")]
2934    pub suggestion: Span,
2935}
2936
2937#[derive(LintDiagnostic)]
2938#[diag(lint_reserved_multihash)]
2939pub(crate) struct ReservedMultihash {
2940    #[suggestion(code = " ", applicability = "machine-applicable")]
2941    pub suggestion: Span,
2942}
2943
2944#[derive(LintDiagnostic)]
2945#[diag(lint_function_casts_as_integer)]
2946pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> {
2947    #[subdiagnostic]
2948    pub(crate) sugg: FunctionCastsAsIntegerSugg<'tcx>,
2949}
2950
2951#[derive(Subdiagnostic)]
2952#[suggestion(
2953    lint_cast_as_fn,
2954    code = " as *const ()",
2955    applicability = "machine-applicable",
2956    style = "verbose"
2957)]
2958pub(crate) struct FunctionCastsAsIntegerSugg<'tcx> {
2959    #[primary_span]
2960    pub suggestion: Span,
2961    pub cast_to_ty: Ty<'tcx>,
2962}
2963
2964#[derive(Debug)]
2965pub(crate) struct MismatchedLifetimeSyntaxes {
2966    pub inputs: LifetimeSyntaxCategories<Vec<Span>>,
2967    pub outputs: LifetimeSyntaxCategories<Vec<Span>>,
2968
2969    pub suggestions: Vec<MismatchedLifetimeSyntaxesSuggestion>,
2970}
2971
2972impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSyntaxes {
2973    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
2974        let counts = self.inputs.len() + self.outputs.len();
2975        let message = match counts {
2976            LifetimeSyntaxCategories { hidden: 0, elided: 0, named: 0 } => {
2977                panic!("No lifetime mismatch detected")
2978            }
2979
2980            LifetimeSyntaxCategories { hidden: _, elided: _, named: 0 } => {
2981                fluent::lint_mismatched_lifetime_syntaxes_hiding_while_elided
2982            }
2983
2984            LifetimeSyntaxCategories { hidden: _, elided: 0, named: _ } => {
2985                fluent::lint_mismatched_lifetime_syntaxes_hiding_while_named
2986            }
2987
2988            LifetimeSyntaxCategories { hidden: 0, elided: _, named: _ } => {
2989                fluent::lint_mismatched_lifetime_syntaxes_eliding_while_named
2990            }
2991
2992            LifetimeSyntaxCategories { hidden: _, elided: _, named: _ } => {
2993                fluent::lint_mismatched_lifetime_syntaxes_hiding_and_eliding_while_named
2994            }
2995        };
2996        diag.primary_message(message);
2997
2998        for s in self.inputs.hidden {
2999            diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_hidden);
3000        }
3001        for s in self.inputs.elided {
3002            diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_elided);
3003        }
3004        for s in self.inputs.named {
3005            diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_named);
3006        }
3007
3008        for s in self.outputs.hidden {
3009            diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_hidden);
3010        }
3011        for s in self.outputs.elided {
3012            diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_elided);
3013        }
3014        for s in self.outputs.named {
3015            diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_named);
3016        }
3017
3018        diag.help(fluent::lint_mismatched_lifetime_syntaxes_help);
3019
3020        let mut suggestions = self.suggestions.into_iter();
3021        if let Some(s) = suggestions.next() {
3022            diag.subdiagnostic(s);
3023
3024            for mut s in suggestions {
3025                s.make_optional_alternative();
3026                diag.subdiagnostic(s);
3027            }
3028        }
3029    }
3030}
3031
3032#[derive(Debug)]
3033pub(crate) enum MismatchedLifetimeSyntaxesSuggestion {
3034    Implicit {
3035        suggestions: Vec<Span>,
3036        optional_alternative: bool,
3037    },
3038
3039    Mixed {
3040        implicit_suggestions: Vec<Span>,
3041        explicit_anonymous_suggestions: Vec<(Span, String)>,
3042        optional_alternative: bool,
3043    },
3044
3045    Explicit {
3046        lifetime_name: String,
3047        suggestions: Vec<(Span, String)>,
3048        optional_alternative: bool,
3049    },
3050}
3051
3052impl MismatchedLifetimeSyntaxesSuggestion {
3053    fn make_optional_alternative(&mut self) {
3054        use MismatchedLifetimeSyntaxesSuggestion::*;
3055
3056        let optional_alternative = match self {
3057            Implicit { optional_alternative, .. }
3058            | Mixed { optional_alternative, .. }
3059            | Explicit { optional_alternative, .. } => optional_alternative,
3060        };
3061
3062        *optional_alternative = true;
3063    }
3064}
3065
3066impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion {
3067    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
3068        use MismatchedLifetimeSyntaxesSuggestion::*;
3069
3070        let style = |optional_alternative| {
3071            if optional_alternative {
3072                SuggestionStyle::CompletelyHidden
3073            } else {
3074                SuggestionStyle::ShowAlways
3075            }
3076        };
3077
3078        let applicability = |optional_alternative| {
3079            // `cargo fix` can't handle more than one fix for the same issue,
3080            // so hide alternative suggestions from it by marking them as maybe-incorrect
3081            if optional_alternative {
3082                Applicability::MaybeIncorrect
3083            } else {
3084                Applicability::MachineApplicable
3085            }
3086        };
3087
3088        match self {
3089            Implicit { suggestions, optional_alternative } => {
3090                let suggestions = suggestions.into_iter().map(|s| (s, String::new())).collect();
3091                diag.multipart_suggestion_with_style(
3092                    fluent::lint_mismatched_lifetime_syntaxes_suggestion_implicit,
3093                    suggestions,
3094                    applicability(optional_alternative),
3095                    style(optional_alternative),
3096                );
3097            }
3098
3099            Mixed {
3100                implicit_suggestions,
3101                explicit_anonymous_suggestions,
3102                optional_alternative,
3103            } => {
3104                let message = if implicit_suggestions.is_empty() {
3105                    fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths
3106                } else {
3107                    fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed
3108                };
3109
3110                let implicit_suggestions =
3111                    implicit_suggestions.into_iter().map(|s| (s, String::new()));
3112
3113                let suggestions =
3114                    implicit_suggestions.chain(explicit_anonymous_suggestions).collect();
3115
3116                diag.multipart_suggestion_with_style(
3117                    message,
3118                    suggestions,
3119                    applicability(optional_alternative),
3120                    style(optional_alternative),
3121                );
3122            }
3123
3124            Explicit { lifetime_name, suggestions, optional_alternative } => {
3125                diag.arg("lifetime_name", lifetime_name);
3126                let msg = diag.eagerly_translate(
3127                    fluent::lint_mismatched_lifetime_syntaxes_suggestion_explicit,
3128                );
3129                diag.remove_arg("lifetime_name");
3130                diag.multipart_suggestion_with_style(
3131                    msg,
3132                    suggestions,
3133                    applicability(optional_alternative),
3134                    style(optional_alternative),
3135                );
3136            }
3137        }
3138    }
3139}
3140
3141#[derive(LintDiagnostic)]
3142#[diag(lint_empty_attribute)]
3143#[note]
3144pub(crate) struct EmptyAttributeList {
3145    #[suggestion(code = "", applicability = "machine-applicable")]
3146    pub attr_span: Span,
3147    pub attr_path: String,
3148    pub valid_without_list: bool,
3149}
3150
3151#[derive(LintDiagnostic)]
3152#[diag(lint_invalid_target)]
3153#[warning]
3154#[help]
3155pub(crate) struct InvalidTargetLint {
3156    pub name: String,
3157    pub target: &'static str,
3158    pub applied: DiagArgValue,
3159    pub only: &'static str,
3160    #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
3161    pub attr_span: Span,
3162}
3163
3164#[derive(LintDiagnostic)]
3165#[diag(lint_invalid_style)]
3166pub(crate) struct InvalidAttrStyle {
3167    pub name: String,
3168    pub is_used_as_inner: bool,
3169    #[note]
3170    pub target_span: Option<Span>,
3171    pub target: &'static str,
3172}
3173
3174#[derive(LintDiagnostic)]
3175#[diag(lint_unused_duplicate)]
3176pub(crate) struct UnusedDuplicate {
3177    #[suggestion(code = "", applicability = "machine-applicable")]
3178    pub this: Span,
3179    #[note]
3180    pub other: Span,
3181    #[warning]
3182    pub warning: bool,
3183}
3184
3185#[derive(LintDiagnostic)]
3186#[diag(lint_unsafe_attr_outside_unsafe)]
3187pub(crate) struct UnsafeAttrOutsideUnsafeLint {
3188    #[label]
3189    pub span: Span,
3190    #[subdiagnostic]
3191    pub suggestion: Option<UnsafeAttrOutsideUnsafeSuggestion>,
3192}
3193
3194#[derive(Subdiagnostic)]
3195#[multipart_suggestion(
3196    lint_unsafe_attr_outside_unsafe_suggestion,
3197    applicability = "machine-applicable"
3198)]
3199pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
3200    #[suggestion_part(code = "unsafe(")]
3201    pub left: Span,
3202    #[suggestion_part(code = ")")]
3203    pub right: Span,
3204}
3205
3206#[derive(LintDiagnostic)]
3207#[diag(lint_unused_visibilities)]
3208#[note]
3209pub(crate) struct UnusedVisibility {
3210    #[suggestion(style = "short", code = "", applicability = "machine-applicable")]
3211    pub span: Span,
3212}
3213
3214#[derive(LintDiagnostic)]
3215#[diag(lint_doc_alias_duplicated)]
3216pub(crate) struct DocAliasDuplicated {
3217    #[label]
3218    pub first_defn: Span,
3219}
3220
3221#[derive(LintDiagnostic)]
3222#[diag(lint_doc_auto_cfg_expects_hide_or_show)]
3223pub(crate) struct DocAutoCfgExpectsHideOrShow;
3224
3225#[derive(LintDiagnostic)]
3226#[diag(lint_doc_auto_cfg_hide_show_unexpected_item)]
3227pub(crate) struct DocAutoCfgHideShowUnexpectedItem {
3228    pub attr_name: Symbol,
3229}
3230
3231#[derive(LintDiagnostic)]
3232#[diag(lint_doc_auto_cfg_hide_show_expects_list)]
3233pub(crate) struct DocAutoCfgHideShowExpectsList {
3234    pub attr_name: Symbol,
3235}
3236
3237#[derive(LintDiagnostic)]
3238#[diag(lint_doc_invalid)]
3239pub(crate) struct DocInvalid;
3240
3241#[derive(LintDiagnostic)]
3242#[diag(lint_doc_unknown_include)]
3243pub(crate) struct DocUnknownInclude {
3244    pub inner: &'static str,
3245    pub value: Symbol,
3246    #[suggestion(code = "#{inner}[doc = include_str!(\"{value}\")]")]
3247    pub sugg: (Span, Applicability),
3248}
3249
3250#[derive(LintDiagnostic)]
3251#[diag(lint_doc_unknown_spotlight)]
3252#[note]
3253#[note(lint_no_op_note)]
3254pub(crate) struct DocUnknownSpotlight {
3255    #[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")]
3256    pub sugg_span: Span,
3257}
3258
3259#[derive(LintDiagnostic)]
3260#[diag(lint_doc_unknown_passes)]
3261#[note]
3262#[note(lint_no_op_note)]
3263pub(crate) struct DocUnknownPasses {
3264    pub name: Symbol,
3265    #[label]
3266    pub note_span: Span,
3267}
3268
3269#[derive(LintDiagnostic)]
3270#[diag(lint_doc_unknown_plugins)]
3271#[note]
3272#[note(lint_no_op_note)]
3273pub(crate) struct DocUnknownPlugins {
3274    #[label]
3275    pub label_span: Span,
3276}
3277
3278#[derive(LintDiagnostic)]
3279#[diag(lint_doc_unknown_any)]
3280pub(crate) struct DocUnknownAny {
3281    pub name: Symbol,
3282}
3283
3284#[derive(LintDiagnostic)]
3285#[diag(lint_doc_auto_cfg_wrong_literal)]
3286pub(crate) struct DocAutoCfgWrongLiteral;
3287
3288#[derive(LintDiagnostic)]
3289#[diag(lint_doc_test_takes_list)]
3290pub(crate) struct DocTestTakesList;
3291
3292#[derive(LintDiagnostic)]
3293#[diag(lint_doc_test_unknown)]
3294pub(crate) struct DocTestUnknown {
3295    pub name: Symbol,
3296}
3297
3298#[derive(LintDiagnostic)]
3299#[diag(lint_doc_test_literal)]
3300pub(crate) struct DocTestLiteral;