rustc_lint/
lints.rs

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