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, SubdiagMessageOp, 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_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
453        self,
454        diag: &mut Diag<'_, G>,
455        _f: &F,
456    ) {
457        let mut err = self.err;
458        loop {
459            if let Some(span) = err.span {
460                diag.span_note(span, err.message);
461            } else {
462                diag.note(err.message);
463            }
464            if let Some(e) = err.nested {
465                err = *e;
466            } else {
467                break;
468            }
469        }
470    }
471}
472
473#[derive(LintDiagnostic)]
474pub(crate) enum BuiltinClashingExtern<'a> {
475    #[diag(lint_builtin_clashing_extern_same_name)]
476    SameName {
477        this: Symbol,
478        orig: Symbol,
479        #[label(lint_previous_decl_label)]
480        previous_decl_label: Span,
481        #[label(lint_mismatch_label)]
482        mismatch_label: Span,
483        #[subdiagnostic]
484        sub: BuiltinClashingExternSub<'a>,
485    },
486    #[diag(lint_builtin_clashing_extern_diff_name)]
487    DiffName {
488        this: Symbol,
489        orig: Symbol,
490        #[label(lint_previous_decl_label)]
491        previous_decl_label: Span,
492        #[label(lint_mismatch_label)]
493        mismatch_label: Span,
494        #[subdiagnostic]
495        sub: BuiltinClashingExternSub<'a>,
496    },
497}
498
499// FIXME(davidtwco): translatable expected/found
500pub(crate) struct BuiltinClashingExternSub<'a> {
501    pub tcx: TyCtxt<'a>,
502    pub expected: Ty<'a>,
503    pub found: Ty<'a>,
504}
505
506impl Subdiagnostic for BuiltinClashingExternSub<'_> {
507    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
508        self,
509        diag: &mut Diag<'_, G>,
510        _f: &F,
511    ) {
512        let mut expected_str = DiagStyledString::new();
513        expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
514        let mut found_str = DiagStyledString::new();
515        found_str.push(self.found.fn_sig(self.tcx).to_string(), true);
516        diag.note_expected_found(&"", expected_str, &"", found_str);
517    }
518}
519
520#[derive(LintDiagnostic)]
521#[diag(lint_builtin_deref_nullptr)]
522pub(crate) struct BuiltinDerefNullptr {
523    #[label]
524    pub label: Span,
525}
526
527// FIXME: migrate fluent::lint::builtin_asm_labels
528
529#[derive(LintDiagnostic)]
530pub(crate) enum BuiltinSpecialModuleNameUsed {
531    #[diag(lint_builtin_special_module_name_used_lib)]
532    #[note]
533    #[help]
534    Lib,
535    #[diag(lint_builtin_special_module_name_used_main)]
536    #[note]
537    Main,
538}
539
540// deref_into_dyn_supertrait.rs
541#[derive(LintDiagnostic)]
542#[diag(lint_supertrait_as_deref_target)]
543pub(crate) struct SupertraitAsDerefTarget<'a> {
544    pub self_ty: Ty<'a>,
545    pub supertrait_principal: PolyExistentialTraitRef<'a>,
546    pub target_principal: PolyExistentialTraitRef<'a>,
547    #[label]
548    pub label: Span,
549    #[subdiagnostic]
550    pub label2: Option<SupertraitAsDerefTargetLabel>,
551}
552
553#[derive(Subdiagnostic)]
554#[label(lint_label2)]
555pub(crate) struct SupertraitAsDerefTargetLabel {
556    #[primary_span]
557    pub label: Span,
558}
559
560// enum_intrinsics_non_enums.rs
561#[derive(LintDiagnostic)]
562#[diag(lint_enum_intrinsics_mem_discriminant)]
563pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> {
564    pub ty_param: Ty<'a>,
565    #[note]
566    pub note: Span,
567}
568
569#[derive(LintDiagnostic)]
570#[diag(lint_enum_intrinsics_mem_variant)]
571#[note]
572pub(crate) struct EnumIntrinsicsMemVariant<'a> {
573    pub ty_param: Ty<'a>,
574}
575
576// expect.rs
577#[derive(LintDiagnostic)]
578#[diag(lint_expectation)]
579pub(crate) struct Expectation {
580    #[subdiagnostic]
581    pub rationale: Option<ExpectationNote>,
582    #[note]
583    pub note: bool,
584}
585
586#[derive(Subdiagnostic)]
587#[note(lint_rationale)]
588pub(crate) struct ExpectationNote {
589    pub rationale: Symbol,
590}
591
592// ptr_nulls.rs
593#[derive(LintDiagnostic)]
594pub(crate) enum PtrNullChecksDiag<'a> {
595    #[diag(lint_ptr_null_checks_fn_ptr)]
596    #[help(lint_help)]
597    FnPtr {
598        orig_ty: Ty<'a>,
599        #[label]
600        label: Span,
601    },
602    #[diag(lint_ptr_null_checks_ref)]
603    Ref {
604        orig_ty: Ty<'a>,
605        #[label]
606        label: Span,
607    },
608    #[diag(lint_ptr_null_checks_fn_ret)]
609    FnRet { fn_name: Ident },
610}
611
612// for_loops_over_fallibles.rs
613#[derive(LintDiagnostic)]
614#[diag(lint_for_loops_over_fallibles)]
615pub(crate) struct ForLoopsOverFalliblesDiag<'a> {
616    pub article: &'static str,
617    pub ref_prefix: &'static str,
618    pub ty: &'static str,
619    #[subdiagnostic]
620    pub sub: ForLoopsOverFalliblesLoopSub<'a>,
621    #[subdiagnostic]
622    pub question_mark: Option<ForLoopsOverFalliblesQuestionMark>,
623    #[subdiagnostic]
624    pub suggestion: ForLoopsOverFalliblesSuggestion<'a>,
625}
626
627#[derive(Subdiagnostic)]
628pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> {
629    #[suggestion(lint_remove_next, code = ".by_ref()", applicability = "maybe-incorrect")]
630    RemoveNext {
631        #[primary_span]
632        suggestion: Span,
633        recv_snip: String,
634    },
635    #[multipart_suggestion(lint_use_while_let, applicability = "maybe-incorrect")]
636    UseWhileLet {
637        #[suggestion_part(code = "while let {var}(")]
638        start_span: Span,
639        #[suggestion_part(code = ") = ")]
640        end_span: Span,
641        var: &'a str,
642    },
643}
644
645#[derive(Subdiagnostic)]
646#[suggestion(lint_use_question_mark, code = "?", applicability = "maybe-incorrect")]
647pub(crate) struct ForLoopsOverFalliblesQuestionMark {
648    #[primary_span]
649    pub suggestion: Span,
650}
651
652#[derive(Subdiagnostic)]
653#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
654pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> {
655    pub var: &'a str,
656    #[suggestion_part(code = "if let {var}(")]
657    pub start_span: Span,
658    #[suggestion_part(code = ") = ")]
659    pub end_span: Span,
660}
661
662#[derive(Subdiagnostic)]
663pub(crate) enum UseLetUnderscoreIgnoreSuggestion {
664    #[note(lint_use_let_underscore_ignore_suggestion)]
665    Note,
666    #[multipart_suggestion(
667        lint_use_let_underscore_ignore_suggestion,
668        style = "verbose",
669        applicability = "maybe-incorrect"
670    )]
671    Suggestion {
672        #[suggestion_part(code = "let _ = ")]
673        start_span: Span,
674        #[suggestion_part(code = "")]
675        end_span: Span,
676    },
677}
678
679// drop_forget_useless.rs
680#[derive(LintDiagnostic)]
681#[diag(lint_dropping_references)]
682pub(crate) struct DropRefDiag<'a> {
683    pub arg_ty: Ty<'a>,
684    #[label]
685    pub label: Span,
686    #[subdiagnostic]
687    pub sugg: UseLetUnderscoreIgnoreSuggestion,
688}
689
690#[derive(LintDiagnostic)]
691#[diag(lint_dropping_copy_types)]
692pub(crate) struct DropCopyDiag<'a> {
693    pub arg_ty: Ty<'a>,
694    #[label]
695    pub label: Span,
696    #[subdiagnostic]
697    pub sugg: UseLetUnderscoreIgnoreSuggestion,
698}
699
700#[derive(LintDiagnostic)]
701#[diag(lint_forgetting_references)]
702pub(crate) struct ForgetRefDiag<'a> {
703    pub arg_ty: Ty<'a>,
704    #[label]
705    pub label: Span,
706    #[subdiagnostic]
707    pub sugg: UseLetUnderscoreIgnoreSuggestion,
708}
709
710#[derive(LintDiagnostic)]
711#[diag(lint_forgetting_copy_types)]
712pub(crate) struct ForgetCopyDiag<'a> {
713    pub arg_ty: Ty<'a>,
714    #[label]
715    pub label: Span,
716    #[subdiagnostic]
717    pub sugg: UseLetUnderscoreIgnoreSuggestion,
718}
719
720#[derive(LintDiagnostic)]
721#[diag(lint_undropped_manually_drops)]
722pub(crate) struct UndroppedManuallyDropsDiag<'a> {
723    pub arg_ty: Ty<'a>,
724    #[label]
725    pub label: Span,
726    #[subdiagnostic]
727    pub suggestion: UndroppedManuallyDropsSuggestion,
728}
729
730#[derive(Subdiagnostic)]
731#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
732pub(crate) struct UndroppedManuallyDropsSuggestion {
733    #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")]
734    pub start_span: Span,
735    #[suggestion_part(code = ")")]
736    pub end_span: Span,
737}
738
739// invalid_from_utf8.rs
740#[derive(LintDiagnostic)]
741pub(crate) enum InvalidFromUtf8Diag {
742    #[diag(lint_invalid_from_utf8_unchecked)]
743    Unchecked {
744        method: String,
745        valid_up_to: usize,
746        #[label]
747        label: Span,
748    },
749    #[diag(lint_invalid_from_utf8_checked)]
750    Checked {
751        method: String,
752        valid_up_to: usize,
753        #[label]
754        label: Span,
755    },
756}
757
758// reference_casting.rs
759#[derive(LintDiagnostic)]
760pub(crate) enum InvalidReferenceCastingDiag<'tcx> {
761    #[diag(lint_invalid_reference_casting_borrow_as_mut)]
762    #[note(lint_invalid_reference_casting_note_book)]
763    BorrowAsMut {
764        #[label]
765        orig_cast: Option<Span>,
766        #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
767        ty_has_interior_mutability: bool,
768    },
769    #[diag(lint_invalid_reference_casting_assign_to_ref)]
770    #[note(lint_invalid_reference_casting_note_book)]
771    AssignToRef {
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_bigger_layout)]
778    #[note(lint_layout)]
779    BiggerLayout {
780        #[label]
781        orig_cast: Option<Span>,
782        #[label(lint_alloc)]
783        alloc: Span,
784        from_ty: Ty<'tcx>,
785        from_size: u64,
786        to_ty: Ty<'tcx>,
787        to_size: u64,
788    },
789}
790
791// hidden_unicode_codepoints.rs
792#[derive(LintDiagnostic)]
793#[diag(lint_hidden_unicode_codepoints)]
794#[note]
795pub(crate) struct HiddenUnicodeCodepointsDiag<'a> {
796    pub label: &'a str,
797    pub count: usize,
798    #[label]
799    pub span_label: Span,
800    #[subdiagnostic]
801    pub labels: Option<HiddenUnicodeCodepointsDiagLabels>,
802    #[subdiagnostic]
803    pub sub: HiddenUnicodeCodepointsDiagSub,
804}
805
806pub(crate) struct HiddenUnicodeCodepointsDiagLabels {
807    pub spans: Vec<(char, Span)>,
808}
809
810impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels {
811    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
812        self,
813        diag: &mut Diag<'_, G>,
814        _f: &F,
815    ) {
816        for (c, span) in self.spans {
817            diag.span_label(span, format!("{c:?}"));
818        }
819    }
820}
821
822pub(crate) enum HiddenUnicodeCodepointsDiagSub {
823    Escape { spans: Vec<(char, Span)> },
824    NoEscape { spans: Vec<(char, Span)> },
825}
826
827// Used because of multiple multipart_suggestion and note
828impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub {
829    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
830        self,
831        diag: &mut Diag<'_, G>,
832        _f: &F,
833    ) {
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_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1003        self,
1004        diag: &mut Diag<'_, G>,
1005        _f: &F,
1006    ) {
1007        let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
1008
1009        if can_suggest_binding {
1010            let prefix = if self.is_assign_desugar { "let " } else { "" };
1011            diag.span_suggestion_verbose(
1012                self.suggestion,
1013                fluent::lint_non_binding_let_suggestion,
1014                format!("{prefix}_unused"),
1015                Applicability::MachineApplicable,
1016            );
1017        } else {
1018            diag.span_help(self.suggestion, fluent::lint_non_binding_let_suggestion);
1019        }
1020        if let Some(drop_fn_start_end) = self.drop_fn_start_end {
1021            diag.multipart_suggestion(
1022                fluent::lint_non_binding_let_multi_suggestion,
1023                vec![
1024                    (drop_fn_start_end.0, "drop(".to_string()),
1025                    (drop_fn_start_end.1, ")".to_string()),
1026                ],
1027                Applicability::MachineApplicable,
1028            );
1029        } else {
1030            diag.help(fluent::lint_non_binding_let_multi_drop_fn);
1031        }
1032    }
1033}
1034
1035// levels.rs
1036#[derive(LintDiagnostic)]
1037#[diag(lint_overruled_attribute)]
1038pub(crate) struct OverruledAttributeLint<'a> {
1039    #[label]
1040    pub overruled: Span,
1041    pub lint_level: &'a str,
1042    pub lint_source: Symbol,
1043    #[subdiagnostic]
1044    pub sub: OverruledAttributeSub,
1045}
1046
1047#[derive(LintDiagnostic)]
1048#[diag(lint_deprecated_lint_name)]
1049pub(crate) struct DeprecatedLintName<'a> {
1050    pub name: String,
1051    #[suggestion(code = "{replace}", applicability = "machine-applicable")]
1052    pub suggestion: Span,
1053    pub replace: &'a str,
1054}
1055
1056#[derive(LintDiagnostic)]
1057#[diag(lint_deprecated_lint_name)]
1058#[help]
1059pub(crate) struct DeprecatedLintNameFromCommandLine<'a> {
1060    pub name: String,
1061    pub replace: &'a str,
1062    #[subdiagnostic]
1063    pub requested_level: RequestedLevel<'a>,
1064}
1065
1066#[derive(LintDiagnostic)]
1067#[diag(lint_renamed_lint)]
1068pub(crate) struct RenamedLint<'a> {
1069    pub name: &'a str,
1070    #[subdiagnostic]
1071    pub suggestion: RenamedLintSuggestion<'a>,
1072}
1073
1074#[derive(Subdiagnostic)]
1075pub(crate) enum RenamedLintSuggestion<'a> {
1076    #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
1077    WithSpan {
1078        #[primary_span]
1079        suggestion: Span,
1080        replace: &'a str,
1081    },
1082    #[help(lint_help)]
1083    WithoutSpan { replace: &'a str },
1084}
1085
1086#[derive(LintDiagnostic)]
1087#[diag(lint_renamed_lint)]
1088pub(crate) struct RenamedLintFromCommandLine<'a> {
1089    pub name: &'a str,
1090    #[subdiagnostic]
1091    pub suggestion: RenamedLintSuggestion<'a>,
1092    #[subdiagnostic]
1093    pub requested_level: RequestedLevel<'a>,
1094}
1095
1096#[derive(LintDiagnostic)]
1097#[diag(lint_removed_lint)]
1098pub(crate) struct RemovedLint<'a> {
1099    pub name: &'a str,
1100    pub reason: &'a str,
1101}
1102
1103#[derive(LintDiagnostic)]
1104#[diag(lint_removed_lint)]
1105pub(crate) struct RemovedLintFromCommandLine<'a> {
1106    pub name: &'a str,
1107    pub reason: &'a str,
1108    #[subdiagnostic]
1109    pub requested_level: RequestedLevel<'a>,
1110}
1111
1112#[derive(LintDiagnostic)]
1113#[diag(lint_unknown_lint)]
1114pub(crate) struct UnknownLint {
1115    pub name: String,
1116    #[subdiagnostic]
1117    pub suggestion: Option<UnknownLintSuggestion>,
1118}
1119
1120#[derive(Subdiagnostic)]
1121pub(crate) enum UnknownLintSuggestion {
1122    #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1123    WithSpan {
1124        #[primary_span]
1125        suggestion: Span,
1126        replace: Symbol,
1127        from_rustc: bool,
1128    },
1129    #[help(lint_help)]
1130    WithoutSpan { replace: Symbol, from_rustc: bool },
1131}
1132
1133#[derive(LintDiagnostic)]
1134#[diag(lint_unknown_lint, code = E0602)]
1135pub(crate) struct UnknownLintFromCommandLine<'a> {
1136    pub name: String,
1137    #[subdiagnostic]
1138    pub suggestion: Option<UnknownLintSuggestion>,
1139    #[subdiagnostic]
1140    pub requested_level: RequestedLevel<'a>,
1141}
1142
1143#[derive(LintDiagnostic)]
1144#[diag(lint_ignored_unless_crate_specified)]
1145pub(crate) struct IgnoredUnlessCrateSpecified<'a> {
1146    pub level: &'a str,
1147    pub name: Symbol,
1148}
1149
1150// dangling.rs
1151#[derive(LintDiagnostic)]
1152#[diag(lint_dangling_pointers_from_temporaries)]
1153#[note]
1154#[help(lint_help_bind)]
1155#[help(lint_help_returned)]
1156#[help(lint_help_visit)]
1157// FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts
1158pub(crate) struct DanglingPointersFromTemporaries<'tcx> {
1159    pub callee: Ident,
1160    pub ty: Ty<'tcx>,
1161    #[label(lint_label_ptr)]
1162    pub ptr_span: Span,
1163    #[label(lint_label_temporary)]
1164    pub temporary_span: Span,
1165}
1166
1167// multiple_supertrait_upcastable.rs
1168#[derive(LintDiagnostic)]
1169#[diag(lint_multiple_supertrait_upcastable)]
1170pub(crate) struct MultipleSupertraitUpcastable {
1171    pub ident: Ident,
1172}
1173
1174// non_ascii_idents.rs
1175#[derive(LintDiagnostic)]
1176#[diag(lint_identifier_non_ascii_char)]
1177pub(crate) struct IdentifierNonAsciiChar;
1178
1179#[derive(LintDiagnostic)]
1180#[diag(lint_identifier_uncommon_codepoints)]
1181#[note]
1182pub(crate) struct IdentifierUncommonCodepoints {
1183    pub codepoints: Vec<char>,
1184    pub codepoints_len: usize,
1185    pub identifier_type: &'static str,
1186}
1187
1188#[derive(LintDiagnostic)]
1189#[diag(lint_confusable_identifier_pair)]
1190pub(crate) struct ConfusableIdentifierPair {
1191    pub existing_sym: Symbol,
1192    pub sym: Symbol,
1193    #[label(lint_other_use)]
1194    pub label: Span,
1195    #[label(lint_current_use)]
1196    pub main_label: Span,
1197}
1198
1199#[derive(LintDiagnostic)]
1200#[diag(lint_mixed_script_confusables)]
1201#[note(lint_includes_note)]
1202#[note]
1203pub(crate) struct MixedScriptConfusables {
1204    pub set: String,
1205    pub includes: String,
1206}
1207
1208// non_fmt_panic.rs
1209pub(crate) struct NonFmtPanicUnused {
1210    pub count: usize,
1211    pub suggestion: Option<Span>,
1212}
1213
1214// Used because of two suggestions based on one Option<Span>
1215impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused {
1216    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1217        diag.primary_message(fluent::lint_non_fmt_panic_unused);
1218        diag.arg("count", self.count);
1219        diag.note(fluent::lint_note);
1220        if let Some(span) = self.suggestion {
1221            diag.span_suggestion(
1222                span.shrink_to_hi(),
1223                fluent::lint_add_args_suggestion,
1224                ", ...",
1225                Applicability::HasPlaceholders,
1226            );
1227            diag.span_suggestion(
1228                span.shrink_to_lo(),
1229                fluent::lint_add_fmt_suggestion,
1230                "\"{}\", ",
1231                Applicability::MachineApplicable,
1232            );
1233        }
1234    }
1235}
1236
1237#[derive(LintDiagnostic)]
1238#[diag(lint_non_fmt_panic_braces)]
1239#[note]
1240pub(crate) struct NonFmtPanicBraces {
1241    pub count: usize,
1242    #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
1243    pub suggestion: Option<Span>,
1244}
1245
1246// nonstandard_style.rs
1247#[derive(LintDiagnostic)]
1248#[diag(lint_non_camel_case_type)]
1249pub(crate) struct NonCamelCaseType<'a> {
1250    pub sort: &'a str,
1251    pub name: &'a str,
1252    #[subdiagnostic]
1253    pub sub: NonCamelCaseTypeSub,
1254}
1255
1256#[derive(Subdiagnostic)]
1257pub(crate) enum NonCamelCaseTypeSub {
1258    #[label(lint_label)]
1259    Label {
1260        #[primary_span]
1261        span: Span,
1262    },
1263    #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1264    Suggestion {
1265        #[primary_span]
1266        span: Span,
1267        replace: String,
1268    },
1269}
1270
1271#[derive(LintDiagnostic)]
1272#[diag(lint_non_snake_case)]
1273pub(crate) struct NonSnakeCaseDiag<'a> {
1274    pub sort: &'a str,
1275    pub name: &'a str,
1276    pub sc: String,
1277    #[subdiagnostic]
1278    pub sub: NonSnakeCaseDiagSub,
1279}
1280
1281pub(crate) enum NonSnakeCaseDiagSub {
1282    Label { span: Span },
1283    Help,
1284    RenameOrConvertSuggestion { span: Span, suggestion: Ident },
1285    ConvertSuggestion { span: Span, suggestion: String },
1286    SuggestionAndNote { span: Span },
1287}
1288
1289impl Subdiagnostic for NonSnakeCaseDiagSub {
1290    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1291        self,
1292        diag: &mut Diag<'_, G>,
1293        _f: &F,
1294    ) {
1295        match self {
1296            NonSnakeCaseDiagSub::Label { span } => {
1297                diag.span_label(span, fluent::lint_label);
1298            }
1299            NonSnakeCaseDiagSub::Help => {
1300                diag.help(fluent::lint_help);
1301            }
1302            NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
1303                diag.span_suggestion(
1304                    span,
1305                    fluent::lint_convert_suggestion,
1306                    suggestion,
1307                    Applicability::MaybeIncorrect,
1308                );
1309            }
1310            NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
1311                diag.span_suggestion(
1312                    span,
1313                    fluent::lint_rename_or_convert_suggestion,
1314                    suggestion,
1315                    Applicability::MaybeIncorrect,
1316                );
1317            }
1318            NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
1319                diag.note(fluent::lint_cannot_convert_note);
1320                diag.span_suggestion(
1321                    span,
1322                    fluent::lint_rename_suggestion,
1323                    "",
1324                    Applicability::MaybeIncorrect,
1325                );
1326            }
1327        }
1328    }
1329}
1330
1331#[derive(LintDiagnostic)]
1332#[diag(lint_non_upper_case_global)]
1333pub(crate) struct NonUpperCaseGlobal<'a> {
1334    pub sort: &'a str,
1335    pub name: &'a str,
1336    #[subdiagnostic]
1337    pub sub: NonUpperCaseGlobalSub,
1338}
1339
1340#[derive(Subdiagnostic)]
1341pub(crate) enum NonUpperCaseGlobalSub {
1342    #[label(lint_label)]
1343    Label {
1344        #[primary_span]
1345        span: Span,
1346    },
1347    #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1348    Suggestion {
1349        #[primary_span]
1350        span: Span,
1351        replace: String,
1352    },
1353}
1354
1355// noop_method_call.rs
1356#[derive(LintDiagnostic)]
1357#[diag(lint_noop_method_call)]
1358#[note]
1359pub(crate) struct NoopMethodCallDiag<'a> {
1360    pub method: Ident,
1361    pub orig_ty: Ty<'a>,
1362    pub trait_: Symbol,
1363    #[suggestion(code = "", applicability = "machine-applicable")]
1364    pub label: Span,
1365    #[suggestion(
1366        lint_derive_suggestion,
1367        code = "#[derive(Clone)]\n",
1368        applicability = "maybe-incorrect"
1369    )]
1370    pub suggest_derive: Option<Span>,
1371}
1372
1373#[derive(LintDiagnostic)]
1374#[diag(lint_suspicious_double_ref_deref)]
1375pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> {
1376    pub ty: Ty<'a>,
1377}
1378
1379#[derive(LintDiagnostic)]
1380#[diag(lint_suspicious_double_ref_clone)]
1381pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> {
1382    pub ty: Ty<'a>,
1383}
1384
1385// non_local_defs.rs
1386pub(crate) enum NonLocalDefinitionsDiag {
1387    Impl {
1388        depth: u32,
1389        body_kind_descr: &'static str,
1390        body_name: String,
1391        cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
1392        const_anon: Option<Option<Span>>,
1393        doctest: bool,
1394        macro_to_change: Option<(String, &'static str)>,
1395    },
1396    MacroRules {
1397        depth: u32,
1398        body_kind_descr: &'static str,
1399        body_name: String,
1400        doctest: bool,
1401        cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
1402    },
1403}
1404
1405impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
1406    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1407        match self {
1408            NonLocalDefinitionsDiag::Impl {
1409                depth,
1410                body_kind_descr,
1411                body_name,
1412                cargo_update,
1413                const_anon,
1414                doctest,
1415                macro_to_change,
1416            } => {
1417                diag.primary_message(fluent::lint_non_local_definitions_impl);
1418                diag.arg("depth", depth);
1419                diag.arg("body_kind_descr", body_kind_descr);
1420                diag.arg("body_name", body_name);
1421
1422                if let Some((macro_to_change, macro_kind)) = macro_to_change {
1423                    diag.arg("macro_to_change", macro_to_change);
1424                    diag.arg("macro_kind", macro_kind);
1425                    diag.note(fluent::lint_macro_to_change);
1426                }
1427                if let Some(cargo_update) = cargo_update {
1428                    diag.subdiagnostic(cargo_update);
1429                }
1430
1431                diag.note(fluent::lint_non_local);
1432
1433                if doctest {
1434                    diag.help(fluent::lint_doctest);
1435                }
1436
1437                if let Some(const_anon) = const_anon {
1438                    diag.note(fluent::lint_exception);
1439                    if let Some(const_anon) = const_anon {
1440                        diag.span_suggestion(
1441                            const_anon,
1442                            fluent::lint_const_anon,
1443                            "_",
1444                            Applicability::MachineApplicable,
1445                        );
1446                    }
1447                }
1448            }
1449            NonLocalDefinitionsDiag::MacroRules {
1450                depth,
1451                body_kind_descr,
1452                body_name,
1453                doctest,
1454                cargo_update,
1455            } => {
1456                diag.primary_message(fluent::lint_non_local_definitions_macro_rules);
1457                diag.arg("depth", depth);
1458                diag.arg("body_kind_descr", body_kind_descr);
1459                diag.arg("body_name", body_name);
1460
1461                if doctest {
1462                    diag.help(fluent::lint_help_doctest);
1463                } else {
1464                    diag.help(fluent::lint_help);
1465                }
1466
1467                diag.note(fluent::lint_non_local);
1468
1469                if let Some(cargo_update) = cargo_update {
1470                    diag.subdiagnostic(cargo_update);
1471                }
1472            }
1473        }
1474    }
1475}
1476
1477#[derive(Subdiagnostic)]
1478#[note(lint_non_local_definitions_cargo_update)]
1479pub(crate) struct NonLocalDefinitionsCargoUpdateNote {
1480    pub macro_kind: &'static str,
1481    pub macro_name: Symbol,
1482    pub crate_name: Symbol,
1483}
1484
1485// precedence.rs
1486#[derive(LintDiagnostic)]
1487#[diag(lint_ambiguous_negative_literals)]
1488#[note(lint_example)]
1489pub(crate) struct AmbiguousNegativeLiteralsDiag {
1490    #[subdiagnostic]
1491    pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
1492    #[subdiagnostic]
1493    pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion,
1494}
1495
1496#[derive(Subdiagnostic)]
1497#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")]
1498pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
1499    #[suggestion_part(code = "(")]
1500    pub start_span: Span,
1501    #[suggestion_part(code = ")")]
1502    pub end_span: Span,
1503}
1504
1505#[derive(Subdiagnostic)]
1506#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")]
1507pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
1508    #[suggestion_part(code = "(")]
1509    pub start_span: Span,
1510    #[suggestion_part(code = ")")]
1511    pub end_span: Span,
1512}
1513
1514// pass_by_value.rs
1515#[derive(LintDiagnostic)]
1516#[diag(lint_pass_by_value)]
1517pub(crate) struct PassByValueDiag {
1518    pub ty: String,
1519    #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
1520    pub suggestion: Span,
1521}
1522
1523// redundant_semicolon.rs
1524#[derive(LintDiagnostic)]
1525#[diag(lint_redundant_semicolons)]
1526pub(crate) struct RedundantSemicolonsDiag {
1527    pub multiple: bool,
1528    #[suggestion(code = "", applicability = "maybe-incorrect")]
1529    pub suggestion: Span,
1530}
1531
1532// traits.rs
1533pub(crate) struct DropTraitConstraintsDiag<'a> {
1534    pub predicate: Clause<'a>,
1535    pub tcx: TyCtxt<'a>,
1536    pub def_id: DefId,
1537}
1538
1539// Needed for def_path_str
1540impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> {
1541    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1542        diag.primary_message(fluent::lint_drop_trait_constraints);
1543        diag.arg("predicate", self.predicate);
1544        diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
1545    }
1546}
1547
1548pub(crate) struct DropGlue<'a> {
1549    pub tcx: TyCtxt<'a>,
1550    pub def_id: DefId,
1551}
1552
1553// Needed for def_path_str
1554impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> {
1555    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1556        diag.primary_message(fluent::lint_drop_glue);
1557        diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
1558    }
1559}
1560
1561// types.rs
1562#[derive(LintDiagnostic)]
1563#[diag(lint_range_endpoint_out_of_range)]
1564pub(crate) struct RangeEndpointOutOfRange<'a> {
1565    pub ty: &'a str,
1566    #[subdiagnostic]
1567    pub sub: UseInclusiveRange<'a>,
1568}
1569
1570#[derive(Subdiagnostic)]
1571pub(crate) enum UseInclusiveRange<'a> {
1572    #[suggestion(
1573        lint_range_use_inclusive_range,
1574        code = "{start}..={literal}{suffix}",
1575        applicability = "machine-applicable"
1576    )]
1577    WithoutParen {
1578        #[primary_span]
1579        sugg: Span,
1580        start: String,
1581        literal: u128,
1582        suffix: &'a str,
1583    },
1584    #[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")]
1585    WithParen {
1586        #[suggestion_part(code = "=")]
1587        eq_sugg: Span,
1588        #[suggestion_part(code = "{literal}{suffix}")]
1589        lit_sugg: Span,
1590        literal: u128,
1591        suffix: &'a str,
1592    },
1593}
1594
1595#[derive(LintDiagnostic)]
1596#[diag(lint_overflowing_bin_hex)]
1597pub(crate) struct OverflowingBinHex<'a> {
1598    pub ty: &'a str,
1599    pub lit: String,
1600    pub dec: u128,
1601    pub actually: String,
1602    #[subdiagnostic]
1603    pub sign: OverflowingBinHexSign,
1604    #[subdiagnostic]
1605    pub sub: Option<OverflowingBinHexSub<'a>>,
1606    #[subdiagnostic]
1607    pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>,
1608}
1609
1610pub(crate) enum OverflowingBinHexSign {
1611    Positive,
1612    Negative,
1613}
1614
1615impl Subdiagnostic for OverflowingBinHexSign {
1616    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1617        self,
1618        diag: &mut Diag<'_, G>,
1619        _f: &F,
1620    ) {
1621        match self {
1622            OverflowingBinHexSign::Positive => {
1623                diag.note(fluent::lint_positive_note);
1624            }
1625            OverflowingBinHexSign::Negative => {
1626                diag.note(fluent::lint_negative_note);
1627                diag.note(fluent::lint_negative_becomes_note);
1628            }
1629        }
1630    }
1631}
1632
1633#[derive(Subdiagnostic)]
1634pub(crate) enum OverflowingBinHexSub<'a> {
1635    #[suggestion(
1636        lint_suggestion,
1637        code = "{sans_suffix}{suggestion_ty}",
1638        applicability = "machine-applicable"
1639    )]
1640    Suggestion {
1641        #[primary_span]
1642        span: Span,
1643        suggestion_ty: &'a str,
1644        sans_suffix: &'a str,
1645    },
1646    #[help(lint_help)]
1647    Help { suggestion_ty: &'a str },
1648}
1649
1650#[derive(Subdiagnostic)]
1651#[suggestion(
1652    lint_sign_bit_suggestion,
1653    code = "{lit_no_suffix}{uint_ty} as {int_ty}",
1654    applicability = "maybe-incorrect"
1655)]
1656pub(crate) struct OverflowingBinHexSignBitSub<'a> {
1657    #[primary_span]
1658    pub span: Span,
1659    pub lit_no_suffix: &'a str,
1660    pub negative_val: String,
1661    pub uint_ty: &'a str,
1662    pub int_ty: &'a str,
1663}
1664
1665#[derive(LintDiagnostic)]
1666#[diag(lint_overflowing_int)]
1667#[note]
1668pub(crate) struct OverflowingInt<'a> {
1669    pub ty: &'a str,
1670    pub lit: String,
1671    pub min: i128,
1672    pub max: u128,
1673    #[subdiagnostic]
1674    pub help: Option<OverflowingIntHelp<'a>>,
1675}
1676
1677#[derive(Subdiagnostic)]
1678#[help(lint_help)]
1679pub(crate) struct OverflowingIntHelp<'a> {
1680    pub suggestion_ty: &'a str,
1681}
1682
1683#[derive(LintDiagnostic)]
1684#[diag(lint_only_cast_u8_to_char)]
1685pub(crate) struct OnlyCastu8ToChar {
1686    #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
1687    pub span: Span,
1688    pub literal: u128,
1689}
1690
1691#[derive(LintDiagnostic)]
1692#[diag(lint_overflowing_uint)]
1693#[note]
1694pub(crate) struct OverflowingUInt<'a> {
1695    pub ty: &'a str,
1696    pub lit: String,
1697    pub min: u128,
1698    pub max: u128,
1699}
1700
1701#[derive(LintDiagnostic)]
1702#[diag(lint_overflowing_literal)]
1703#[note]
1704pub(crate) struct OverflowingLiteral<'a> {
1705    pub ty: &'a str,
1706    pub lit: String,
1707}
1708
1709#[derive(LintDiagnostic)]
1710#[diag(lint_uses_power_alignment)]
1711pub(crate) struct UsesPowerAlignment;
1712
1713#[derive(LintDiagnostic)]
1714#[diag(lint_unused_comparisons)]
1715pub(crate) struct UnusedComparisons;
1716
1717#[derive(LintDiagnostic)]
1718pub(crate) enum InvalidNanComparisons {
1719    #[diag(lint_invalid_nan_comparisons_eq_ne)]
1720    EqNe {
1721        #[subdiagnostic]
1722        suggestion: InvalidNanComparisonsSuggestion,
1723    },
1724    #[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)]
1725    LtLeGtGe,
1726}
1727
1728#[derive(Subdiagnostic)]
1729pub(crate) enum InvalidNanComparisonsSuggestion {
1730    #[multipart_suggestion(
1731        lint_suggestion,
1732        style = "verbose",
1733        applicability = "machine-applicable"
1734    )]
1735    Spanful {
1736        #[suggestion_part(code = "!")]
1737        neg: Option<Span>,
1738        #[suggestion_part(code = ".is_nan()")]
1739        float: Span,
1740        #[suggestion_part(code = "")]
1741        nan_plus_binop: Span,
1742    },
1743    #[help(lint_suggestion)]
1744    Spanless,
1745}
1746
1747#[derive(LintDiagnostic)]
1748pub(crate) enum AmbiguousWidePointerComparisons<'a> {
1749    #[diag(lint_ambiguous_wide_pointer_comparisons)]
1750    Spanful {
1751        #[subdiagnostic]
1752        addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>,
1753        #[subdiagnostic]
1754        addr_metadata_suggestion: Option<AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a>>,
1755    },
1756    #[diag(lint_ambiguous_wide_pointer_comparisons)]
1757    #[help(lint_addr_metadata_suggestion)]
1758    #[help(lint_addr_suggestion)]
1759    Spanless,
1760}
1761
1762#[derive(Subdiagnostic)]
1763#[multipart_suggestion(
1764    lint_addr_metadata_suggestion,
1765    style = "verbose",
1766    // FIXME(#53934): make machine-applicable again
1767    applicability = "maybe-incorrect"
1768)]
1769pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> {
1770    pub ne: &'a str,
1771    pub deref_left: &'a str,
1772    pub deref_right: &'a str,
1773    pub l_modifiers: &'a str,
1774    pub r_modifiers: &'a str,
1775    #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")]
1776    pub left: Span,
1777    #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
1778    pub middle: Span,
1779    #[suggestion_part(code = "{r_modifiers})")]
1780    pub right: Span,
1781}
1782
1783#[derive(Subdiagnostic)]
1784pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
1785    #[multipart_suggestion(
1786        lint_addr_suggestion,
1787        style = "verbose",
1788        // FIXME(#53934): make machine-applicable again
1789        applicability = "maybe-incorrect"
1790    )]
1791    AddrEq {
1792        ne: &'a str,
1793        deref_left: &'a str,
1794        deref_right: &'a str,
1795        l_modifiers: &'a str,
1796        r_modifiers: &'a str,
1797        #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
1798        left: Span,
1799        #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
1800        middle: Span,
1801        #[suggestion_part(code = "{r_modifiers})")]
1802        right: Span,
1803    },
1804    #[multipart_suggestion(
1805        lint_addr_suggestion,
1806        style = "verbose",
1807        // FIXME(#53934): make machine-applicable again
1808        applicability = "maybe-incorrect"
1809    )]
1810    Cast {
1811        deref_left: &'a str,
1812        deref_right: &'a str,
1813        paren_left: &'a str,
1814        paren_right: &'a str,
1815        l_modifiers: &'a str,
1816        r_modifiers: &'a str,
1817        #[suggestion_part(code = "({deref_left}")]
1818        left_before: Option<Span>,
1819        #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")]
1820        left_after: Span,
1821        #[suggestion_part(code = "({deref_right}")]
1822        right_before: Option<Span>,
1823        #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")]
1824        right_after: Span,
1825    },
1826}
1827
1828#[derive(LintDiagnostic)]
1829pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> {
1830    #[diag(lint_unpredictable_fn_pointer_comparisons)]
1831    #[note(lint_note_duplicated_fn)]
1832    #[note(lint_note_deduplicated_fn)]
1833    #[note(lint_note_visit_fn_addr_eq)]
1834    Suggestion {
1835        #[subdiagnostic]
1836        sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>,
1837    },
1838    #[diag(lint_unpredictable_fn_pointer_comparisons)]
1839    #[note(lint_note_duplicated_fn)]
1840    #[note(lint_note_deduplicated_fn)]
1841    #[note(lint_note_visit_fn_addr_eq)]
1842    Warn,
1843}
1844
1845#[derive(Subdiagnostic)]
1846pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> {
1847    #[multipart_suggestion(
1848        lint_fn_addr_eq_suggestion,
1849        style = "verbose",
1850        applicability = "maybe-incorrect"
1851    )]
1852    FnAddrEq {
1853        ne: &'a str,
1854        deref_left: &'a str,
1855        deref_right: &'a str,
1856        #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
1857        left: Span,
1858        #[suggestion_part(code = ", {deref_right}")]
1859        middle: Span,
1860        #[suggestion_part(code = ")")]
1861        right: Span,
1862    },
1863    #[multipart_suggestion(
1864        lint_fn_addr_eq_suggestion,
1865        style = "verbose",
1866        applicability = "maybe-incorrect"
1867    )]
1868    FnAddrEqWithCast {
1869        ne: &'a str,
1870        deref_left: &'a str,
1871        deref_right: &'a str,
1872        fn_sig: rustc_middle::ty::PolyFnSig<'tcx>,
1873        #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
1874        left: Span,
1875        #[suggestion_part(code = ", {deref_right}")]
1876        middle: Span,
1877        #[suggestion_part(code = " as {fn_sig})")]
1878        right: Span,
1879    },
1880}
1881
1882pub(crate) struct ImproperCTypes<'a> {
1883    pub ty: Ty<'a>,
1884    pub desc: &'a str,
1885    pub label: Span,
1886    pub help: Option<DiagMessage>,
1887    pub note: DiagMessage,
1888    pub span_note: Option<Span>,
1889}
1890
1891// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
1892impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
1893    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
1894        diag.primary_message(fluent::lint_improper_ctypes);
1895        diag.arg("ty", self.ty);
1896        diag.arg("desc", self.desc);
1897        diag.span_label(self.label, fluent::lint_label);
1898        if let Some(help) = self.help {
1899            diag.help(help);
1900        }
1901        diag.note(self.note);
1902        if let Some(note) = self.span_note {
1903            diag.span_note(note, fluent::lint_note);
1904        }
1905    }
1906}
1907
1908#[derive(LintDiagnostic)]
1909#[diag(lint_variant_size_differences)]
1910pub(crate) struct VariantSizeDifferencesDiag {
1911    pub largest: u64,
1912}
1913
1914#[derive(LintDiagnostic)]
1915#[diag(lint_atomic_ordering_load)]
1916#[help]
1917pub(crate) struct AtomicOrderingLoad;
1918
1919#[derive(LintDiagnostic)]
1920#[diag(lint_atomic_ordering_store)]
1921#[help]
1922pub(crate) struct AtomicOrderingStore;
1923
1924#[derive(LintDiagnostic)]
1925#[diag(lint_atomic_ordering_fence)]
1926#[help]
1927pub(crate) struct AtomicOrderingFence;
1928
1929#[derive(LintDiagnostic)]
1930#[diag(lint_atomic_ordering_invalid)]
1931#[help]
1932pub(crate) struct InvalidAtomicOrderingDiag {
1933    pub method: Symbol,
1934    #[label]
1935    pub fail_order_arg_span: Span,
1936}
1937
1938// unused.rs
1939#[derive(LintDiagnostic)]
1940#[diag(lint_unused_op)]
1941pub(crate) struct UnusedOp<'a> {
1942    pub op: &'a str,
1943    #[label]
1944    pub label: Span,
1945    #[subdiagnostic]
1946    pub suggestion: UnusedOpSuggestion,
1947}
1948
1949#[derive(Subdiagnostic)]
1950pub(crate) enum UnusedOpSuggestion {
1951    #[suggestion(
1952        lint_suggestion,
1953        style = "verbose",
1954        code = "let _ = ",
1955        applicability = "maybe-incorrect"
1956    )]
1957    NormalExpr {
1958        #[primary_span]
1959        span: Span,
1960    },
1961    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
1962    BlockTailExpr {
1963        #[suggestion_part(code = "let _ = ")]
1964        before_span: Span,
1965        #[suggestion_part(code = ";")]
1966        after_span: Span,
1967    },
1968}
1969
1970#[derive(LintDiagnostic)]
1971#[diag(lint_unused_result)]
1972pub(crate) struct UnusedResult<'a> {
1973    pub ty: Ty<'a>,
1974}
1975
1976// FIXME(davidtwco): this isn't properly translatable because of the
1977// pre/post strings
1978#[derive(LintDiagnostic)]
1979#[diag(lint_unused_closure)]
1980#[note]
1981pub(crate) struct UnusedClosure<'a> {
1982    pub count: usize,
1983    pub pre: &'a str,
1984    pub post: &'a str,
1985}
1986
1987// FIXME(davidtwco): this isn't properly translatable because of the
1988// pre/post strings
1989#[derive(LintDiagnostic)]
1990#[diag(lint_unused_coroutine)]
1991#[note]
1992pub(crate) struct UnusedCoroutine<'a> {
1993    pub count: usize,
1994    pub pre: &'a str,
1995    pub post: &'a str,
1996}
1997
1998// FIXME(davidtwco): this isn't properly translatable because of the pre/post
1999// strings
2000pub(crate) struct UnusedDef<'a, 'b> {
2001    pub pre: &'a str,
2002    pub post: &'a str,
2003    pub cx: &'a LateContext<'b>,
2004    pub def_id: DefId,
2005    pub note: Option<Symbol>,
2006    pub suggestion: Option<UnusedDefSuggestion>,
2007}
2008
2009#[derive(Subdiagnostic)]
2010
2011pub(crate) enum UnusedDefSuggestion {
2012    #[suggestion(
2013        lint_suggestion,
2014        style = "verbose",
2015        code = "let _ = ",
2016        applicability = "maybe-incorrect"
2017    )]
2018    NormalExpr {
2019        #[primary_span]
2020        span: Span,
2021    },
2022    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
2023    BlockTailExpr {
2024        #[suggestion_part(code = "let _ = ")]
2025        before_span: Span,
2026        #[suggestion_part(code = ";")]
2027        after_span: Span,
2028    },
2029}
2030
2031// Needed because of def_path_str
2032impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> {
2033    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2034        diag.primary_message(fluent::lint_unused_def);
2035        diag.arg("pre", self.pre);
2036        diag.arg("post", self.post);
2037        diag.arg("def", self.cx.tcx.def_path_str(self.def_id));
2038        // check for #[must_use = "..."]
2039        if let Some(note) = self.note {
2040            diag.note(note.to_string());
2041        }
2042        if let Some(sugg) = self.suggestion {
2043            diag.subdiagnostic(sugg);
2044        }
2045    }
2046}
2047
2048#[derive(LintDiagnostic)]
2049#[diag(lint_path_statement_drop)]
2050pub(crate) struct PathStatementDrop {
2051    #[subdiagnostic]
2052    pub sub: PathStatementDropSub,
2053}
2054
2055#[derive(Subdiagnostic)]
2056pub(crate) enum PathStatementDropSub {
2057    #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
2058    Suggestion {
2059        #[primary_span]
2060        span: Span,
2061        snippet: String,
2062    },
2063    #[help(lint_help)]
2064    Help {
2065        #[primary_span]
2066        span: Span,
2067    },
2068}
2069
2070#[derive(LintDiagnostic)]
2071#[diag(lint_path_statement_no_effect)]
2072pub(crate) struct PathStatementNoEffect;
2073
2074#[derive(LintDiagnostic)]
2075#[diag(lint_unused_delim)]
2076pub(crate) struct UnusedDelim<'a> {
2077    pub delim: &'static str,
2078    pub item: &'a str,
2079    #[subdiagnostic]
2080    pub suggestion: Option<UnusedDelimSuggestion>,
2081}
2082
2083#[derive(Subdiagnostic)]
2084#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2085pub(crate) struct UnusedDelimSuggestion {
2086    #[suggestion_part(code = "{start_replace}")]
2087    pub start_span: Span,
2088    pub start_replace: &'static str,
2089    #[suggestion_part(code = "{end_replace}")]
2090    pub end_span: Span,
2091    pub end_replace: &'static str,
2092}
2093
2094#[derive(LintDiagnostic)]
2095#[diag(lint_unused_import_braces)]
2096pub(crate) struct UnusedImportBracesDiag {
2097    pub node: Symbol,
2098}
2099
2100#[derive(LintDiagnostic)]
2101#[diag(lint_unused_allocation)]
2102pub(crate) struct UnusedAllocationDiag;
2103
2104#[derive(LintDiagnostic)]
2105#[diag(lint_unused_allocation_mut)]
2106pub(crate) struct UnusedAllocationMutDiag;
2107
2108pub(crate) struct AsyncFnInTraitDiag {
2109    pub sugg: Option<Vec<(Span, String)>>,
2110}
2111
2112impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag {
2113    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2114        diag.primary_message(fluent::lint_async_fn_in_trait);
2115        diag.note(fluent::lint_note);
2116        if let Some(sugg) = self.sugg {
2117            diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect);
2118        }
2119    }
2120}
2121
2122#[derive(LintDiagnostic)]
2123#[diag(lint_unit_bindings)]
2124pub(crate) struct UnitBindingsDiag {
2125    #[label]
2126    pub label: Span,
2127}
2128
2129#[derive(LintDiagnostic)]
2130pub(crate) enum InvalidAsmLabel {
2131    #[diag(lint_invalid_asm_label_named)]
2132    #[help]
2133    #[note]
2134    Named {
2135        #[note(lint_invalid_asm_label_no_span)]
2136        missing_precise_span: bool,
2137    },
2138    #[diag(lint_invalid_asm_label_format_arg)]
2139    #[help]
2140    #[note(lint_note1)]
2141    #[note(lint_note2)]
2142    FormatArg {
2143        #[note(lint_invalid_asm_label_no_span)]
2144        missing_precise_span: bool,
2145    },
2146    #[diag(lint_invalid_asm_label_binary)]
2147    #[help]
2148    #[note(lint_note1)]
2149    #[note(lint_note2)]
2150    Binary {
2151        #[note(lint_invalid_asm_label_no_span)]
2152        missing_precise_span: bool,
2153        // hack to get a label on the whole span, must match the emitted span
2154        #[label]
2155        span: Span,
2156    },
2157}
2158
2159#[derive(Subdiagnostic)]
2160pub(crate) enum UnexpectedCfgCargoHelp {
2161    #[help(lint_unexpected_cfg_add_cargo_feature)]
2162    #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
2163    LintCfg { cargo_toml_lint_cfg: String },
2164    #[help(lint_unexpected_cfg_add_cargo_feature)]
2165    #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
2166    #[help(lint_unexpected_cfg_add_build_rs_println)]
2167    LintCfgAndBuildRs { cargo_toml_lint_cfg: String, build_rs_println: String },
2168}
2169
2170impl UnexpectedCfgCargoHelp {
2171    fn cargo_toml_lint_cfg(unescaped: &str) -> String {
2172        format!(
2173            "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}"
2174        )
2175    }
2176
2177    pub(crate) fn lint_cfg(unescaped: &str) -> Self {
2178        UnexpectedCfgCargoHelp::LintCfg {
2179            cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
2180        }
2181    }
2182
2183    pub(crate) fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self {
2184        UnexpectedCfgCargoHelp::LintCfgAndBuildRs {
2185            cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
2186            build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");"),
2187        }
2188    }
2189}
2190
2191#[derive(Subdiagnostic)]
2192#[help(lint_unexpected_cfg_add_cmdline_arg)]
2193pub(crate) struct UnexpectedCfgRustcHelp {
2194    pub cmdline_arg: String,
2195}
2196
2197impl UnexpectedCfgRustcHelp {
2198    pub(crate) fn new(unescaped: &str) -> Self {
2199        Self { cmdline_arg: format!("--check-cfg={unescaped}") }
2200    }
2201}
2202
2203#[derive(Subdiagnostic)]
2204#[note(lint_unexpected_cfg_from_external_macro_origin)]
2205#[help(lint_unexpected_cfg_from_external_macro_refer)]
2206pub(crate) struct UnexpectedCfgRustcMacroHelp {
2207    pub macro_kind: &'static str,
2208    pub macro_name: Symbol,
2209}
2210
2211#[derive(Subdiagnostic)]
2212#[note(lint_unexpected_cfg_from_external_macro_origin)]
2213#[help(lint_unexpected_cfg_from_external_macro_refer)]
2214#[help(lint_unexpected_cfg_cargo_update)]
2215pub(crate) struct UnexpectedCfgCargoMacroHelp {
2216    pub macro_kind: &'static str,
2217    pub macro_name: Symbol,
2218    pub crate_name: Symbol,
2219}
2220
2221#[derive(LintDiagnostic)]
2222#[diag(lint_unexpected_cfg_name)]
2223pub(crate) struct UnexpectedCfgName {
2224    #[subdiagnostic]
2225    pub code_sugg: unexpected_cfg_name::CodeSuggestion,
2226    #[subdiagnostic]
2227    pub invocation_help: unexpected_cfg_name::InvocationHelp,
2228
2229    pub name: Symbol,
2230}
2231
2232pub(crate) mod unexpected_cfg_name {
2233    use rustc_errors::DiagSymbolList;
2234    use rustc_macros::Subdiagnostic;
2235    use rustc_span::{Ident, Span, Symbol};
2236
2237    #[derive(Subdiagnostic)]
2238    pub(crate) enum CodeSuggestion {
2239        #[help(lint_unexpected_cfg_define_features)]
2240        DefineFeatures,
2241        #[suggestion(
2242            lint_unexpected_cfg_name_similar_name_value,
2243            applicability = "maybe-incorrect",
2244            code = "{code}"
2245        )]
2246        SimilarNameAndValue {
2247            #[primary_span]
2248            span: Span,
2249            code: String,
2250        },
2251        #[suggestion(
2252            lint_unexpected_cfg_name_similar_name_no_value,
2253            applicability = "maybe-incorrect",
2254            code = "{code}"
2255        )]
2256        SimilarNameNoValue {
2257            #[primary_span]
2258            span: Span,
2259            code: String,
2260        },
2261        #[suggestion(
2262            lint_unexpected_cfg_name_similar_name_different_values,
2263            applicability = "maybe-incorrect",
2264            code = "{code}"
2265        )]
2266        SimilarNameDifferentValues {
2267            #[primary_span]
2268            span: Span,
2269            code: String,
2270            #[subdiagnostic]
2271            expected: Option<ExpectedValues>,
2272        },
2273        #[suggestion(
2274            lint_unexpected_cfg_name_similar_name,
2275            applicability = "maybe-incorrect",
2276            code = "{code}"
2277        )]
2278        SimilarName {
2279            #[primary_span]
2280            span: Span,
2281            code: String,
2282            #[subdiagnostic]
2283            expected: Option<ExpectedValues>,
2284        },
2285        SimilarValues {
2286            #[subdiagnostic]
2287            with_similar_values: Vec<FoundWithSimilarValue>,
2288            #[subdiagnostic]
2289            expected_names: Option<ExpectedNames>,
2290        },
2291    }
2292
2293    #[derive(Subdiagnostic)]
2294    #[help(lint_unexpected_cfg_name_expected_values)]
2295    pub(crate) struct ExpectedValues {
2296        pub best_match: Symbol,
2297        pub possibilities: DiagSymbolList,
2298    }
2299
2300    #[derive(Subdiagnostic)]
2301    #[suggestion(
2302        lint_unexpected_cfg_name_with_similar_value,
2303        applicability = "maybe-incorrect",
2304        code = "{code}"
2305    )]
2306    pub(crate) struct FoundWithSimilarValue {
2307        #[primary_span]
2308        pub span: Span,
2309        pub code: String,
2310    }
2311
2312    #[derive(Subdiagnostic)]
2313    #[help_once(lint_unexpected_cfg_name_expected_names)]
2314    pub(crate) struct ExpectedNames {
2315        pub possibilities: DiagSymbolList<Ident>,
2316        pub and_more: usize,
2317    }
2318
2319    #[derive(Subdiagnostic)]
2320    pub(crate) enum InvocationHelp {
2321        #[note(lint_unexpected_cfg_doc_cargo)]
2322        Cargo {
2323            #[subdiagnostic]
2324            macro_help: Option<super::UnexpectedCfgCargoMacroHelp>,
2325            #[subdiagnostic]
2326            help: Option<super::UnexpectedCfgCargoHelp>,
2327        },
2328        #[note(lint_unexpected_cfg_doc_rustc)]
2329        Rustc {
2330            #[subdiagnostic]
2331            macro_help: Option<super::UnexpectedCfgRustcMacroHelp>,
2332            #[subdiagnostic]
2333            help: super::UnexpectedCfgRustcHelp,
2334        },
2335    }
2336}
2337
2338#[derive(LintDiagnostic)]
2339#[diag(lint_unexpected_cfg_value)]
2340pub(crate) struct UnexpectedCfgValue {
2341    #[subdiagnostic]
2342    pub code_sugg: unexpected_cfg_value::CodeSuggestion,
2343    #[subdiagnostic]
2344    pub invocation_help: unexpected_cfg_value::InvocationHelp,
2345
2346    pub has_value: bool,
2347    pub value: String,
2348}
2349
2350pub(crate) mod unexpected_cfg_value {
2351    use rustc_errors::DiagSymbolList;
2352    use rustc_macros::Subdiagnostic;
2353    use rustc_span::{Span, Symbol};
2354
2355    #[derive(Subdiagnostic)]
2356    pub(crate) enum CodeSuggestion {
2357        ChangeValue {
2358            #[subdiagnostic]
2359            expected_values: ExpectedValues,
2360            #[subdiagnostic]
2361            suggestion: Option<ChangeValueSuggestion>,
2362        },
2363        #[note(lint_unexpected_cfg_value_no_expected_value)]
2364        RemoveValue {
2365            #[subdiagnostic]
2366            suggestion: Option<RemoveValueSuggestion>,
2367
2368            name: Symbol,
2369        },
2370        #[note(lint_unexpected_cfg_value_no_expected_values)]
2371        RemoveCondition {
2372            #[subdiagnostic]
2373            suggestion: RemoveConditionSuggestion,
2374
2375            name: Symbol,
2376        },
2377    }
2378
2379    #[derive(Subdiagnostic)]
2380    pub(crate) enum ChangeValueSuggestion {
2381        #[suggestion(
2382            lint_unexpected_cfg_value_similar_name,
2383            code = r#""{best_match}""#,
2384            applicability = "maybe-incorrect"
2385        )]
2386        SimilarName {
2387            #[primary_span]
2388            span: Span,
2389            best_match: Symbol,
2390        },
2391        #[suggestion(
2392            lint_unexpected_cfg_value_specify_value,
2393            code = r#" = "{first_possibility}""#,
2394            applicability = "maybe-incorrect"
2395        )]
2396        SpecifyValue {
2397            #[primary_span]
2398            span: Span,
2399            first_possibility: Symbol,
2400        },
2401    }
2402
2403    #[derive(Subdiagnostic)]
2404    #[suggestion(
2405        lint_unexpected_cfg_value_remove_value,
2406        code = "",
2407        applicability = "maybe-incorrect"
2408    )]
2409    pub(crate) struct RemoveValueSuggestion {
2410        #[primary_span]
2411        pub span: Span,
2412    }
2413
2414    #[derive(Subdiagnostic)]
2415    #[suggestion(
2416        lint_unexpected_cfg_value_remove_condition,
2417        code = "",
2418        applicability = "maybe-incorrect"
2419    )]
2420    pub(crate) struct RemoveConditionSuggestion {
2421        #[primary_span]
2422        pub span: Span,
2423    }
2424
2425    #[derive(Subdiagnostic)]
2426    #[note(lint_unexpected_cfg_value_expected_values)]
2427    pub(crate) struct ExpectedValues {
2428        pub name: Symbol,
2429        pub have_none_possibility: bool,
2430        pub possibilities: DiagSymbolList,
2431        pub and_more: usize,
2432    }
2433
2434    #[derive(Subdiagnostic)]
2435    pub(crate) enum InvocationHelp {
2436        #[note(lint_unexpected_cfg_doc_cargo)]
2437        Cargo {
2438            #[subdiagnostic]
2439            help: Option<CargoHelp>,
2440            #[subdiagnostic]
2441            macro_help: Option<super::UnexpectedCfgCargoMacroHelp>,
2442        },
2443        #[note(lint_unexpected_cfg_doc_rustc)]
2444        Rustc {
2445            #[subdiagnostic]
2446            help: Option<super::UnexpectedCfgRustcHelp>,
2447            #[subdiagnostic]
2448            macro_help: Option<super::UnexpectedCfgRustcMacroHelp>,
2449        },
2450    }
2451
2452    #[derive(Subdiagnostic)]
2453    pub(crate) enum CargoHelp {
2454        #[help(lint_unexpected_cfg_value_add_feature)]
2455        AddFeature {
2456            value: Symbol,
2457        },
2458        #[help(lint_unexpected_cfg_define_features)]
2459        DefineFeatures,
2460        Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp),
2461    }
2462}
2463
2464#[derive(LintDiagnostic)]
2465#[diag(lint_unexpected_builtin_cfg)]
2466#[note(lint_controlled_by)]
2467#[note(lint_incoherent)]
2468pub(crate) struct UnexpectedBuiltinCfg {
2469    pub(crate) cfg: String,
2470    pub(crate) cfg_name: Symbol,
2471    pub(crate) controlled_by: &'static str,
2472}
2473
2474#[derive(LintDiagnostic)]
2475#[diag(lint_macro_use_deprecated)]
2476#[help]
2477pub(crate) struct MacroUseDeprecated;
2478
2479#[derive(LintDiagnostic)]
2480#[diag(lint_unused_macro_use)]
2481pub(crate) struct UnusedMacroUse;
2482
2483#[derive(LintDiagnostic)]
2484#[diag(lint_private_extern_crate_reexport, code = E0365)]
2485pub(crate) struct PrivateExternCrateReexport {
2486    pub ident: Ident,
2487    #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")]
2488    pub sugg: Span,
2489}
2490
2491#[derive(LintDiagnostic)]
2492#[diag(lint_unused_label)]
2493pub(crate) struct UnusedLabel;
2494
2495#[derive(LintDiagnostic)]
2496#[diag(lint_macro_is_private)]
2497pub(crate) struct MacroIsPrivate {
2498    pub ident: Ident,
2499}
2500
2501#[derive(LintDiagnostic)]
2502#[diag(lint_unused_macro_definition)]
2503pub(crate) struct UnusedMacroDefinition {
2504    pub name: Symbol,
2505}
2506
2507#[derive(LintDiagnostic)]
2508#[diag(lint_macro_rule_never_used)]
2509pub(crate) struct MacroRuleNeverUsed {
2510    pub n: usize,
2511    pub name: Symbol,
2512}
2513
2514pub(crate) struct UnstableFeature {
2515    pub msg: DiagMessage,
2516}
2517
2518impl<'a> LintDiagnostic<'a, ()> for UnstableFeature {
2519    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2520        diag.primary_message(self.msg);
2521    }
2522}
2523
2524#[derive(LintDiagnostic)]
2525#[diag(lint_avoid_intel_syntax)]
2526pub(crate) struct AvoidIntelSyntax;
2527
2528#[derive(LintDiagnostic)]
2529#[diag(lint_avoid_att_syntax)]
2530pub(crate) struct AvoidAttSyntax;
2531
2532#[derive(LintDiagnostic)]
2533#[diag(lint_incomplete_include)]
2534pub(crate) struct IncompleteInclude;
2535
2536#[derive(LintDiagnostic)]
2537#[diag(lint_unnameable_test_items)]
2538pub(crate) struct UnnameableTestItems;
2539
2540#[derive(LintDiagnostic)]
2541#[diag(lint_duplicate_macro_attribute)]
2542pub(crate) struct DuplicateMacroAttribute;
2543
2544#[derive(LintDiagnostic)]
2545#[diag(lint_cfg_attr_no_attributes)]
2546pub(crate) struct CfgAttrNoAttributes;
2547
2548#[derive(LintDiagnostic)]
2549#[diag(lint_missing_fragment_specifier)]
2550pub(crate) struct MissingFragmentSpecifier;
2551
2552#[derive(LintDiagnostic)]
2553#[diag(lint_metavariable_still_repeating)]
2554pub(crate) struct MetaVariableStillRepeating {
2555    pub name: MacroRulesNormalizedIdent,
2556}
2557
2558#[derive(LintDiagnostic)]
2559#[diag(lint_metavariable_wrong_operator)]
2560pub(crate) struct MetaVariableWrongOperator;
2561
2562#[derive(LintDiagnostic)]
2563#[diag(lint_duplicate_matcher_binding)]
2564pub(crate) struct DuplicateMatcherBinding;
2565
2566#[derive(LintDiagnostic)]
2567#[diag(lint_unknown_macro_variable)]
2568pub(crate) struct UnknownMacroVariable {
2569    pub name: MacroRulesNormalizedIdent,
2570}
2571
2572#[derive(LintDiagnostic)]
2573#[diag(lint_unused_crate_dependency)]
2574#[help]
2575pub(crate) struct UnusedCrateDependency {
2576    pub extern_crate: Symbol,
2577    pub local_crate: Symbol,
2578}
2579
2580#[derive(LintDiagnostic)]
2581#[diag(lint_ill_formed_attribute_input)]
2582pub(crate) struct IllFormedAttributeInput {
2583    pub num_suggestions: usize,
2584    pub suggestions: DiagArgValue,
2585}
2586
2587#[derive(LintDiagnostic)]
2588pub(crate) enum InnerAttributeUnstable {
2589    #[diag(lint_inner_macro_attribute_unstable)]
2590    InnerMacroAttribute,
2591    #[diag(lint_custom_inner_attribute_unstable)]
2592    CustomInnerAttribute,
2593}
2594
2595#[derive(LintDiagnostic)]
2596#[diag(lint_unknown_diagnostic_attribute)]
2597pub(crate) struct UnknownDiagnosticAttribute {
2598    #[subdiagnostic]
2599    pub typo: Option<UnknownDiagnosticAttributeTypoSugg>,
2600}
2601
2602#[derive(Subdiagnostic)]
2603#[suggestion(
2604    lint_unknown_diagnostic_attribute_typo_sugg,
2605    style = "verbose",
2606    code = "{typo_name}",
2607    applicability = "machine-applicable"
2608)]
2609pub(crate) struct UnknownDiagnosticAttributeTypoSugg {
2610    #[primary_span]
2611    pub span: Span,
2612    pub typo_name: Symbol,
2613}
2614
2615#[derive(LintDiagnostic)]
2616#[diag(lint_unicode_text_flow)]
2617#[note]
2618pub(crate) struct UnicodeTextFlow {
2619    #[label]
2620    pub comment_span: Span,
2621    #[subdiagnostic]
2622    pub characters: Vec<UnicodeCharNoteSub>,
2623    #[subdiagnostic]
2624    pub suggestions: Option<UnicodeTextFlowSuggestion>,
2625
2626    pub num_codepoints: usize,
2627}
2628
2629#[derive(Subdiagnostic)]
2630#[label(lint_label_comment_char)]
2631pub(crate) struct UnicodeCharNoteSub {
2632    #[primary_span]
2633    pub span: Span,
2634    pub c_debug: String,
2635}
2636
2637#[derive(Subdiagnostic)]
2638#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")]
2639pub(crate) struct UnicodeTextFlowSuggestion {
2640    #[suggestion_part(code = "")]
2641    pub spans: Vec<Span>,
2642}
2643
2644#[derive(LintDiagnostic)]
2645#[diag(lint_abs_path_with_module)]
2646pub(crate) struct AbsPathWithModule {
2647    #[subdiagnostic]
2648    pub sugg: AbsPathWithModuleSugg,
2649}
2650
2651#[derive(Subdiagnostic)]
2652#[suggestion(lint_suggestion, code = "{replacement}")]
2653pub(crate) struct AbsPathWithModuleSugg {
2654    #[primary_span]
2655    pub span: Span,
2656    #[applicability]
2657    pub applicability: Applicability,
2658    pub replacement: String,
2659}
2660
2661#[derive(LintDiagnostic)]
2662#[diag(lint_proc_macro_derive_resolution_fallback)]
2663pub(crate) struct ProcMacroDeriveResolutionFallback {
2664    #[label]
2665    pub span: Span,
2666    pub ns: Namespace,
2667    pub ident: Ident,
2668}
2669
2670#[derive(LintDiagnostic)]
2671#[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)]
2672pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths {
2673    #[note]
2674    pub definition: Span,
2675}
2676
2677#[derive(LintDiagnostic)]
2678#[diag(lint_hidden_lifetime_parameters)]
2679pub(crate) struct ElidedLifetimesInPaths {
2680    #[subdiagnostic]
2681    pub subdiag: ElidedLifetimeInPathSubdiag,
2682}
2683
2684pub(crate) struct ElidedNamedLifetime {
2685    pub span: Span,
2686    pub kind: MissingLifetimeKind,
2687    pub name: Symbol,
2688    pub declaration: Option<Span>,
2689}
2690
2691impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime {
2692    fn decorate_lint(self, diag: &mut rustc_errors::Diag<'_, G>) {
2693        let Self { span, kind, name, declaration } = self;
2694        diag.primary_message(fluent::lint_elided_named_lifetime);
2695        diag.arg("name", name);
2696        diag.span_label(span, fluent::lint_label_elided);
2697        if let Some(declaration) = declaration {
2698            diag.span_label(declaration, fluent::lint_label_named);
2699        }
2700        // FIXME(GrigorenkoPV): this `if` and `return` should be removed,
2701        //  but currently this lint's suggestions can conflict with those of `clippy::needless_lifetimes`:
2702        //  https://github.com/rust-lang/rust/pull/129840#issuecomment-2323349119
2703        // HACK: `'static` suggestions will never sonflict, emit only those for now.
2704        if name != kw::StaticLifetime {
2705            return;
2706        }
2707        match kind {
2708            MissingLifetimeKind::Underscore => diag.span_suggestion_verbose(
2709                span,
2710                fluent::lint_suggestion,
2711                format!("{name}"),
2712                Applicability::MachineApplicable,
2713            ),
2714            MissingLifetimeKind::Ampersand => diag.span_suggestion_verbose(
2715                span.shrink_to_hi(),
2716                fluent::lint_suggestion,
2717                format!("{name} "),
2718                Applicability::MachineApplicable,
2719            ),
2720            MissingLifetimeKind::Comma => diag.span_suggestion_verbose(
2721                span.shrink_to_hi(),
2722                fluent::lint_suggestion,
2723                format!("{name}, "),
2724                Applicability::MachineApplicable,
2725            ),
2726            MissingLifetimeKind::Brackets => diag.span_suggestion_verbose(
2727                span.shrink_to_hi(),
2728                fluent::lint_suggestion,
2729                format!("<{name}>"),
2730                Applicability::MachineApplicable,
2731            ),
2732        };
2733    }
2734}
2735
2736#[derive(LintDiagnostic)]
2737#[diag(lint_invalid_crate_type_value)]
2738pub(crate) struct UnknownCrateTypes {
2739    #[subdiagnostic]
2740    pub sugg: Option<UnknownCrateTypesSub>,
2741}
2742
2743#[derive(Subdiagnostic)]
2744#[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")]
2745pub(crate) struct UnknownCrateTypesSub {
2746    #[primary_span]
2747    pub span: Span,
2748    pub candidate: Symbol,
2749}
2750
2751#[derive(LintDiagnostic)]
2752#[diag(lint_unused_imports)]
2753pub(crate) struct UnusedImports {
2754    #[subdiagnostic]
2755    pub sugg: UnusedImportsSugg,
2756    #[help]
2757    pub test_module_span: Option<Span>,
2758
2759    pub span_snippets: DiagArgValue,
2760    pub num_snippets: usize,
2761}
2762
2763#[derive(Subdiagnostic)]
2764pub(crate) enum UnusedImportsSugg {
2765    #[suggestion(
2766        lint_suggestion_remove_whole_use,
2767        applicability = "machine-applicable",
2768        code = "",
2769        style = "tool-only"
2770    )]
2771    RemoveWholeUse {
2772        #[primary_span]
2773        span: Span,
2774    },
2775    #[multipart_suggestion(
2776        lint_suggestion_remove_imports,
2777        applicability = "machine-applicable",
2778        style = "tool-only"
2779    )]
2780    RemoveImports {
2781        #[suggestion_part(code = "")]
2782        remove_spans: Vec<Span>,
2783        num_to_remove: usize,
2784    },
2785}
2786
2787#[derive(LintDiagnostic)]
2788#[diag(lint_redundant_import)]
2789pub(crate) struct RedundantImport {
2790    #[subdiagnostic]
2791    pub subs: Vec<RedundantImportSub>,
2792
2793    pub ident: Ident,
2794}
2795
2796#[derive(Subdiagnostic)]
2797pub(crate) enum RedundantImportSub {
2798    #[label(lint_label_imported_here)]
2799    ImportedHere(#[primary_span] Span),
2800    #[label(lint_label_defined_here)]
2801    DefinedHere(#[primary_span] Span),
2802    #[label(lint_label_imported_prelude)]
2803    ImportedPrelude(#[primary_span] Span),
2804    #[label(lint_label_defined_prelude)]
2805    DefinedPrelude(#[primary_span] Span),
2806}
2807
2808#[derive(LintDiagnostic)]
2809#[diag(lint_unused_doc_comment)]
2810#[help]
2811pub(crate) struct UnusedDocComment {
2812    #[label]
2813    pub span: Span,
2814}
2815
2816#[derive(LintDiagnostic)]
2817pub(crate) enum PatternsInFnsWithoutBody {
2818    #[diag(lint_pattern_in_foreign)]
2819    Foreign {
2820        #[subdiagnostic]
2821        sub: PatternsInFnsWithoutBodySub,
2822    },
2823    #[diag(lint_pattern_in_bodiless)]
2824    Bodiless {
2825        #[subdiagnostic]
2826        sub: PatternsInFnsWithoutBodySub,
2827    },
2828}
2829
2830#[derive(Subdiagnostic)]
2831#[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")]
2832pub(crate) struct PatternsInFnsWithoutBodySub {
2833    #[primary_span]
2834    pub span: Span,
2835
2836    pub ident: Ident,
2837}
2838
2839#[derive(LintDiagnostic)]
2840#[diag(lint_extern_without_abi)]
2841pub(crate) struct MissingAbi {
2842    #[suggestion(code = "extern {default_abi}", applicability = "machine-applicable")]
2843    pub span: Span,
2844    pub default_abi: ExternAbi,
2845}
2846
2847#[derive(LintDiagnostic)]
2848#[diag(lint_legacy_derive_helpers)]
2849pub(crate) struct LegacyDeriveHelpers {
2850    #[label]
2851    pub span: Span,
2852}
2853
2854#[derive(LintDiagnostic)]
2855#[diag(lint_or_patterns_back_compat)]
2856pub(crate) struct OrPatternsBackCompat {
2857    #[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
2858    pub span: Span,
2859    pub suggestion: String,
2860}
2861
2862#[derive(LintDiagnostic)]
2863#[diag(lint_reserved_prefix)]
2864pub(crate) struct ReservedPrefix {
2865    #[label]
2866    pub label: Span,
2867    #[suggestion(code = " ", applicability = "machine-applicable")]
2868    pub suggestion: Span,
2869
2870    pub prefix: String,
2871}
2872
2873#[derive(LintDiagnostic)]
2874#[diag(lint_raw_prefix)]
2875pub(crate) struct RawPrefix {
2876    #[label]
2877    pub label: Span,
2878    #[suggestion(code = " ", applicability = "machine-applicable")]
2879    pub suggestion: Span,
2880}
2881
2882#[derive(LintDiagnostic)]
2883#[diag(lint_unused_builtin_attribute)]
2884pub(crate) struct UnusedBuiltinAttribute {
2885    #[note]
2886    pub invoc_span: Span,
2887
2888    pub attr_name: Symbol,
2889    pub macro_name: String,
2890}
2891
2892#[derive(LintDiagnostic)]
2893#[diag(lint_trailing_semi_macro)]
2894pub(crate) struct TrailingMacro {
2895    #[note(lint_note1)]
2896    #[note(lint_note2)]
2897    pub is_trailing: bool,
2898
2899    pub name: Ident,
2900}
2901
2902#[derive(LintDiagnostic)]
2903#[diag(lint_break_with_label_and_loop)]
2904pub(crate) struct BreakWithLabelAndLoop {
2905    #[subdiagnostic]
2906    pub sub: BreakWithLabelAndLoopSub,
2907}
2908
2909#[derive(Subdiagnostic)]
2910#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2911pub(crate) struct BreakWithLabelAndLoopSub {
2912    #[suggestion_part(code = "(")]
2913    pub left: Span,
2914    #[suggestion_part(code = ")")]
2915    pub right: Span,
2916}
2917
2918#[derive(LintDiagnostic)]
2919#[diag(lint_deprecated_where_clause_location)]
2920#[note]
2921pub(crate) struct DeprecatedWhereClauseLocation {
2922    #[subdiagnostic]
2923    pub suggestion: DeprecatedWhereClauseLocationSugg,
2924}
2925
2926#[derive(Subdiagnostic)]
2927pub(crate) enum DeprecatedWhereClauseLocationSugg {
2928    #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")]
2929    MoveToEnd {
2930        #[suggestion_part(code = "")]
2931        left: Span,
2932        #[suggestion_part(code = "{sugg}")]
2933        right: Span,
2934
2935        sugg: String,
2936    },
2937    #[suggestion(lint_suggestion_remove_where, code = "", applicability = "machine-applicable")]
2938    RemoveWhere {
2939        #[primary_span]
2940        span: Span,
2941    },
2942}
2943
2944#[derive(LintDiagnostic)]
2945#[diag(lint_missing_unsafe_on_extern)]
2946pub(crate) struct MissingUnsafeOnExtern {
2947    #[suggestion(code = "unsafe ", applicability = "machine-applicable")]
2948    pub suggestion: Span,
2949}
2950
2951#[derive(LintDiagnostic)]
2952#[diag(lint_single_use_lifetime)]
2953pub(crate) struct SingleUseLifetime {
2954    #[label(lint_label_param)]
2955    pub param_span: Span,
2956    #[label(lint_label_use)]
2957    pub use_span: Span,
2958    #[subdiagnostic]
2959    pub suggestion: Option<SingleUseLifetimeSugg>,
2960
2961    pub ident: Ident,
2962}
2963
2964#[derive(Subdiagnostic)]
2965#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
2966pub(crate) struct SingleUseLifetimeSugg {
2967    #[suggestion_part(code = "")]
2968    pub deletion_span: Option<Span>,
2969    #[suggestion_part(code = "{replace_lt}")]
2970    pub use_span: Span,
2971
2972    pub replace_lt: String,
2973}
2974
2975#[derive(LintDiagnostic)]
2976#[diag(lint_unused_lifetime)]
2977pub(crate) struct UnusedLifetime {
2978    #[suggestion(code = "", applicability = "machine-applicable")]
2979    pub deletion_span: Option<Span>,
2980
2981    pub ident: Ident,
2982}
2983
2984#[derive(LintDiagnostic)]
2985#[diag(lint_named_argument_used_positionally)]
2986pub(crate) struct NamedArgumentUsedPositionally {
2987    #[label(lint_label_named_arg)]
2988    pub named_arg_sp: Span,
2989    #[label(lint_label_position_arg)]
2990    pub position_label_sp: Option<Span>,
2991    #[suggestion(style = "verbose", code = "{name}", applicability = "maybe-incorrect")]
2992    pub suggestion: Option<Span>,
2993
2994    pub name: String,
2995    pub named_arg_name: String,
2996}
2997
2998#[derive(LintDiagnostic)]
2999#[diag(lint_byte_slice_in_packed_struct_with_derive)]
3000#[help]
3001pub(crate) struct ByteSliceInPackedStructWithDerive {
3002    // FIXME: make this translatable
3003    pub ty: String,
3004}
3005
3006#[derive(LintDiagnostic)]
3007#[diag(lint_unused_extern_crate)]
3008pub(crate) struct UnusedExternCrate {
3009    #[suggestion(code = "", applicability = "machine-applicable")]
3010    pub removal_span: Span,
3011}
3012
3013#[derive(LintDiagnostic)]
3014#[diag(lint_extern_crate_not_idiomatic)]
3015pub(crate) struct ExternCrateNotIdiomatic {
3016    #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")]
3017    pub span: Span,
3018
3019    pub code: &'static str,
3020}
3021
3022// FIXME: make this translatable
3023pub(crate) struct AmbiguousGlobImports {
3024    pub ambiguity: AmbiguityErrorDiag,
3025}
3026
3027impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports {
3028    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
3029        diag.primary_message(self.ambiguity.msg.clone());
3030        rustc_errors::report_ambiguity_error(diag, self.ambiguity);
3031    }
3032}
3033
3034#[derive(LintDiagnostic)]
3035#[diag(lint_ambiguous_glob_reexport)]
3036pub(crate) struct AmbiguousGlobReexports {
3037    #[label(lint_label_first_reexport)]
3038    pub first_reexport: Span,
3039    #[label(lint_label_duplicate_reexport)]
3040    pub duplicate_reexport: Span,
3041
3042    pub name: String,
3043    // FIXME: make this translatable
3044    pub namespace: String,
3045}
3046
3047#[derive(LintDiagnostic)]
3048#[diag(lint_hidden_glob_reexport)]
3049pub(crate) struct HiddenGlobReexports {
3050    #[note(lint_note_glob_reexport)]
3051    pub glob_reexport: Span,
3052    #[note(lint_note_private_item)]
3053    pub private_item: Span,
3054
3055    pub name: String,
3056    // FIXME: make this translatable
3057    pub namespace: String,
3058}
3059
3060#[derive(LintDiagnostic)]
3061#[diag(lint_unnecessary_qualification)]
3062pub(crate) struct UnusedQualifications {
3063    #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
3064    pub removal_span: Span,
3065}
3066
3067#[derive(LintDiagnostic)]
3068#[diag(lint_associated_const_elided_lifetime)]
3069pub(crate) struct AssociatedConstElidedLifetime {
3070    #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")]
3071    pub span: Span,
3072
3073    pub code: &'static str,
3074    pub elided: bool,
3075    #[note]
3076    pub lifetimes_in_scope: MultiSpan,
3077}
3078
3079#[derive(LintDiagnostic)]
3080#[diag(lint_redundant_import_visibility)]
3081pub(crate) struct RedundantImportVisibility {
3082    #[note]
3083    pub span: Span,
3084    #[help]
3085    pub help: (),
3086
3087    pub import_vis: String,
3088    pub max_vis: String,
3089}
3090
3091#[derive(LintDiagnostic)]
3092#[diag(lint_unsafe_attr_outside_unsafe)]
3093pub(crate) struct UnsafeAttrOutsideUnsafe {
3094    #[label]
3095    pub span: Span,
3096    #[subdiagnostic]
3097    pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
3098}
3099
3100#[derive(Subdiagnostic)]
3101#[multipart_suggestion(
3102    lint_unsafe_attr_outside_unsafe_suggestion,
3103    applicability = "machine-applicable"
3104)]
3105pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
3106    #[suggestion_part(code = "unsafe(")]
3107    pub left: Span,
3108    #[suggestion_part(code = ")")]
3109    pub right: Span,
3110}
3111
3112#[derive(LintDiagnostic)]
3113#[diag(lint_out_of_scope_macro_calls)]
3114#[help]
3115pub(crate) struct OutOfScopeMacroCalls {
3116    #[label]
3117    pub span: Span,
3118    pub path: String,
3119    pub location: String,
3120}
3121
3122#[derive(LintDiagnostic)]
3123#[diag(lint_static_mut_refs_lint)]
3124pub(crate) struct RefOfMutStatic<'a> {
3125    #[label]
3126    pub span: Span,
3127    #[subdiagnostic]
3128    pub sugg: Option<MutRefSugg>,
3129    pub shared_label: &'a str,
3130    #[note(lint_shared_note)]
3131    pub shared_note: bool,
3132    #[note(lint_mut_note)]
3133    pub mut_note: bool,
3134}
3135
3136#[derive(Subdiagnostic)]
3137pub(crate) enum MutRefSugg {
3138    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
3139    Shared {
3140        #[suggestion_part(code = "&raw const ")]
3141        span: Span,
3142    },
3143    #[multipart_suggestion(
3144        lint_suggestion_mut,
3145        style = "verbose",
3146        applicability = "maybe-incorrect"
3147    )]
3148    Mut {
3149        #[suggestion_part(code = "&raw mut ")]
3150        span: Span,
3151    },
3152}
3153
3154#[derive(LintDiagnostic)]
3155#[diag(lint_unqualified_local_imports)]
3156pub(crate) struct UnqualifiedLocalImportsDiag {}
3157
3158#[derive(LintDiagnostic)]
3159#[diag(lint_reserved_string)]
3160pub(crate) struct ReservedString {
3161    #[suggestion(code = " ", applicability = "machine-applicable")]
3162    pub suggestion: Span,
3163}
3164
3165#[derive(LintDiagnostic)]
3166#[diag(lint_reserved_multihash)]
3167pub(crate) struct ReservedMultihash {
3168    #[suggestion(code = " ", applicability = "machine-applicable")]
3169    pub suggestion: Span,
3170}