rustc_lint/
lints.rs

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