]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/lints.rs
Rollup merge of #107706 - tgross35:atomic-as-mut-ptr, r=m-ou-se
[rust.git] / compiler / rustc_lint / src / lints.rs
1 #![allow(rustc::untranslatable_diagnostic)]
2 #![allow(rustc::diagnostic_outside_of_impl)]
3 use std::num::NonZeroU32;
4
5 use rustc_errors::{
6     fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage,
7     DiagnosticStyledString, SuggestionStyle,
8 };
9 use rustc_hir::def_id::DefId;
10 use rustc_macros::{LintDiagnostic, Subdiagnostic};
11 use rustc_middle::ty::{Predicate, Ty, TyCtxt};
12 use rustc_session::parse::ParseSess;
13 use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
14
15 use crate::{
16     builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext,
17 };
18
19 // array_into_iter.rs
20 #[derive(LintDiagnostic)]
21 #[diag(lint_array_into_iter)]
22 pub struct ArrayIntoIterDiag<'a> {
23     pub target: &'a str,
24     #[suggestion(use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
25     pub suggestion: Span,
26     #[subdiagnostic]
27     pub sub: Option<ArrayIntoIterDiagSub>,
28 }
29
30 #[derive(Subdiagnostic)]
31 pub enum ArrayIntoIterDiagSub {
32     #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
33     RemoveIntoIter {
34         #[primary_span]
35         span: Span,
36     },
37     #[multipart_suggestion(use_explicit_into_iter_suggestion, applicability = "maybe-incorrect")]
38     UseExplicitIntoIter {
39         #[suggestion_part(code = "IntoIterator::into_iter(")]
40         start_span: Span,
41         #[suggestion_part(code = ")")]
42         end_span: Span,
43     },
44 }
45
46 // builtin.rs
47 #[derive(LintDiagnostic)]
48 #[diag(lint_builtin_while_true)]
49 pub struct BuiltinWhileTrue {
50     #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")]
51     pub suggestion: Span,
52     pub replace: String,
53 }
54
55 #[derive(LintDiagnostic)]
56 #[diag(lint_builtin_box_pointers)]
57 pub struct BuiltinBoxPointers<'a> {
58     pub ty: Ty<'a>,
59 }
60
61 #[derive(LintDiagnostic)]
62 #[diag(lint_builtin_non_shorthand_field_patterns)]
63 pub struct BuiltinNonShorthandFieldPatterns {
64     pub ident: Ident,
65     #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")]
66     pub suggestion: Span,
67     pub prefix: &'static str,
68 }
69
70 #[derive(LintDiagnostic)]
71 pub enum BuiltinUnsafe {
72     #[diag(lint_builtin_allow_internal_unsafe)]
73     AllowInternalUnsafe,
74     #[diag(lint_builtin_unsafe_block)]
75     UnsafeBlock,
76     #[diag(lint_builtin_unsafe_trait)]
77     UnsafeTrait,
78     #[diag(lint_builtin_unsafe_impl)]
79     UnsafeImpl,
80     #[diag(lint_builtin_no_mangle_fn)]
81     #[note(lint_builtin_overridden_symbol_name)]
82     NoMangleFn,
83     #[diag(lint_builtin_export_name_fn)]
84     #[note(lint_builtin_overridden_symbol_name)]
85     ExportNameFn,
86     #[diag(lint_builtin_link_section_fn)]
87     #[note(lint_builtin_overridden_symbol_section)]
88     LinkSectionFn,
89     #[diag(lint_builtin_no_mangle_static)]
90     #[note(lint_builtin_overridden_symbol_name)]
91     NoMangleStatic,
92     #[diag(lint_builtin_export_name_static)]
93     #[note(lint_builtin_overridden_symbol_name)]
94     ExportNameStatic,
95     #[diag(lint_builtin_link_section_static)]
96     #[note(lint_builtin_overridden_symbol_section)]
97     LinkSectionStatic,
98     #[diag(lint_builtin_no_mangle_method)]
99     #[note(lint_builtin_overridden_symbol_name)]
100     NoMangleMethod,
101     #[diag(lint_builtin_export_name_method)]
102     #[note(lint_builtin_overridden_symbol_name)]
103     ExportNameMethod,
104     #[diag(lint_builtin_decl_unsafe_fn)]
105     DeclUnsafeFn,
106     #[diag(lint_builtin_decl_unsafe_method)]
107     DeclUnsafeMethod,
108     #[diag(lint_builtin_impl_unsafe_method)]
109     ImplUnsafeMethod,
110 }
111
112 #[derive(LintDiagnostic)]
113 #[diag(lint_builtin_missing_doc)]
114 pub struct BuiltinMissingDoc<'a> {
115     pub article: &'a str,
116     pub desc: &'a str,
117 }
118
119 #[derive(LintDiagnostic)]
120 #[diag(lint_builtin_missing_copy_impl)]
121 pub struct BuiltinMissingCopyImpl;
122
123 pub struct BuiltinMissingDebugImpl<'a> {
124     pub tcx: TyCtxt<'a>,
125     pub def_id: DefId,
126 }
127
128 // Needed for def_path_str
129 impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> {
130     fn decorate_lint<'b>(
131         self,
132         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
133     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
134         diag.set_arg("debug", self.tcx.def_path_str(self.def_id));
135         diag
136     }
137
138     fn msg(&self) -> DiagnosticMessage {
139         fluent::lint_builtin_missing_debug_impl
140     }
141 }
142
143 #[derive(LintDiagnostic)]
144 #[diag(lint_builtin_anonymous_params)]
145 pub struct BuiltinAnonymousParams<'a> {
146     #[suggestion(code = "_: {ty_snip}")]
147     pub suggestion: (Span, Applicability),
148     pub ty_snip: &'a str,
149 }
150
151 // FIXME(davidtwco) translatable deprecated attr
152 #[derive(LintDiagnostic)]
153 #[diag(lint_builtin_deprecated_attr_link)]
154 pub struct BuiltinDeprecatedAttrLink<'a> {
155     pub name: Symbol,
156     pub reason: &'a str,
157     pub link: &'a str,
158     #[subdiagnostic]
159     pub suggestion: BuiltinDeprecatedAttrLinkSuggestion<'a>,
160 }
161
162 #[derive(Subdiagnostic)]
163 pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> {
164     #[suggestion(msg_suggestion, code = "", applicability = "machine-applicable")]
165     Msg {
166         #[primary_span]
167         suggestion: Span,
168         msg: &'a str,
169     },
170     #[suggestion(default_suggestion, code = "", applicability = "machine-applicable")]
171     Default {
172         #[primary_span]
173         suggestion: Span,
174     },
175 }
176
177 #[derive(LintDiagnostic)]
178 #[diag(lint_builtin_deprecated_attr_used)]
179 pub struct BuiltinDeprecatedAttrUsed {
180     pub name: String,
181     #[suggestion(
182         lint_builtin_deprecated_attr_default_suggestion,
183         style = "short",
184         code = "",
185         applicability = "machine-applicable"
186     )]
187     pub suggestion: Span,
188 }
189
190 #[derive(LintDiagnostic)]
191 #[diag(lint_builtin_unused_doc_comment)]
192 pub struct BuiltinUnusedDocComment<'a> {
193     pub kind: &'a str,
194     #[label]
195     pub label: Span,
196     #[subdiagnostic]
197     pub sub: BuiltinUnusedDocCommentSub,
198 }
199
200 #[derive(Subdiagnostic)]
201 pub enum BuiltinUnusedDocCommentSub {
202     #[help(plain_help)]
203     PlainHelp,
204     #[help(block_help)]
205     BlockHelp,
206 }
207
208 #[derive(LintDiagnostic)]
209 #[diag(lint_builtin_no_mangle_generic)]
210 pub struct BuiltinNoMangleGeneric {
211     // Use of `#[no_mangle]` suggests FFI intent; correct
212     // fix may be to monomorphize source by hand
213     #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")]
214     pub suggestion: Span,
215 }
216
217 #[derive(LintDiagnostic)]
218 #[diag(lint_builtin_const_no_mangle)]
219 pub struct BuiltinConstNoMangle {
220     #[suggestion(code = "pub static", applicability = "machine-applicable")]
221     pub suggestion: Span,
222 }
223
224 #[derive(LintDiagnostic)]
225 #[diag(lint_builtin_mutable_transmutes)]
226 pub struct BuiltinMutablesTransmutes;
227
228 #[derive(LintDiagnostic)]
229 #[diag(lint_builtin_unstable_features)]
230 pub struct BuiltinUnstableFeatures;
231
232 // lint_ungated_async_fn_track_caller
233 pub struct BuiltinUngatedAsyncFnTrackCaller<'a> {
234     pub label: Span,
235     pub parse_sess: &'a ParseSess,
236 }
237
238 impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
239     fn decorate_lint<'b>(
240         self,
241         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
242     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
243         diag.span_label(self.label, fluent::label);
244         rustc_session::parse::add_feature_diagnostics(
245             diag,
246             &self.parse_sess,
247             sym::closure_track_caller,
248         );
249         diag
250     }
251
252     fn msg(&self) -> DiagnosticMessage {
253         fluent::lint_ungated_async_fn_track_caller
254     }
255 }
256
257 #[derive(LintDiagnostic)]
258 #[diag(lint_builtin_unreachable_pub)]
259 pub struct BuiltinUnreachablePub<'a> {
260     pub what: &'a str,
261     #[suggestion(code = "pub(crate)")]
262     pub suggestion: (Span, Applicability),
263     #[help]
264     pub help: Option<()>,
265 }
266
267 pub struct SuggestChangingAssocTypes<'a, 'b> {
268     pub ty: &'a rustc_hir::Ty<'b>,
269 }
270
271 impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> {
272     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
273     where
274         F: Fn(
275             &mut rustc_errors::Diagnostic,
276             rustc_errors::SubdiagnosticMessage,
277         ) -> rustc_errors::SubdiagnosticMessage,
278     {
279         // Access to associates types should use `<T as Bound>::Assoc`, which does not need a
280         // bound. Let's see if this type does that.
281
282         // We use a HIR visitor to walk the type.
283         use rustc_hir::intravisit::{self, Visitor};
284         struct WalkAssocTypes<'a> {
285             err: &'a mut rustc_errors::Diagnostic,
286         }
287         impl Visitor<'_> for WalkAssocTypes<'_> {
288             fn visit_qpath(
289                 &mut self,
290                 qpath: &rustc_hir::QPath<'_>,
291                 id: rustc_hir::HirId,
292                 span: Span,
293             ) {
294                 if TypeAliasBounds::is_type_variable_assoc(qpath) {
295                     self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help);
296                 }
297                 intravisit::walk_qpath(self, qpath, id)
298             }
299         }
300
301         // Let's go for a walk!
302         let mut visitor = WalkAssocTypes { err: diag };
303         visitor.visit_ty(self.ty);
304     }
305 }
306
307 #[derive(LintDiagnostic)]
308 #[diag(lint_builtin_type_alias_where_clause)]
309 pub struct BuiltinTypeAliasWhereClause<'a, 'b> {
310     #[suggestion(code = "", applicability = "machine-applicable")]
311     pub suggestion: Span,
312     #[subdiagnostic]
313     pub sub: Option<SuggestChangingAssocTypes<'a, 'b>>,
314 }
315
316 #[derive(LintDiagnostic)]
317 #[diag(lint_builtin_type_alias_generic_bounds)]
318 pub struct BuiltinTypeAliasGenericBounds<'a, 'b> {
319     #[subdiagnostic]
320     pub suggestion: BuiltinTypeAliasGenericBoundsSuggestion,
321     #[subdiagnostic]
322     pub sub: Option<SuggestChangingAssocTypes<'a, 'b>>,
323 }
324
325 pub struct BuiltinTypeAliasGenericBoundsSuggestion {
326     pub suggestions: Vec<(Span, String)>,
327 }
328
329 impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
330     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
331     where
332         F: Fn(
333             &mut rustc_errors::Diagnostic,
334             rustc_errors::SubdiagnosticMessage,
335         ) -> rustc_errors::SubdiagnosticMessage,
336     {
337         diag.multipart_suggestion(
338             fluent::suggestion,
339             self.suggestions,
340             Applicability::MachineApplicable,
341         );
342     }
343 }
344
345 #[derive(LintDiagnostic)]
346 #[diag(lint_builtin_trivial_bounds)]
347 pub struct BuiltinTrivialBounds<'a> {
348     pub predicate_kind_name: &'a str,
349     pub predicate: Predicate<'a>,
350 }
351
352 #[derive(LintDiagnostic)]
353 pub enum BuiltinEllipsisInclusiveRangePatternsLint {
354     #[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
355     Parenthesise {
356         #[suggestion(code = "{replace}", applicability = "machine-applicable")]
357         suggestion: Span,
358         replace: String,
359     },
360     #[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
361     NonParenthesise {
362         #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")]
363         suggestion: Span,
364     },
365 }
366
367 #[derive(LintDiagnostic)]
368 #[diag(lint_builtin_unnameable_test_items)]
369 pub struct BuiltinUnnameableTestItems;
370
371 #[derive(LintDiagnostic)]
372 #[diag(lint_builtin_keyword_idents)]
373 pub struct BuiltinKeywordIdents {
374     pub kw: Ident,
375     pub next: Edition,
376     #[suggestion(code = "r#{kw}", applicability = "machine-applicable")]
377     pub suggestion: Span,
378 }
379
380 #[derive(LintDiagnostic)]
381 #[diag(lint_builtin_explicit_outlives)]
382 pub struct BuiltinExplicitOutlives {
383     pub count: usize,
384     #[subdiagnostic]
385     pub suggestion: BuiltinExplicitOutlivesSuggestion,
386 }
387
388 #[derive(Subdiagnostic)]
389 #[multipart_suggestion(suggestion)]
390 pub struct BuiltinExplicitOutlivesSuggestion {
391     #[suggestion_part(code = "")]
392     pub spans: Vec<Span>,
393     #[applicability]
394     pub applicability: Applicability,
395 }
396
397 #[derive(LintDiagnostic)]
398 #[diag(lint_builtin_incomplete_features)]
399 pub struct BuiltinIncompleteFeatures {
400     pub name: Symbol,
401     #[subdiagnostic]
402     pub note: Option<BuiltinIncompleteFeaturesNote>,
403     #[subdiagnostic]
404     pub help: Option<BuiltinIncompleteFeaturesHelp>,
405 }
406
407 #[derive(Subdiagnostic)]
408 #[help(help)]
409 pub struct BuiltinIncompleteFeaturesHelp;
410
411 #[derive(Subdiagnostic)]
412 #[note(note)]
413 pub struct BuiltinIncompleteFeaturesNote {
414     pub n: NonZeroU32,
415 }
416
417 pub struct BuiltinUnpermittedTypeInit<'a> {
418     pub msg: DiagnosticMessage,
419     pub ty: Ty<'a>,
420     pub label: Span,
421     pub sub: BuiltinUnpermittedTypeInitSub,
422 }
423
424 impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
425     fn decorate_lint<'b>(
426         self,
427         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
428     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
429         diag.set_arg("ty", self.ty);
430         diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label);
431         diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label_suggestion);
432         self.sub.add_to_diagnostic(diag);
433         diag
434     }
435
436     fn msg(&self) -> rustc_errors::DiagnosticMessage {
437         self.msg.clone()
438     }
439 }
440
441 // FIXME(davidtwco): make translatable
442 pub struct BuiltinUnpermittedTypeInitSub {
443     pub err: InitError,
444 }
445
446 impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub {
447     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
448     where
449         F: Fn(
450             &mut rustc_errors::Diagnostic,
451             rustc_errors::SubdiagnosticMessage,
452         ) -> rustc_errors::SubdiagnosticMessage,
453     {
454         let mut err = self.err;
455         loop {
456             if let Some(span) = err.span {
457                 diag.span_note(span, err.message);
458             } else {
459                 diag.note(err.message);
460             }
461             if let Some(e) = err.nested {
462                 err = *e;
463             } else {
464                 break;
465             }
466         }
467     }
468 }
469
470 #[derive(LintDiagnostic)]
471 pub enum BuiltinClashingExtern<'a> {
472     #[diag(lint_builtin_clashing_extern_same_name)]
473     SameName {
474         this: Symbol,
475         orig: Symbol,
476         #[label(previous_decl_label)]
477         previous_decl_label: Span,
478         #[label(mismatch_label)]
479         mismatch_label: Span,
480         #[subdiagnostic]
481         sub: BuiltinClashingExternSub<'a>,
482     },
483     #[diag(lint_builtin_clashing_extern_diff_name)]
484     DiffName {
485         this: Symbol,
486         orig: Symbol,
487         #[label(previous_decl_label)]
488         previous_decl_label: Span,
489         #[label(mismatch_label)]
490         mismatch_label: Span,
491         #[subdiagnostic]
492         sub: BuiltinClashingExternSub<'a>,
493     },
494 }
495
496 // FIXME(davidtwco): translatable expected/found
497 pub struct BuiltinClashingExternSub<'a> {
498     pub tcx: TyCtxt<'a>,
499     pub expected: Ty<'a>,
500     pub found: Ty<'a>,
501 }
502
503 impl AddToDiagnostic for BuiltinClashingExternSub<'_> {
504     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
505     where
506         F: Fn(
507             &mut rustc_errors::Diagnostic,
508             rustc_errors::SubdiagnosticMessage,
509         ) -> rustc_errors::SubdiagnosticMessage,
510     {
511         let mut expected_str = DiagnosticStyledString::new();
512         expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
513         let mut found_str = DiagnosticStyledString::new();
514         found_str.push(self.found.fn_sig(self.tcx).to_string(), true);
515         diag.note_expected_found(&"", expected_str, &"", found_str);
516     }
517 }
518
519 #[derive(LintDiagnostic)]
520 #[diag(lint_builtin_deref_nullptr)]
521 pub struct BuiltinDerefNullptr {
522     #[label]
523     pub label: Span,
524 }
525
526 // FIXME: migrate fluent::lint::builtin_asm_labels
527
528 #[derive(LintDiagnostic)]
529 pub enum BuiltinSpecialModuleNameUsed {
530     #[diag(lint_builtin_special_module_name_used_lib)]
531     #[note]
532     #[help]
533     Lib,
534     #[diag(lint_builtin_special_module_name_used_main)]
535     #[note]
536     Main,
537 }
538
539 #[derive(LintDiagnostic)]
540 #[diag(lint_builtin_unexpected_cli_config_name)]
541 #[help]
542 pub struct BuiltinUnexpectedCliConfigName {
543     pub name: Symbol,
544 }
545
546 #[derive(LintDiagnostic)]
547 #[diag(lint_builtin_unexpected_cli_config_value)]
548 #[help]
549 pub struct BuiltinUnexpectedCliConfigValue {
550     pub name: Symbol,
551     pub value: Symbol,
552 }
553
554 // deref_into_dyn_supertrait.rs
555 #[derive(LintDiagnostic)]
556 #[diag(lint_supertrait_as_deref_target)]
557 pub struct SupertraitAsDerefTarget<'a> {
558     pub t: Ty<'a>,
559     pub target_principal: String,
560     // pub target_principal: Binder<'a, ExistentialTraitRef<'b>>,
561     #[subdiagnostic]
562     pub label: Option<SupertraitAsDerefTargetLabel>,
563 }
564
565 #[derive(Subdiagnostic)]
566 #[label(label)]
567 pub struct SupertraitAsDerefTargetLabel {
568     #[primary_span]
569     pub label: Span,
570 }
571
572 // enum_intrinsics_non_enums.rs
573 #[derive(LintDiagnostic)]
574 #[diag(lint_enum_intrinsics_mem_discriminant)]
575 pub struct EnumIntrinsicsMemDiscriminate<'a> {
576     pub ty_param: Ty<'a>,
577     #[note]
578     pub note: Span,
579 }
580
581 #[derive(LintDiagnostic)]
582 #[diag(lint_enum_intrinsics_mem_variant)]
583 #[note]
584 pub struct EnumIntrinsicsMemVariant<'a> {
585     pub ty_param: Ty<'a>,
586 }
587
588 // expect.rs
589 #[derive(LintDiagnostic)]
590 #[diag(lint_expectation)]
591 pub struct Expectation {
592     #[subdiagnostic]
593     pub rationale: Option<ExpectationNote>,
594     #[note]
595     pub note: Option<()>,
596 }
597
598 #[derive(Subdiagnostic)]
599 #[note(rationale)]
600 pub struct ExpectationNote {
601     pub rationale: Symbol,
602 }
603
604 // for_loops_over_fallibles.rs
605 #[derive(LintDiagnostic)]
606 #[diag(lint_for_loops_over_fallibles)]
607 pub struct ForLoopsOverFalliblesDiag<'a> {
608     pub article: &'static str,
609     pub ty: &'static str,
610     #[subdiagnostic]
611     pub sub: ForLoopsOverFalliblesLoopSub<'a>,
612     #[subdiagnostic]
613     pub question_mark: Option<ForLoopsOverFalliblesQuestionMark>,
614     #[subdiagnostic]
615     pub suggestion: ForLoopsOverFalliblesSuggestion<'a>,
616 }
617
618 #[derive(Subdiagnostic)]
619 pub enum ForLoopsOverFalliblesLoopSub<'a> {
620     #[suggestion(remove_next, code = ".by_ref()", applicability = "maybe-incorrect")]
621     RemoveNext {
622         #[primary_span]
623         suggestion: Span,
624         recv_snip: String,
625     },
626     #[multipart_suggestion(use_while_let, applicability = "maybe-incorrect")]
627     UseWhileLet {
628         #[suggestion_part(code = "while let {var}(")]
629         start_span: Span,
630         #[suggestion_part(code = ") = ")]
631         end_span: Span,
632         var: &'a str,
633     },
634 }
635
636 #[derive(Subdiagnostic)]
637 #[suggestion(use_question_mark, code = "?", applicability = "maybe-incorrect")]
638 pub struct ForLoopsOverFalliblesQuestionMark {
639     #[primary_span]
640     pub suggestion: Span,
641 }
642
643 #[derive(Subdiagnostic)]
644 #[multipart_suggestion(suggestion, applicability = "maybe-incorrect")]
645 pub struct ForLoopsOverFalliblesSuggestion<'a> {
646     pub var: &'a str,
647     #[suggestion_part(code = "if let {var}(")]
648     pub start_span: Span,
649     #[suggestion_part(code = ") = ")]
650     pub end_span: Span,
651 }
652
653 // hidden_unicode_codepoints.rs
654 #[derive(LintDiagnostic)]
655 #[diag(lint_hidden_unicode_codepoints)]
656 #[note]
657 pub struct HiddenUnicodeCodepointsDiag<'a> {
658     pub label: &'a str,
659     pub count: usize,
660     #[label]
661     pub span_label: Span,
662     #[subdiagnostic]
663     pub labels: Option<HiddenUnicodeCodepointsDiagLabels>,
664     #[subdiagnostic]
665     pub sub: HiddenUnicodeCodepointsDiagSub,
666 }
667
668 pub struct HiddenUnicodeCodepointsDiagLabels {
669     pub spans: Vec<(char, Span)>,
670 }
671
672 impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels {
673     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
674     where
675         F: Fn(
676             &mut rustc_errors::Diagnostic,
677             rustc_errors::SubdiagnosticMessage,
678         ) -> rustc_errors::SubdiagnosticMessage,
679     {
680         for (c, span) in self.spans {
681             diag.span_label(span, format!("{:?}", c));
682         }
683     }
684 }
685
686 pub enum HiddenUnicodeCodepointsDiagSub {
687     Escape { spans: Vec<(char, Span)> },
688     NoEscape { spans: Vec<(char, Span)> },
689 }
690
691 // Used because of multiple multipart_suggestion and note
692 impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
693     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
694     where
695         F: Fn(
696             &mut rustc_errors::Diagnostic,
697             rustc_errors::SubdiagnosticMessage,
698         ) -> rustc_errors::SubdiagnosticMessage,
699     {
700         match self {
701             HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
702                 diag.multipart_suggestion_with_style(
703                     fluent::suggestion_remove,
704                     spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
705                     Applicability::MachineApplicable,
706                     SuggestionStyle::HideCodeAlways,
707                 );
708                 diag.multipart_suggestion(
709                     fluent::suggestion_escape,
710                     spans
711                         .into_iter()
712                         .map(|(c, span)| {
713                             let c = format!("{:?}", c);
714                             (span, c[1..c.len() - 1].to_string())
715                         })
716                         .collect(),
717                     Applicability::MachineApplicable,
718                 );
719             }
720             HiddenUnicodeCodepointsDiagSub::NoEscape { spans } => {
721                 // FIXME: in other suggestions we've reversed the inner spans of doc comments. We
722                 // should do the same here to provide the same good suggestions as we do for
723                 // literals above.
724                 diag.set_arg(
725                     "escaped",
726                     spans
727                         .into_iter()
728                         .map(|(c, _)| format!("{:?}", c))
729                         .collect::<Vec<String>>()
730                         .join(", "),
731                 );
732                 diag.note(fluent::suggestion_remove);
733                 diag.note(fluent::no_suggestion_note_escape);
734             }
735         }
736     }
737 }
738
739 // internal.rs
740 #[derive(LintDiagnostic)]
741 #[diag(lint_default_hash_types)]
742 #[note]
743 pub struct DefaultHashTypesDiag<'a> {
744     pub preferred: &'a str,
745     pub used: Symbol,
746 }
747
748 #[derive(LintDiagnostic)]
749 #[diag(lint_query_instability)]
750 #[note]
751 pub struct QueryInstability {
752     pub query: Symbol,
753 }
754
755 #[derive(LintDiagnostic)]
756 #[diag(lint_tykind_kind)]
757 pub struct TykindKind {
758     #[suggestion(code = "ty", applicability = "maybe-incorrect")]
759     pub suggestion: Span,
760 }
761
762 #[derive(LintDiagnostic)]
763 #[diag(lint_tykind)]
764 #[help]
765 pub struct TykindDiag;
766
767 #[derive(LintDiagnostic)]
768 #[diag(lint_ty_qualified)]
769 pub struct TyQualified {
770     pub ty: String,
771     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
772     pub suggestion: Span,
773 }
774
775 #[derive(LintDiagnostic)]
776 #[diag(lint_lintpass_by_hand)]
777 #[help]
778 pub struct LintPassByHand;
779
780 #[derive(LintDiagnostic)]
781 #[diag(lint_non_existant_doc_keyword)]
782 #[help]
783 pub struct NonExistantDocKeyword {
784     pub keyword: Symbol,
785 }
786
787 #[derive(LintDiagnostic)]
788 #[diag(lint_diag_out_of_impl)]
789 pub struct DiagOutOfImpl;
790
791 #[derive(LintDiagnostic)]
792 #[diag(lint_untranslatable_diag)]
793 pub struct UntranslatableDiag;
794
795 #[derive(LintDiagnostic)]
796 #[diag(lint_bad_opt_access)]
797 pub struct BadOptAccessDiag<'a> {
798     pub msg: &'a str,
799 }
800
801 // let_underscore.rs
802 #[derive(LintDiagnostic)]
803 pub enum NonBindingLet {
804     #[diag(lint_non_binding_let_on_sync_lock)]
805     SyncLock {
806         #[subdiagnostic]
807         sub: NonBindingLetSub,
808     },
809     #[diag(lint_non_binding_let_on_drop_type)]
810     DropType {
811         #[subdiagnostic]
812         sub: NonBindingLetSub,
813     },
814 }
815
816 pub struct NonBindingLetSub {
817     pub suggestion: Span,
818     pub multi_suggestion_start: Span,
819     pub multi_suggestion_end: Span,
820 }
821
822 impl AddToDiagnostic for NonBindingLetSub {
823     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
824     where
825         F: Fn(
826             &mut rustc_errors::Diagnostic,
827             rustc_errors::SubdiagnosticMessage,
828         ) -> rustc_errors::SubdiagnosticMessage,
829     {
830         diag.span_suggestion_verbose(
831             self.suggestion,
832             fluent::lint_non_binding_let_suggestion,
833             "_unused",
834             Applicability::MachineApplicable,
835         );
836         diag.multipart_suggestion(
837             fluent::lint_non_binding_let_multi_suggestion,
838             vec![
839                 (self.multi_suggestion_start, "drop(".to_string()),
840                 (self.multi_suggestion_end, ")".to_string()),
841             ],
842             Applicability::MachineApplicable,
843         );
844     }
845 }
846
847 // levels.rs
848 #[derive(LintDiagnostic)]
849 #[diag(lint_overruled_attribute)]
850 pub struct OverruledAtributeLint<'a> {
851     #[label]
852     pub overruled: Span,
853     pub lint_level: &'a str,
854     pub lint_source: Symbol,
855     #[subdiagnostic]
856     pub sub: OverruledAttributeSub,
857 }
858
859 #[derive(LintDiagnostic)]
860 #[diag(lint_deprecated_lint_name)]
861 pub struct DeprecatedLintName<'a> {
862     pub name: String,
863     #[suggestion(code = "{replace}", applicability = "machine-applicable")]
864     pub suggestion: Span,
865     pub replace: &'a str,
866 }
867
868 // FIXME: Non-translatable msg
869 #[derive(LintDiagnostic)]
870 #[diag(lint_renamed_or_removed_lint)]
871 pub struct RenamedOrRemovedLint<'a> {
872     pub msg: &'a str,
873     #[subdiagnostic]
874     pub suggestion: Option<RenamedOrRemovedLintSuggestion<'a>>,
875 }
876
877 #[derive(Subdiagnostic)]
878 #[suggestion(suggestion, code = "{replace}", applicability = "machine-applicable")]
879 pub struct RenamedOrRemovedLintSuggestion<'a> {
880     #[primary_span]
881     pub suggestion: Span,
882     pub replace: &'a str,
883 }
884
885 #[derive(LintDiagnostic)]
886 #[diag(lint_unknown_lint)]
887 pub struct UnknownLint {
888     pub name: String,
889     #[subdiagnostic]
890     pub suggestion: Option<UnknownLintSuggestion>,
891 }
892
893 #[derive(Subdiagnostic)]
894 #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
895 pub struct UnknownLintSuggestion {
896     #[primary_span]
897     pub suggestion: Span,
898     pub replace: Symbol,
899 }
900
901 #[derive(LintDiagnostic)]
902 #[diag(lint_ignored_unless_crate_specified)]
903 pub struct IgnoredUnlessCrateSpecified<'a> {
904     pub level: &'a str,
905     pub name: Symbol,
906 }
907
908 // methods.rs
909 #[derive(LintDiagnostic)]
910 #[diag(lint_cstring_ptr)]
911 #[note]
912 #[help]
913 pub struct CStringPtr {
914     #[label(as_ptr_label)]
915     pub as_ptr: Span,
916     #[label(unwrap_label)]
917     pub unwrap: Span,
918 }
919
920 // multiple_supertrait_upcastable.rs
921 #[derive(LintDiagnostic)]
922 #[diag(lint_multple_supertrait_upcastable)]
923 pub struct MultipleSupertraitUpcastable {
924     pub ident: Ident,
925 }
926
927 // non_ascii_idents.rs
928 #[derive(LintDiagnostic)]
929 #[diag(lint_identifier_non_ascii_char)]
930 pub struct IdentifierNonAsciiChar;
931
932 #[derive(LintDiagnostic)]
933 #[diag(lint_identifier_uncommon_codepoints)]
934 pub struct IdentifierUncommonCodepoints;
935
936 #[derive(LintDiagnostic)]
937 #[diag(lint_confusable_identifier_pair)]
938 pub struct ConfusableIdentifierPair {
939     pub existing_sym: Symbol,
940     pub sym: Symbol,
941     #[label]
942     pub label: Span,
943 }
944
945 #[derive(LintDiagnostic)]
946 #[diag(lint_mixed_script_confusables)]
947 #[note(includes_note)]
948 #[note]
949 pub struct MixedScriptConfusables {
950     pub set: String,
951     pub includes: String,
952 }
953
954 // non_fmt_panic.rs
955 pub struct NonFmtPanicUnused {
956     pub count: usize,
957     pub suggestion: Option<Span>,
958 }
959
960 // Used because of two suggestions based on one Option<Span>
961 impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
962     fn decorate_lint<'b>(
963         self,
964         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
965     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
966         diag.set_arg("count", self.count);
967         diag.note(fluent::note);
968         if let Some(span) = self.suggestion {
969             diag.span_suggestion(
970                 span.shrink_to_hi(),
971                 fluent::add_args_suggestion,
972                 ", ...",
973                 Applicability::HasPlaceholders,
974             );
975             diag.span_suggestion(
976                 span.shrink_to_lo(),
977                 fluent::add_fmt_suggestion,
978                 "\"{}\", ",
979                 Applicability::MachineApplicable,
980             );
981         }
982         diag
983     }
984
985     fn msg(&self) -> rustc_errors::DiagnosticMessage {
986         fluent::lint_non_fmt_panic_unused
987     }
988 }
989
990 #[derive(LintDiagnostic)]
991 #[diag(lint_non_fmt_panic_braces)]
992 #[note]
993 pub struct NonFmtPanicBraces {
994     pub count: usize,
995     #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
996     pub suggestion: Option<Span>,
997 }
998
999 // nonstandard_style.rs
1000 #[derive(LintDiagnostic)]
1001 #[diag(lint_non_camel_case_type)]
1002 pub struct NonCamelCaseType<'a> {
1003     pub sort: &'a str,
1004     pub name: &'a str,
1005     #[subdiagnostic]
1006     pub sub: NonCamelCaseTypeSub,
1007 }
1008
1009 #[derive(Subdiagnostic)]
1010 pub enum NonCamelCaseTypeSub {
1011     #[label(label)]
1012     Label {
1013         #[primary_span]
1014         span: Span,
1015     },
1016     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1017     Suggestion {
1018         #[primary_span]
1019         span: Span,
1020         replace: String,
1021     },
1022 }
1023
1024 #[derive(LintDiagnostic)]
1025 #[diag(lint_non_snake_case)]
1026 pub struct NonSnakeCaseDiag<'a> {
1027     pub sort: &'a str,
1028     pub name: &'a str,
1029     pub sc: String,
1030     #[subdiagnostic]
1031     pub sub: NonSnakeCaseDiagSub,
1032 }
1033
1034 pub enum NonSnakeCaseDiagSub {
1035     Label { span: Span },
1036     Help,
1037     RenameOrConvertSuggestion { span: Span, suggestion: Ident },
1038     ConvertSuggestion { span: Span, suggestion: String },
1039     SuggestionAndNote { span: Span },
1040 }
1041
1042 impl AddToDiagnostic for NonSnakeCaseDiagSub {
1043     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
1044     where
1045         F: Fn(
1046             &mut rustc_errors::Diagnostic,
1047             rustc_errors::SubdiagnosticMessage,
1048         ) -> rustc_errors::SubdiagnosticMessage,
1049     {
1050         match self {
1051             NonSnakeCaseDiagSub::Label { span } => {
1052                 diag.span_label(span, fluent::label);
1053             }
1054             NonSnakeCaseDiagSub::Help => {
1055                 diag.help(fluent::help);
1056             }
1057             NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
1058                 diag.span_suggestion(
1059                     span,
1060                     fluent::convert_suggestion,
1061                     suggestion,
1062                     Applicability::MaybeIncorrect,
1063                 );
1064             }
1065             NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
1066                 diag.span_suggestion(
1067                     span,
1068                     fluent::rename_or_convert_suggestion,
1069                     suggestion,
1070                     Applicability::MaybeIncorrect,
1071                 );
1072             }
1073             NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
1074                 diag.note(fluent::cannot_convert_note);
1075                 diag.span_suggestion(
1076                     span,
1077                     fluent::rename_suggestion,
1078                     "",
1079                     Applicability::MaybeIncorrect,
1080                 );
1081             }
1082         }
1083     }
1084 }
1085
1086 #[derive(LintDiagnostic)]
1087 #[diag(lint_non_upper_case_global)]
1088 pub struct NonUpperCaseGlobal<'a> {
1089     pub sort: &'a str,
1090     pub name: &'a str,
1091     #[subdiagnostic]
1092     pub sub: NonUpperCaseGlobalSub,
1093 }
1094
1095 #[derive(Subdiagnostic)]
1096 pub enum NonUpperCaseGlobalSub {
1097     #[label(label)]
1098     Label {
1099         #[primary_span]
1100         span: Span,
1101     },
1102     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
1103     Suggestion {
1104         #[primary_span]
1105         span: Span,
1106         replace: String,
1107     },
1108 }
1109
1110 // noop_method_call.rs
1111 #[derive(LintDiagnostic)]
1112 #[diag(lint_noop_method_call)]
1113 #[note]
1114 pub struct NoopMethodCallDiag<'a> {
1115     pub method: Symbol,
1116     pub receiver_ty: Ty<'a>,
1117     #[label]
1118     pub label: Span,
1119 }
1120
1121 // pass_by_value.rs
1122 #[derive(LintDiagnostic)]
1123 #[diag(lint_pass_by_value)]
1124 pub struct PassByValueDiag {
1125     pub ty: String,
1126     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
1127     pub suggestion: Span,
1128 }
1129
1130 // redundant_semicolon.rs
1131 #[derive(LintDiagnostic)]
1132 #[diag(lint_redundant_semicolons)]
1133 pub struct RedundantSemicolonsDiag {
1134     pub multiple: bool,
1135     #[suggestion(code = "", applicability = "maybe-incorrect")]
1136     pub suggestion: Span,
1137 }
1138
1139 // traits.rs
1140 pub struct DropTraitConstraintsDiag<'a> {
1141     pub predicate: Predicate<'a>,
1142     pub tcx: TyCtxt<'a>,
1143     pub def_id: DefId,
1144 }
1145
1146 // Needed for def_path_str
1147 impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> {
1148     fn decorate_lint<'b>(
1149         self,
1150         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
1151     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
1152         diag.set_arg("predicate", self.predicate);
1153         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id))
1154     }
1155
1156     fn msg(&self) -> rustc_errors::DiagnosticMessage {
1157         fluent::lint_drop_trait_constraints
1158     }
1159 }
1160
1161 pub struct DropGlue<'a> {
1162     pub tcx: TyCtxt<'a>,
1163     pub def_id: DefId,
1164 }
1165
1166 // Needed for def_path_str
1167 impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
1168     fn decorate_lint<'b>(
1169         self,
1170         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
1171     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
1172         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id))
1173     }
1174
1175     fn msg(&self) -> rustc_errors::DiagnosticMessage {
1176         fluent::lint_drop_glue
1177     }
1178 }
1179
1180 // types.rs
1181 #[derive(LintDiagnostic)]
1182 #[diag(lint_range_endpoint_out_of_range)]
1183 pub struct RangeEndpointOutOfRange<'a> {
1184     pub ty: &'a str,
1185     #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
1186     pub suggestion: Span,
1187     pub start: String,
1188     pub literal: u128,
1189     pub suffix: &'a str,
1190 }
1191
1192 #[derive(LintDiagnostic)]
1193 #[diag(lint_overflowing_bin_hex)]
1194 pub struct OverflowingBinHex<'a> {
1195     pub ty: &'a str,
1196     pub lit: String,
1197     pub dec: u128,
1198     pub actually: String,
1199     #[subdiagnostic]
1200     pub sign: OverflowingBinHexSign,
1201     #[subdiagnostic]
1202     pub sub: Option<OverflowingBinHexSub<'a>>,
1203 }
1204
1205 pub enum OverflowingBinHexSign {
1206     Positive,
1207     Negative,
1208 }
1209
1210 impl AddToDiagnostic for OverflowingBinHexSign {
1211     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
1212     where
1213         F: Fn(
1214             &mut rustc_errors::Diagnostic,
1215             rustc_errors::SubdiagnosticMessage,
1216         ) -> rustc_errors::SubdiagnosticMessage,
1217     {
1218         match self {
1219             OverflowingBinHexSign::Positive => {
1220                 diag.note(fluent::positive_note);
1221             }
1222             OverflowingBinHexSign::Negative => {
1223                 diag.note(fluent::negative_note);
1224                 diag.note(fluent::negative_becomes_note);
1225             }
1226         }
1227     }
1228 }
1229
1230 #[derive(Subdiagnostic)]
1231 pub enum OverflowingBinHexSub<'a> {
1232     #[suggestion(
1233         suggestion,
1234         code = "{sans_suffix}{suggestion_ty}",
1235         applicability = "machine-applicable"
1236     )]
1237     Suggestion {
1238         #[primary_span]
1239         span: Span,
1240         suggestion_ty: &'a str,
1241         sans_suffix: &'a str,
1242     },
1243     #[help(help)]
1244     Help { suggestion_ty: &'a str },
1245 }
1246
1247 #[derive(LintDiagnostic)]
1248 #[diag(lint_overflowing_int)]
1249 #[note]
1250 pub struct OverflowingInt<'a> {
1251     pub ty: &'a str,
1252     pub lit: String,
1253     pub min: i128,
1254     pub max: u128,
1255     #[subdiagnostic]
1256     pub help: Option<OverflowingIntHelp<'a>>,
1257 }
1258
1259 #[derive(Subdiagnostic)]
1260 #[help(help)]
1261 pub struct OverflowingIntHelp<'a> {
1262     pub suggestion_ty: &'a str,
1263 }
1264
1265 #[derive(LintDiagnostic)]
1266 #[diag(lint_only_cast_u8_to_char)]
1267 pub struct OnlyCastu8ToChar {
1268     #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
1269     pub span: Span,
1270     pub literal: u128,
1271 }
1272
1273 #[derive(LintDiagnostic)]
1274 #[diag(lint_overflowing_uint)]
1275 #[note]
1276 pub struct OverflowingUInt<'a> {
1277     pub ty: &'a str,
1278     pub lit: String,
1279     pub min: u128,
1280     pub max: u128,
1281 }
1282
1283 #[derive(LintDiagnostic)]
1284 #[diag(lint_overflowing_literal)]
1285 #[note]
1286 pub struct OverflowingLiteral<'a> {
1287     pub ty: &'a str,
1288     pub lit: String,
1289 }
1290
1291 #[derive(LintDiagnostic)]
1292 #[diag(lint_unused_comparisons)]
1293 pub struct UnusedComparisons;
1294
1295 pub struct ImproperCTypes<'a> {
1296     pub ty: Ty<'a>,
1297     pub desc: &'a str,
1298     pub label: Span,
1299     pub help: Option<DiagnosticMessage>,
1300     pub note: DiagnosticMessage,
1301     pub span_note: Option<Span>,
1302 }
1303
1304 // Used because of the complexity of Option<DiagnosticMessage>, DiagnosticMessage, and Option<Span>
1305 impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
1306     fn decorate_lint<'b>(
1307         self,
1308         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
1309     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
1310         diag.set_arg("ty", self.ty);
1311         diag.set_arg("desc", self.desc);
1312         diag.span_label(self.label, fluent::label);
1313         if let Some(help) = self.help {
1314             diag.help(help);
1315         }
1316         diag.note(self.note);
1317         if let Some(note) = self.span_note {
1318             diag.span_note(note, fluent::note);
1319         }
1320         diag
1321     }
1322
1323     fn msg(&self) -> rustc_errors::DiagnosticMessage {
1324         fluent::lint_improper_ctypes
1325     }
1326 }
1327
1328 #[derive(LintDiagnostic)]
1329 #[diag(lint_variant_size_differences)]
1330 pub struct VariantSizeDifferencesDiag {
1331     pub largest: u64,
1332 }
1333
1334 #[derive(LintDiagnostic)]
1335 #[diag(lint_atomic_ordering_load)]
1336 #[help]
1337 pub struct AtomicOrderingLoad;
1338
1339 #[derive(LintDiagnostic)]
1340 #[diag(lint_atomic_ordering_store)]
1341 #[help]
1342 pub struct AtomicOrderingStore;
1343
1344 #[derive(LintDiagnostic)]
1345 #[diag(lint_atomic_ordering_fence)]
1346 #[help]
1347 pub struct AtomicOrderingFence;
1348
1349 #[derive(LintDiagnostic)]
1350 #[diag(lint_atomic_ordering_invalid)]
1351 #[help]
1352 pub struct InvalidAtomicOrderingDiag {
1353     pub method: Symbol,
1354     #[label]
1355     pub fail_order_arg_span: Span,
1356 }
1357
1358 // unused.rs
1359 #[derive(LintDiagnostic)]
1360 #[diag(lint_unused_op)]
1361 pub struct UnusedOp<'a> {
1362     pub op: &'a str,
1363     #[label]
1364     pub label: Span,
1365     #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")]
1366     pub suggestion: Span,
1367 }
1368
1369 #[derive(LintDiagnostic)]
1370 #[diag(lint_unused_result)]
1371 pub struct UnusedResult<'a> {
1372     pub ty: Ty<'a>,
1373 }
1374
1375 // FIXME(davidtwco): this isn't properly translatable becauses of the
1376 // pre/post strings
1377 #[derive(LintDiagnostic)]
1378 #[diag(lint_unused_closure)]
1379 #[note]
1380 pub struct UnusedClosure<'a> {
1381     pub count: usize,
1382     pub pre: &'a str,
1383     pub post: &'a str,
1384 }
1385
1386 // FIXME(davidtwco): this isn't properly translatable becauses of the
1387 // pre/post strings
1388 #[derive(LintDiagnostic)]
1389 #[diag(lint_unused_generator)]
1390 #[note]
1391 pub struct UnusedGenerator<'a> {
1392     pub count: usize,
1393     pub pre: &'a str,
1394     pub post: &'a str,
1395 }
1396
1397 // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
1398 // strings
1399 pub struct UnusedDef<'a, 'b> {
1400     pub pre: &'a str,
1401     pub post: &'a str,
1402     pub cx: &'a LateContext<'b>,
1403     pub def_id: DefId,
1404     pub note: Option<Symbol>,
1405     pub suggestion: Option<UnusedDefSuggestion>,
1406 }
1407
1408 #[derive(Subdiagnostic)]
1409 pub enum UnusedDefSuggestion {
1410     #[suggestion(
1411         suggestion,
1412         style = "verbose",
1413         code = "let _ = ",
1414         applicability = "machine-applicable"
1415     )]
1416     Default {
1417         #[primary_span]
1418         span: Span,
1419     },
1420 }
1421
1422 // Needed because of def_path_str
1423 impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
1424     fn decorate_lint<'b>(
1425         self,
1426         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
1427     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
1428         diag.set_arg("pre", self.pre);
1429         diag.set_arg("post", self.post);
1430         diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
1431         // check for #[must_use = "..."]
1432         if let Some(note) = self.note {
1433             diag.note(note.as_str());
1434         }
1435         if let Some(sugg) = self.suggestion {
1436             diag.subdiagnostic(sugg);
1437         }
1438         diag
1439     }
1440
1441     fn msg(&self) -> rustc_errors::DiagnosticMessage {
1442         fluent::lint_unused_def
1443     }
1444 }
1445
1446 #[derive(LintDiagnostic)]
1447 #[diag(lint_path_statement_drop)]
1448 pub struct PathStatementDrop {
1449     #[subdiagnostic]
1450     pub sub: PathStatementDropSub,
1451 }
1452
1453 #[derive(Subdiagnostic)]
1454 pub enum PathStatementDropSub {
1455     #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
1456     Suggestion {
1457         #[primary_span]
1458         span: Span,
1459         snippet: String,
1460     },
1461     #[help(help)]
1462     Help {
1463         #[primary_span]
1464         span: Span,
1465     },
1466 }
1467
1468 #[derive(LintDiagnostic)]
1469 #[diag(lint_path_statement_no_effect)]
1470 pub struct PathStatementNoEffect;
1471
1472 #[derive(LintDiagnostic)]
1473 #[diag(lint_unused_delim)]
1474 pub struct UnusedDelim<'a> {
1475     pub delim: &'static str,
1476     pub item: &'a str,
1477     #[subdiagnostic]
1478     pub suggestion: Option<UnusedDelimSuggestion>,
1479 }
1480
1481 #[derive(Subdiagnostic)]
1482 #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
1483 pub struct UnusedDelimSuggestion {
1484     #[suggestion_part(code = "{start_replace}")]
1485     pub start_span: Span,
1486     pub start_replace: &'static str,
1487     #[suggestion_part(code = "{end_replace}")]
1488     pub end_span: Span,
1489     pub end_replace: &'static str,
1490 }
1491
1492 #[derive(LintDiagnostic)]
1493 #[diag(lint_unused_import_braces)]
1494 pub struct UnusedImportBracesDiag {
1495     pub node: Symbol,
1496 }
1497
1498 #[derive(LintDiagnostic)]
1499 #[diag(lint_unused_allocation)]
1500 pub struct UnusedAllocationDiag;
1501
1502 #[derive(LintDiagnostic)]
1503 #[diag(lint_unused_allocation_mut)]
1504 pub struct UnusedAllocationMutDiag;