rustc_lint/
lints.rs

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