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