rustc_lint/
lints.rs

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