rustc_lint/
lints.rs

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