rustc_lint/
lints.rs

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