rustc_lint/
lints.rs

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