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