]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/lints.rs
196922b78c30c35f331c77eb315684e3e554c767
[rust.git] / compiler / rustc_lint / src / lints.rs
1 use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage};
2 use rustc_hir::def_id::DefId;
3 use rustc_macros::{LintDiagnostic, Subdiagnostic};
4 use rustc_middle::ty::{Predicate, Ty, TyCtxt};
5 use rustc_span::{symbol::Ident, Span, Symbol};
6
7 use crate::{errors::OverruledAttributeSub, LateContext};
8
9 // array_into_iter.rs
10 #[derive(LintDiagnostic)]
11 #[diag(lint_array_into_iter)]
12 pub struct ArrayIntoIterDiag<'a> {
13     pub target: &'a str,
14     #[suggestion(use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
15     pub suggestion: Span,
16     #[subdiagnostic]
17     pub sub: Option<ArrayIntoIterDiagSub>,
18 }
19
20 #[derive(Subdiagnostic)]
21 pub enum ArrayIntoIterDiagSub {
22     #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
23     RemoveIntoIter {
24         #[primary_span]
25         span: Span,
26     },
27     #[multipart_suggestion(use_explicit_into_iter_suggestion, applicability = "maybe-incorrect")]
28     UseExplicitIntoIter {
29         #[suggestion_part(code = "IntoIterator::into_iter(")]
30         start_span: Span,
31         #[suggestion_part(code = ")")]
32         end_span: Span,
33     },
34 }
35
36 // enum_intrinsics_non_enums.rs
37 #[derive(LintDiagnostic)]
38 #[diag(lint_enum_intrinsics_mem_discriminant)]
39 pub struct EnumIntrinsicsMemDiscriminate<'a> {
40     pub ty_param: Ty<'a>,
41     #[note]
42     pub note: Span,
43 }
44
45 #[derive(LintDiagnostic)]
46 #[diag(lint_enum_intrinsics_mem_variant)]
47 #[note]
48 pub struct EnumIntrinsicsMemVariant<'a> {
49     pub ty_param: Ty<'a>,
50 }
51
52 // internal.rs
53 #[derive(LintDiagnostic)]
54 #[diag(lint_default_hash_types)]
55 #[note]
56 pub struct DefaultHashTypesDiag<'a> {
57     pub preferred: &'a str,
58     pub used: Symbol,
59 }
60
61 #[derive(LintDiagnostic)]
62 #[diag(lint_query_instability)]
63 #[note]
64 pub struct QueryInstability {
65     pub query: Symbol,
66 }
67
68 #[derive(LintDiagnostic)]
69 #[diag(lint_tykind_kind)]
70 pub struct TykindKind {
71     #[suggestion(code = "ty", applicability = "maybe-incorrect")]
72     pub suggestion: Span,
73 }
74
75 #[derive(LintDiagnostic)]
76 #[diag(lint_tykind)]
77 #[help]
78 pub struct TykindDiag;
79
80 #[derive(LintDiagnostic)]
81 #[diag(lint_ty_qualified)]
82 pub struct TyQualified {
83     pub ty: String,
84     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
85     pub suggestion: Span,
86 }
87
88 #[derive(LintDiagnostic)]
89 #[diag(lint_lintpass_by_hand)]
90 #[help]
91 pub struct LintPassByHand;
92
93 #[derive(LintDiagnostic)]
94 #[diag(lint_non_existant_doc_keyword)]
95 #[help]
96 pub struct NonExistantDocKeyword {
97     pub keyword: Symbol,
98 }
99
100 #[derive(LintDiagnostic)]
101 #[diag(lint_diag_out_of_impl)]
102 pub struct DiagOutOfImpl;
103
104 #[derive(LintDiagnostic)]
105 #[diag(lint_untranslatable_diag)]
106 pub struct UntranslatableDiag;
107
108 #[derive(LintDiagnostic)]
109 #[diag(lint_bad_opt_access)]
110 pub struct BadOptAccessDiag<'a> {
111     pub msg: &'a str,
112 }
113
114 // let_underscore.rs
115 #[derive(LintDiagnostic)]
116 pub enum NonBindingLet {
117     #[diag(lint_non_binding_let_on_sync_lock)]
118     SyncLock {
119         #[subdiagnostic]
120         sub: NonBindingLetSub,
121     },
122     #[diag(lint_non_binding_let_on_drop_type)]
123     DropType {
124         #[subdiagnostic]
125         sub: NonBindingLetSub,
126     },
127 }
128
129 pub struct NonBindingLetSub {
130     pub suggestion: Span,
131     pub multi_suggestion_start: Span,
132     pub multi_suggestion_end: Span,
133 }
134
135 impl AddToDiagnostic for NonBindingLetSub {
136     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
137     where
138         F: Fn(
139             &mut rustc_errors::Diagnostic,
140             rustc_errors::SubdiagnosticMessage,
141         ) -> rustc_errors::SubdiagnosticMessage,
142     {
143         diag.span_suggestion_verbose(
144             self.suggestion,
145             fluent::lint_non_binding_let_suggestion,
146             "_unused",
147             Applicability::MachineApplicable,
148         );
149         diag.multipart_suggestion(
150             fluent::lint_non_binding_let_multi_suggestion,
151             vec![
152                 (self.multi_suggestion_start, "drop(".to_string()),
153                 (self.multi_suggestion_end, ")".to_string()),
154             ],
155             Applicability::MachineApplicable,
156         );
157     }
158 }
159
160 // levels.rs
161 #[derive(LintDiagnostic)]
162 #[diag(lint_overruled_attribute)]
163 pub struct OverruledAtributeLint<'a> {
164     #[label]
165     pub overruled: Span,
166     pub lint_level: &'a str,
167     pub lint_source: Symbol,
168     #[subdiagnostic]
169     pub sub: OverruledAttributeSub,
170 }
171
172 #[derive(LintDiagnostic)]
173 #[diag(lint_deprecated_lint_name)]
174 pub struct DeprecatedLintName<'a> {
175     pub name: String,
176     #[suggestion(code = "{replace}", applicability = "machine-applicable")]
177     pub suggestion: Span,
178     pub replace: &'a str,
179 }
180
181 pub struct RenamedOrRemovedLint<'a> {
182     pub msg: &'a str,
183     pub suggestion: Span,
184     pub renamed: &'a Option<String>,
185 }
186
187 impl<'a> DecorateLint<'a, ()> for RenamedOrRemovedLint<'_> {
188     fn decorate_lint<'b>(
189         self,
190         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
191     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
192         if let Some(new_name) = self.renamed {
193             diag.span_suggestion(
194                 self.suggestion,
195                 fluent::lint_renamed_or_removed_lint_suggestion,
196                 new_name,
197                 Applicability::MachineApplicable,
198             );
199         };
200         diag
201     }
202
203     fn msg(&self) -> rustc_errors::DiagnosticMessage {
204         rustc_errors::DiagnosticMessage::Str(self.msg.to_string())
205     }
206 }
207
208 pub struct UnknownLint<'a> {
209     pub name: String,
210     pub suggestion: Span,
211     pub replace: &'a Option<Symbol>,
212 }
213
214 impl<'a> DecorateLint<'a, ()> for UnknownLint<'_> {
215     fn decorate_lint<'b>(
216         self,
217         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
218     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
219         diag.set_arg("name", self.name);
220         if let Some(replace) = self.replace {
221             diag.span_suggestion(
222                 self.suggestion,
223                 fluent::suggestion,
224                 replace,
225                 Applicability::MaybeIncorrect,
226             );
227         };
228         diag
229     }
230
231     fn msg(&self) -> rustc_errors::DiagnosticMessage {
232         fluent::lint_unknown_lint
233     }
234 }
235
236 #[derive(LintDiagnostic)]
237 #[diag(lint_ignored_unless_crate_specified)]
238 pub struct IgnoredUnlessCrateSpecified<'a> {
239     pub level: &'a str,
240     pub name: Symbol,
241 }
242
243 // methods.rs
244 #[derive(LintDiagnostic)]
245 #[diag(lint_cstring_ptr)]
246 #[note]
247 #[help]
248 pub struct CStringPtr {
249     #[label(as_ptr_label)]
250     pub as_ptr: Span,
251     #[label(unwrap_label)]
252     pub unwrap: Span,
253 }
254
255 // non_ascii_idents.rs
256 #[derive(LintDiagnostic)]
257 #[diag(lint_identifier_non_ascii_char)]
258 pub struct IdentifierNonAsciiChar;
259
260 #[derive(LintDiagnostic)]
261 #[diag(lint_identifier_uncommon_codepoints)]
262 pub struct IdentifierUncommonCodepoints;
263
264 #[derive(LintDiagnostic)]
265 #[diag(lint_confusable_identifier_pair)]
266 pub struct ConfusableIdentifierPair {
267     pub existing_sym: Symbol,
268     pub sym: Symbol,
269     #[label]
270     pub label: Span,
271 }
272
273 #[derive(LintDiagnostic)]
274 #[diag(lint_mixed_script_confusables)]
275 #[note(includes_note)]
276 #[note]
277 pub struct MixedScriptConfusables {
278     pub set: String,
279     pub includes: String,
280 }
281
282 // non_fmt_panic.rs
283 pub struct NonFmtPanicUnused {
284     pub count: usize,
285     pub suggestion: Option<Span>,
286 }
287
288 impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
289     fn decorate_lint<'b>(
290         self,
291         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
292     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
293         diag.set_arg("count", self.count);
294         diag.note(fluent::note);
295         if let Some(span) = self.suggestion {
296             diag.span_suggestion(
297                 span.shrink_to_hi(),
298                 fluent::add_args_suggestion,
299                 ", ...",
300                 Applicability::HasPlaceholders,
301             );
302             diag.span_suggestion(
303                 span.shrink_to_lo(),
304                 fluent::add_fmt_suggestion,
305                 "\"{}\", ",
306                 Applicability::MachineApplicable,
307             );
308         }
309         diag
310     }
311
312     fn msg(&self) -> rustc_errors::DiagnosticMessage {
313         fluent::lint_non_fmt_panic_unused
314     }
315 }
316
317 #[derive(LintDiagnostic)]
318 #[diag(lint_non_fmt_panic_braces)]
319 #[note]
320 pub struct NonFmtPanicBraces {
321     pub count: usize,
322     #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
323     pub suggestion: Option<Span>,
324 }
325
326 // nonstandard_style.rs
327 #[derive(LintDiagnostic)]
328 #[diag(lint_non_camel_case_type)]
329 pub struct NonCamelCaseType<'a> {
330     pub sort: &'a str,
331     pub name: &'a str,
332     #[subdiagnostic]
333     pub sub: NonCamelCaseTypeSub,
334 }
335
336 #[derive(Subdiagnostic)]
337 pub enum NonCamelCaseTypeSub {
338     #[label(label)]
339     Label {
340         #[primary_span]
341         span: Span,
342     },
343     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
344     Suggestion {
345         #[primary_span]
346         span: Span,
347         replace: String,
348     },
349 }
350
351 #[derive(LintDiagnostic)]
352 #[diag(lint_non_snake_case)]
353 pub struct NonSnakeCaseDiag<'a> {
354     pub sort: &'a str,
355     pub name: &'a str,
356     pub sc: String,
357     #[subdiagnostic]
358     pub sub: NonSnakeCaseDiagSub,
359 }
360
361 pub enum NonSnakeCaseDiagSub {
362     Label { span: Span },
363     Help,
364     RenameOrConvertSuggestion { span: Span, suggestion: Ident },
365     ConvertSuggestion { span: Span, suggestion: String },
366     SuggestionAndNote { span: Span },
367 }
368
369 impl AddToDiagnostic for NonSnakeCaseDiagSub {
370     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
371     where
372         F: Fn(
373             &mut rustc_errors::Diagnostic,
374             rustc_errors::SubdiagnosticMessage,
375         ) -> rustc_errors::SubdiagnosticMessage,
376     {
377         match self {
378             NonSnakeCaseDiagSub::Label { span } => {
379                 diag.span_label(span, fluent::label);
380             }
381             NonSnakeCaseDiagSub::Help => {
382                 diag.help(fluent::help);
383             }
384             NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
385                 diag.span_suggestion(
386                     span,
387                     fluent::convert_suggestion,
388                     suggestion,
389                     Applicability::MaybeIncorrect,
390                 );
391             }
392             NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
393                 diag.span_suggestion(
394                     span,
395                     fluent::rename_or_convert_suggestion,
396                     suggestion,
397                     Applicability::MaybeIncorrect,
398                 );
399             }
400             NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
401                 diag.note(fluent::cannot_convert_note);
402                 diag.span_suggestion(
403                     span,
404                     fluent::rename_suggestion,
405                     "",
406                     Applicability::MaybeIncorrect,
407                 );
408             }
409         }
410     }
411 }
412
413 #[derive(LintDiagnostic)]
414 #[diag(lint_non_upper_case_global)]
415 pub struct NonUpperCaseGlobal<'a> {
416     pub sort: &'a str,
417     pub name: &'a str,
418     #[subdiagnostic]
419     pub sub: NonUpperCaseGlobalSub,
420 }
421
422 #[derive(Subdiagnostic)]
423 pub enum NonUpperCaseGlobalSub {
424     #[label(label)]
425     Label {
426         #[primary_span]
427         span: Span,
428     },
429     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
430     Suggestion {
431         #[primary_span]
432         span: Span,
433         replace: String,
434     },
435 }
436
437 // noop_method_call.rs
438 #[derive(LintDiagnostic)]
439 #[diag(lint_noop_method_call)]
440 #[note]
441 pub struct NoopMethodCallDiag<'a> {
442     pub method: Symbol,
443     pub receiver_ty: Ty<'a>,
444     #[label]
445     pub label: Span,
446 }
447
448 // pass_by_value.rs
449 #[derive(LintDiagnostic)]
450 #[diag(lint_pass_by_value)]
451 pub struct PassByValueDiag {
452     pub ty: String,
453     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
454     pub suggestion: Span,
455 }
456
457 // redundant_semicolon.rs
458 #[derive(LintDiagnostic)]
459 #[diag(lint_redundant_semicolons)]
460 pub struct RedundantSemicolonsDiag {
461     pub multiple: bool,
462     #[suggestion(code = "", applicability = "maybe-incorrect")]
463     pub suggestion: Span,
464 }
465
466 // traits.rs
467 pub struct DropTraitConstraintsDiag<'a> {
468     pub predicate: Predicate<'a>,
469     pub tcx: TyCtxt<'a>,
470     pub def_id: DefId,
471 }
472
473 impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> {
474     fn decorate_lint<'b>(
475         self,
476         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
477     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
478         diag.set_arg("predicate", self.predicate);
479         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id))
480     }
481
482     fn msg(&self) -> rustc_errors::DiagnosticMessage {
483         fluent::lint_drop_trait_constraints
484     }
485 }
486
487 pub struct DropGlue<'a> {
488     pub tcx: TyCtxt<'a>,
489     pub def_id: DefId,
490 }
491
492 impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
493     fn decorate_lint<'b>(
494         self,
495         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
496     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
497         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id))
498     }
499
500     fn msg(&self) -> rustc_errors::DiagnosticMessage {
501         fluent::lint_drop_glue
502     }
503 }
504
505 // types.rs
506 #[derive(LintDiagnostic)]
507 #[diag(lint_range_endpoint_out_of_range)]
508 pub struct RangeEndpointOutOfRange<'a> {
509     pub ty: &'a str,
510     #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
511     pub suggestion: Span,
512     pub start: String,
513     pub literal: u128,
514     pub suffix: &'a str,
515 }
516
517 #[derive(LintDiagnostic)]
518 #[diag(lint_overflowing_bin_hex)]
519 pub struct OverflowingBinHex<'a> {
520     pub ty: &'a str,
521     pub lit: String,
522     pub dec: u128,
523     pub actually: String,
524     #[subdiagnostic]
525     pub sign: OverflowingBinHexSign,
526     #[subdiagnostic]
527     pub sub: Option<OverflowingBinHexSub<'a>>,
528 }
529
530 pub enum OverflowingBinHexSign {
531     Positive,
532     Negative,
533 }
534
535 impl AddToDiagnostic for OverflowingBinHexSign {
536     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
537     where
538         F: Fn(
539             &mut rustc_errors::Diagnostic,
540             rustc_errors::SubdiagnosticMessage,
541         ) -> rustc_errors::SubdiagnosticMessage,
542     {
543         match self {
544             OverflowingBinHexSign::Positive => {
545                 diag.note(fluent::positive_note);
546             }
547             OverflowingBinHexSign::Negative => {
548                 diag.note(fluent::negative_note);
549                 diag.note(fluent::negative_becomes_note);
550             }
551         }
552     }
553 }
554
555 #[derive(Subdiagnostic)]
556 pub enum OverflowingBinHexSub<'a> {
557     #[suggestion(
558         suggestion,
559         code = "{sans_suffix}{suggestion_ty}",
560         applicability = "machine-applicable"
561     )]
562     Suggestion {
563         #[primary_span]
564         span: Span,
565         suggestion_ty: &'a str,
566         sans_suffix: &'a str,
567     },
568     #[help(help)]
569     Help { suggestion_ty: &'a str },
570 }
571
572 pub struct OverflowingInt<'a> {
573     pub ty: &'a str,
574     pub lit: String,
575     pub min: i128,
576     pub max: u128,
577     pub suggestion_ty: Option<&'a str>,
578 }
579
580 // FIXME: refactor with `Option<&'a str>` in macro
581 impl<'a> DecorateLint<'a, ()> for OverflowingInt<'_> {
582     fn decorate_lint<'b>(
583         self,
584         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
585     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
586         diag.set_arg("ty", self.ty);
587         diag.set_arg("lit", self.lit);
588         diag.set_arg("min", self.min);
589         diag.set_arg("max", self.max);
590         diag.note(fluent::note);
591         if let Some(suggestion_ty) = self.suggestion_ty {
592             diag.set_arg("suggestion_ty", suggestion_ty);
593             diag.help(fluent::help);
594         }
595         diag
596     }
597
598     fn msg(&self) -> rustc_errors::DiagnosticMessage {
599         fluent::lint_overflowing_int
600     }
601 }
602
603 #[derive(LintDiagnostic)]
604 #[diag(lint_only_cast_u8_to_char)]
605 pub struct OnlyCastu8ToChar {
606     #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
607     pub span: Span,
608     pub literal: u128,
609 }
610
611 #[derive(LintDiagnostic)]
612 #[diag(lint_overflowing_uint)]
613 #[note]
614 pub struct OverflowingUInt<'a> {
615     pub ty: &'a str,
616     pub lit: String,
617     pub min: u128,
618     pub max: u128,
619 }
620
621 #[derive(LintDiagnostic)]
622 #[diag(lint_overflowing_literal)]
623 #[note]
624 pub struct OverflowingLiteral<'a> {
625     pub ty: &'a str,
626     pub lit: String,
627 }
628
629 #[derive(LintDiagnostic)]
630 #[diag(lint_unused_comparisons)]
631 pub struct UnusedComparisons;
632
633 pub struct ImproperCTypes<'a> {
634     pub ty: Ty<'a>,
635     pub desc: &'a str,
636     pub label: Span,
637     pub help: Option<DiagnosticMessage>,
638     pub note: DiagnosticMessage,
639     pub span_note: Option<Span>,
640 }
641
642 impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
643     fn decorate_lint<'b>(
644         self,
645         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
646     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
647         diag.set_arg("ty", self.ty);
648         diag.set_arg("desc", self.desc);
649         diag.span_label(self.label, fluent::label);
650         if let Some(help) = self.help {
651             diag.help(help);
652         }
653         diag.note(self.note);
654         if let Some(note) = self.span_note {
655             diag.span_note(note, fluent::note);
656         }
657         diag
658     }
659
660     fn msg(&self) -> rustc_errors::DiagnosticMessage {
661         fluent::lint_improper_ctypes
662     }
663 }
664
665 #[derive(LintDiagnostic)]
666 #[diag(lint_variant_size_differences)]
667 pub struct VariantSizeDifferencesDiag {
668     pub largest: u64,
669 }
670
671 #[derive(LintDiagnostic)]
672 #[diag(lint_atomic_ordering_load)]
673 #[help]
674 pub struct AtomicOrderingLoad;
675
676 #[derive(LintDiagnostic)]
677 #[diag(lint_atomic_ordering_store)]
678 #[help]
679 pub struct AtomicOrderingStore;
680
681 #[derive(LintDiagnostic)]
682 #[diag(lint_atomic_ordering_fence)]
683 #[help]
684 pub struct AtomicOrderingFence;
685
686 #[derive(LintDiagnostic)]
687 #[diag(lint_atomic_ordering_invalid)]
688 #[help]
689 pub struct InvalidAtomicOrderingDiag {
690     pub method: Symbol,
691     #[label]
692     pub fail_order_arg_span: Span,
693 }
694
695 // unused.rs
696 #[derive(LintDiagnostic)]
697 #[diag(lint_unused_op)]
698 pub struct UnusedOp<'a> {
699     pub op: &'a str,
700     #[label]
701     pub label: Span,
702     #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")]
703     pub suggestion: Span,
704 }
705
706 #[derive(LintDiagnostic)]
707 #[diag(lint_unused_result)]
708 pub struct UnusedResult<'a> {
709     pub ty: Ty<'a>,
710 }
711
712 // FIXME(davidtwco): this isn't properly translatable becauses of the
713 // pre/post strings
714 #[derive(LintDiagnostic)]
715 #[diag(lint_unused_closure)]
716 #[note]
717 pub struct UnusedClosure<'a> {
718     pub count: usize,
719     pub pre: &'a str,
720     pub post: &'a str,
721 }
722
723 // FIXME(davidtwco): this isn't properly translatable becauses of the
724 // pre/post strings
725 #[derive(LintDiagnostic)]
726 #[diag(lint_unused_generator)]
727 #[note]
728 pub struct UnusedGenerator<'a> {
729     pub count: usize,
730     pub pre: &'a str,
731     pub post: &'a str,
732 }
733
734 // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
735 // strings
736 pub struct UnusedDef<'a, 'b> {
737     pub pre: &'a str,
738     pub post: &'a str,
739     pub cx: &'a LateContext<'b>,
740     pub def_id: DefId,
741     pub note: Option<Symbol>,
742 }
743
744 // FIXME: refactor with `Option<String>` in macro
745 impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
746     fn decorate_lint<'b>(
747         self,
748         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
749     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
750         diag.set_arg("pre", self.pre);
751         diag.set_arg("post", self.post);
752         diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
753         // check for #[must_use = "..."]
754         if let Some(note) = self.note {
755             diag.note(note.as_str());
756         }
757         diag
758     }
759
760     fn msg(&self) -> rustc_errors::DiagnosticMessage {
761         fluent::lint_unused_def
762     }
763 }
764
765 #[derive(LintDiagnostic)]
766 #[diag(lint_path_statement_drop)]
767 pub struct PathStatementDrop {
768     #[subdiagnostic]
769     pub sub: PathStatementDropSub,
770 }
771
772 #[derive(Subdiagnostic)]
773 pub enum PathStatementDropSub {
774     #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
775     Suggestion {
776         #[primary_span]
777         span: Span,
778         snippet: String,
779     },
780     #[help(help)]
781     Help {
782         #[primary_span]
783         span: Span,
784     },
785 }
786
787 #[derive(LintDiagnostic)]
788 #[diag(lint_path_statement_no_effect)]
789 pub struct PathStatementNoEffect;
790
791 #[derive(LintDiagnostic)]
792 #[diag(lint_unused_delim)]
793 pub struct UnusedDelim<'a> {
794     pub delim: &'static str,
795     pub item: &'a str,
796     #[subdiagnostic]
797     pub suggestion: Option<UnusedDelimSuggestion>,
798 }
799
800 #[derive(Subdiagnostic)]
801 #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
802 pub struct UnusedDelimSuggestion {
803     #[suggestion_part(code = "{start_replace}")]
804     pub start_span: Span,
805     pub start_replace: &'static str,
806     #[suggestion_part(code = "{end_replace}")]
807     pub end_span: Span,
808     pub end_replace: &'static str,
809 }
810
811 #[derive(LintDiagnostic)]
812 #[diag(lint_unused_import_braces)]
813 pub struct UnusedImportBracesDiag {
814     pub node: Symbol,
815 }
816
817 #[derive(LintDiagnostic)]
818 #[diag(lint_unused_allocation)]
819 pub struct UnusedAllocationDiag;
820
821 #[derive(LintDiagnostic)]
822 #[diag(lint_unused_allocation_mut)]
823 pub struct UnusedAllocationMutDiag;