rustc_lint/
lints.rs

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