]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/lints.rs
782cf668b290b98ce2b9acdf0e074e1ce82f76b0
[rust.git] / compiler / rustc_lint / src / lints.rs
1 use std::num::NonZeroU32;
2
3 use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage};
4 use rustc_hir::def_id::DefId;
5 use rustc_macros::{LintDiagnostic, Subdiagnostic};
6 use rustc_middle::{
7     lint::LintExpectation,
8     ty::{Predicate, Ty, TyCtxt},
9 };
10 use rustc_span::{edition::Edition, symbol::Ident, Span, Symbol};
11
12 use crate::{errors::OverruledAttributeSub, LateContext};
13
14 // array_into_iter.rs
15 #[derive(LintDiagnostic)]
16 #[diag(lint_array_into_iter)]
17 pub struct ArrayIntoIterDiag<'a> {
18     pub target: &'a str,
19     #[suggestion(use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
20     pub suggestion: Span,
21     #[subdiagnostic]
22     pub sub: Option<ArrayIntoIterDiagSub>,
23 }
24
25 #[derive(Subdiagnostic)]
26 pub enum ArrayIntoIterDiagSub {
27     #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
28     RemoveIntoIter {
29         #[primary_span]
30         span: Span,
31     },
32     #[multipart_suggestion(use_explicit_into_iter_suggestion, applicability = "maybe-incorrect")]
33     UseExplicitIntoIter {
34         #[suggestion_part(code = "IntoIterator::into_iter(")]
35         start_span: Span,
36         #[suggestion_part(code = ")")]
37         end_span: Span,
38     },
39 }
40
41 // builtin.rs
42 #[derive(LintDiagnostic)]
43 #[diag(lint_builtin_while_true)]
44 pub struct BuiltinWhileTrue {
45     #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")]
46     pub suggestion: Span,
47     pub replace: String,
48 }
49
50 #[derive(LintDiagnostic)]
51 #[diag(lint_builtin_box_pointers)]
52 pub struct BuiltinBoxPointers<'a> {
53     pub ty: Ty<'a>,
54 }
55
56 #[derive(LintDiagnostic)]
57 #[diag(lint_builtin_non_shorthand_field_patterns)]
58 pub struct BuiltinNonShorthandFieldPatterns {
59     pub ident: Ident,
60     #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")]
61     pub suggestion: Span,
62     pub prefix: &'static str,
63 }
64
65 // FIXME: add lint::unsafe_code
66
67 #[derive(LintDiagnostic)]
68 #[diag(lint_builtin_missing_doc)]
69 pub struct BuiltinMissingDoc<'a> {
70     pub article: &'a str,
71     pub desc: &'a str,
72 }
73
74 #[derive(LintDiagnostic)]
75 #[diag(lint_builtin_missing_copy_impl)]
76 pub struct BuiltinMissingCopyImpl;
77
78 pub struct BuiltinMissingDebugImpl<'a> {
79     pub tcx: TyCtxt<'a>,
80     pub def_id: DefId,
81 }
82
83 impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> {
84     fn decorate_lint<'b>(
85         self,
86         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
87     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
88         diag.set_arg("debug", self.tcx.def_path_str(self.def_id));
89         diag
90     }
91
92     fn msg(&self) -> DiagnosticMessage {
93         fluent::lint_builtin_missing_debug_impl
94     }
95 }
96
97 #[derive(LintDiagnostic)]
98 #[diag(lint_builtin_anonymous_params)]
99 pub struct BuiltinAnonymousParams<'a> {
100     #[suggestion(code = "_: {ty_snip}")]
101     pub suggestion: (Span, Applicability),
102     pub ty_snip: &'a str,
103 }
104
105 // FIXME: add lint::builtin_deprecated_attr_link
106
107 #[derive(LintDiagnostic)]
108 #[diag(lint_builtin_deprecated_attr_used)]
109 pub struct BuiltinDeprecatedAttrUsed {
110     pub name: String,
111     #[suggestion(
112         lint_builtin_deprecated_attr_default_suggestion,
113         style = "short",
114         code = "",
115         applicability = "machine-applicable"
116     )]
117     pub suggestion: Span,
118 }
119
120 #[derive(LintDiagnostic)]
121 #[diag(lint_builtin_unused_doc_comment)]
122 pub struct BuiltinUnusedDocComment<'a> {
123     pub kind: &'a str,
124     #[label]
125     pub label: Span,
126     #[subdiagnostic]
127     pub sub: BuiltinUnusedDocCommentSub,
128 }
129
130 #[derive(Subdiagnostic)]
131 pub enum BuiltinUnusedDocCommentSub {
132     #[help(plain_help)]
133     PlainHelp,
134     #[help(block_help)]
135     BlockHelp,
136 }
137
138 #[derive(LintDiagnostic)]
139 #[diag(lint_builtin_no_mangle_generic)]
140 pub struct BuiltinNoMangleGeneric {
141     // Use of `#[no_mangle]` suggests FFI intent; correct
142     // fix may be to monomorphize source by hand
143     #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")]
144     pub suggestion: Span,
145 }
146
147 #[derive(LintDiagnostic)]
148 #[diag(lint_builtin_const_no_mangle)]
149 pub struct BuiltinConstNoMangle {
150     #[suggestion(code = "pub static", applicability = "machine-applicable")]
151     pub suggestion: Span,
152 }
153
154 #[derive(LintDiagnostic)]
155 #[diag(lint_builtin_mutable_transmutes)]
156 pub struct BuiltinMutablesTransmutes;
157
158 #[derive(LintDiagnostic)]
159 #[diag(lint_builtin_unstable_features)]
160 pub struct BuiltinUnstableFeatures;
161
162 #[derive(LintDiagnostic)]
163 #[diag(lint_builtin_unreachable_pub)]
164 pub struct BuiltinUnreachablePub<'a> {
165     pub what: &'a str,
166     #[suggestion(code = "pub(crate)")]
167     pub suggestion: (Span, Applicability),
168     #[help]
169     pub help: Option<()>,
170 }
171
172 // FIXME: migrate builtin_type_alias_where_clause
173
174 // FIXME: migrate builtin_type_alias_generic_bounds
175
176 #[derive(LintDiagnostic)]
177 #[diag(lint_builtin_trivial_bounds)]
178 pub struct BuiltinTrivialBounds<'a> {
179     pub predicate_kind_name: &'a str,
180     pub predicate: Predicate<'a>,
181 }
182
183 #[derive(LintDiagnostic)]
184 pub enum BuiltinEllipsisInclusiveRangePatternsLint {
185     #[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
186     Parenthesise {
187         #[suggestion(code = "{replace}", applicability = "machine-applicable")]
188         suggestion: Span,
189         replace: String,
190     },
191     #[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
192     NonParenthesise {
193         #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")]
194         suggestion: Span,
195     },
196 }
197
198 #[derive(LintDiagnostic)]
199 #[diag(lint_builtin_unnameable_test_items)]
200 pub struct BuiltinUnnameableTestItems;
201
202 #[derive(LintDiagnostic)]
203 #[diag(lint_builtin_keyword_idents)]
204 pub struct BuiltinKeywordIdents {
205     pub kw: Ident,
206     pub next: Edition,
207     #[suggestion(code = "r#{kw}", applicability = "machine-applicable")]
208     pub suggestion: Span,
209 }
210
211 #[derive(LintDiagnostic)]
212 #[diag(lint_builtin_explicit_outlives)]
213 pub struct BuiltinExplicitOutlives {
214     pub count: usize,
215     #[subdiagnostic]
216     pub suggestion: BuiltinExplicitOutlivesSuggestion,
217 }
218
219 #[derive(Subdiagnostic)]
220 #[multipart_suggestion(suggestion)]
221 pub struct BuiltinExplicitOutlivesSuggestion {
222     #[suggestion_part(code = "")]
223     pub spans: Vec<Span>,
224     #[applicability]
225     pub applicability: Applicability,
226 }
227
228 pub struct BuiltinIncompleteFeatures {
229     pub name: Symbol,
230     pub note: Option<NonZeroU32>,
231     pub help: Option<()>,
232 }
233
234 impl<'a> DecorateLint<'a, ()> for BuiltinIncompleteFeatures {
235     fn decorate_lint<'b>(
236         self,
237         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
238     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
239         diag.set_arg("name", self.name);
240         if let Some(n) = self.note {
241             diag.set_arg("n", n);
242             diag.note(fluent::note);
243         }
244         if let Some(_) = self.help {
245             diag.help(fluent::help);
246         }
247         diag
248     }
249
250     fn msg(&self) -> DiagnosticMessage {
251         fluent::lint_builtin_incomplete_features
252     }
253 }
254
255 // FIXME: migrate "the type `{}` does not permit {}"
256
257 // FIXME: fluent::lint::builtin_clashing_extern_{same,diff}_name
258
259 #[derive(LintDiagnostic)]
260 #[diag(lint_builtin_deref_nullptr)]
261 pub struct BuiltinDerefNullptr {
262     #[label]
263     pub label: Span,
264 }
265
266 // FIXME: migrate fluent::lint::builtin_asm_labels
267
268 #[derive(LintDiagnostic)]
269 pub enum BuiltinSpecialModuleNameUsed {
270     #[diag(lint_builtin_special_module_name_used_lib)]
271     #[note]
272     #[help]
273     Lib,
274     #[diag(lint_builtin_special_module_name_used_main)]
275     #[note]
276     Main,
277 }
278
279 #[derive(LintDiagnostic)]
280 #[diag(lint_builtin_unexpected_cli_config_name)]
281 #[help]
282 pub struct BuiltinUnexpectedCliConfigName {
283     pub name: Symbol,
284 }
285
286 #[derive(LintDiagnostic)]
287 #[diag(lint_builtin_unexpected_cli_config_value)]
288 #[help]
289 pub struct BuiltinUnexpectedCliConfigValue {
290     pub name: Symbol,
291     pub value: Symbol,
292 }
293
294 // enum_intrinsics_non_enums.rs
295 #[derive(LintDiagnostic)]
296 #[diag(lint_enum_intrinsics_mem_discriminant)]
297 pub struct EnumIntrinsicsMemDiscriminate<'a> {
298     pub ty_param: Ty<'a>,
299     #[note]
300     pub note: Span,
301 }
302
303 #[derive(LintDiagnostic)]
304 #[diag(lint_enum_intrinsics_mem_variant)]
305 #[note]
306 pub struct EnumIntrinsicsMemVariant<'a> {
307     pub ty_param: Ty<'a>,
308 }
309
310 // expect.rs
311 pub struct Expectation<'a> {
312     pub expectation: &'a LintExpectation,
313 }
314
315 impl<'a> DecorateLint<'a, ()> for Expectation<'_> {
316     fn decorate_lint<'b>(
317         self,
318         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
319     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
320         if let Some(rationale) = self.expectation.reason {
321             diag.note(rationale.as_str());
322         }
323
324         if self.expectation.is_unfulfilled_lint_expectations {
325             diag.note(fluent::note);
326         }
327
328         diag
329     }
330
331     fn msg(&self) -> DiagnosticMessage {
332         fluent::lint_expectation
333     }
334 }
335
336 // internal.rs
337 #[derive(LintDiagnostic)]
338 #[diag(lint_default_hash_types)]
339 #[note]
340 pub struct DefaultHashTypesDiag<'a> {
341     pub preferred: &'a str,
342     pub used: Symbol,
343 }
344
345 #[derive(LintDiagnostic)]
346 #[diag(lint_query_instability)]
347 #[note]
348 pub struct QueryInstability {
349     pub query: Symbol,
350 }
351
352 #[derive(LintDiagnostic)]
353 #[diag(lint_tykind_kind)]
354 pub struct TykindKind {
355     #[suggestion(code = "ty", applicability = "maybe-incorrect")]
356     pub suggestion: Span,
357 }
358
359 #[derive(LintDiagnostic)]
360 #[diag(lint_tykind)]
361 #[help]
362 pub struct TykindDiag;
363
364 #[derive(LintDiagnostic)]
365 #[diag(lint_ty_qualified)]
366 pub struct TyQualified {
367     pub ty: String,
368     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
369     pub suggestion: Span,
370 }
371
372 #[derive(LintDiagnostic)]
373 #[diag(lint_lintpass_by_hand)]
374 #[help]
375 pub struct LintPassByHand;
376
377 #[derive(LintDiagnostic)]
378 #[diag(lint_non_existant_doc_keyword)]
379 #[help]
380 pub struct NonExistantDocKeyword {
381     pub keyword: Symbol,
382 }
383
384 #[derive(LintDiagnostic)]
385 #[diag(lint_diag_out_of_impl)]
386 pub struct DiagOutOfImpl;
387
388 #[derive(LintDiagnostic)]
389 #[diag(lint_untranslatable_diag)]
390 pub struct UntranslatableDiag;
391
392 #[derive(LintDiagnostic)]
393 #[diag(lint_bad_opt_access)]
394 pub struct BadOptAccessDiag<'a> {
395     pub msg: &'a str,
396 }
397
398 // let_underscore.rs
399 #[derive(LintDiagnostic)]
400 pub enum NonBindingLet {
401     #[diag(lint_non_binding_let_on_sync_lock)]
402     SyncLock {
403         #[subdiagnostic]
404         sub: NonBindingLetSub,
405     },
406     #[diag(lint_non_binding_let_on_drop_type)]
407     DropType {
408         #[subdiagnostic]
409         sub: NonBindingLetSub,
410     },
411 }
412
413 pub struct NonBindingLetSub {
414     pub suggestion: Span,
415     pub multi_suggestion_start: Span,
416     pub multi_suggestion_end: Span,
417 }
418
419 impl AddToDiagnostic for NonBindingLetSub {
420     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
421     where
422         F: Fn(
423             &mut rustc_errors::Diagnostic,
424             rustc_errors::SubdiagnosticMessage,
425         ) -> rustc_errors::SubdiagnosticMessage,
426     {
427         diag.span_suggestion_verbose(
428             self.suggestion,
429             fluent::lint_non_binding_let_suggestion,
430             "_unused",
431             Applicability::MachineApplicable,
432         );
433         diag.multipart_suggestion(
434             fluent::lint_non_binding_let_multi_suggestion,
435             vec![
436                 (self.multi_suggestion_start, "drop(".to_string()),
437                 (self.multi_suggestion_end, ")".to_string()),
438             ],
439             Applicability::MachineApplicable,
440         );
441     }
442 }
443
444 // levels.rs
445 #[derive(LintDiagnostic)]
446 #[diag(lint_overruled_attribute)]
447 pub struct OverruledAtributeLint<'a> {
448     #[label]
449     pub overruled: Span,
450     pub lint_level: &'a str,
451     pub lint_source: Symbol,
452     #[subdiagnostic]
453     pub sub: OverruledAttributeSub,
454 }
455
456 #[derive(LintDiagnostic)]
457 #[diag(lint_deprecated_lint_name)]
458 pub struct DeprecatedLintName<'a> {
459     pub name: String,
460     #[suggestion(code = "{replace}", applicability = "machine-applicable")]
461     pub suggestion: Span,
462     pub replace: &'a str,
463 }
464
465 pub struct RenamedOrRemovedLint<'a> {
466     pub msg: &'a str,
467     pub suggestion: Span,
468     pub renamed: &'a Option<String>,
469 }
470
471 impl<'a> DecorateLint<'a, ()> for RenamedOrRemovedLint<'_> {
472     fn decorate_lint<'b>(
473         self,
474         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
475     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
476         if let Some(new_name) = self.renamed {
477             diag.span_suggestion(
478                 self.suggestion,
479                 fluent::lint_renamed_or_removed_lint_suggestion,
480                 new_name,
481                 Applicability::MachineApplicable,
482             );
483         };
484         diag
485     }
486
487     fn msg(&self) -> rustc_errors::DiagnosticMessage {
488         rustc_errors::DiagnosticMessage::Str(self.msg.to_string())
489     }
490 }
491
492 pub struct UnknownLint<'a> {
493     pub name: String,
494     pub suggestion: Span,
495     pub replace: &'a Option<Symbol>,
496 }
497
498 impl<'a> DecorateLint<'a, ()> for UnknownLint<'_> {
499     fn decorate_lint<'b>(
500         self,
501         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
502     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
503         diag.set_arg("name", self.name);
504         if let Some(replace) = self.replace {
505             diag.span_suggestion(
506                 self.suggestion,
507                 fluent::suggestion,
508                 replace,
509                 Applicability::MaybeIncorrect,
510             );
511         };
512         diag
513     }
514
515     fn msg(&self) -> rustc_errors::DiagnosticMessage {
516         fluent::lint_unknown_lint
517     }
518 }
519
520 #[derive(LintDiagnostic)]
521 #[diag(lint_ignored_unless_crate_specified)]
522 pub struct IgnoredUnlessCrateSpecified<'a> {
523     pub level: &'a str,
524     pub name: Symbol,
525 }
526
527 // methods.rs
528 #[derive(LintDiagnostic)]
529 #[diag(lint_cstring_ptr)]
530 #[note]
531 #[help]
532 pub struct CStringPtr {
533     #[label(as_ptr_label)]
534     pub as_ptr: Span,
535     #[label(unwrap_label)]
536     pub unwrap: Span,
537 }
538
539 // non_ascii_idents.rs
540 #[derive(LintDiagnostic)]
541 #[diag(lint_identifier_non_ascii_char)]
542 pub struct IdentifierNonAsciiChar;
543
544 #[derive(LintDiagnostic)]
545 #[diag(lint_identifier_uncommon_codepoints)]
546 pub struct IdentifierUncommonCodepoints;
547
548 #[derive(LintDiagnostic)]
549 #[diag(lint_confusable_identifier_pair)]
550 pub struct ConfusableIdentifierPair {
551     pub existing_sym: Symbol,
552     pub sym: Symbol,
553     #[label]
554     pub label: Span,
555 }
556
557 #[derive(LintDiagnostic)]
558 #[diag(lint_mixed_script_confusables)]
559 #[note(includes_note)]
560 #[note]
561 pub struct MixedScriptConfusables {
562     pub set: String,
563     pub includes: String,
564 }
565
566 // non_fmt_panic.rs
567 pub struct NonFmtPanicUnused {
568     pub count: usize,
569     pub suggestion: Option<Span>,
570 }
571
572 impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
573     fn decorate_lint<'b>(
574         self,
575         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
576     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
577         diag.set_arg("count", self.count);
578         diag.note(fluent::note);
579         if let Some(span) = self.suggestion {
580             diag.span_suggestion(
581                 span.shrink_to_hi(),
582                 fluent::add_args_suggestion,
583                 ", ...",
584                 Applicability::HasPlaceholders,
585             );
586             diag.span_suggestion(
587                 span.shrink_to_lo(),
588                 fluent::add_fmt_suggestion,
589                 "\"{}\", ",
590                 Applicability::MachineApplicable,
591             );
592         }
593         diag
594     }
595
596     fn msg(&self) -> rustc_errors::DiagnosticMessage {
597         fluent::lint_non_fmt_panic_unused
598     }
599 }
600
601 #[derive(LintDiagnostic)]
602 #[diag(lint_non_fmt_panic_braces)]
603 #[note]
604 pub struct NonFmtPanicBraces {
605     pub count: usize,
606     #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
607     pub suggestion: Option<Span>,
608 }
609
610 // nonstandard_style.rs
611 #[derive(LintDiagnostic)]
612 #[diag(lint_non_camel_case_type)]
613 pub struct NonCamelCaseType<'a> {
614     pub sort: &'a str,
615     pub name: &'a str,
616     #[subdiagnostic]
617     pub sub: NonCamelCaseTypeSub,
618 }
619
620 #[derive(Subdiagnostic)]
621 pub enum NonCamelCaseTypeSub {
622     #[label(label)]
623     Label {
624         #[primary_span]
625         span: Span,
626     },
627     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
628     Suggestion {
629         #[primary_span]
630         span: Span,
631         replace: String,
632     },
633 }
634
635 #[derive(LintDiagnostic)]
636 #[diag(lint_non_snake_case)]
637 pub struct NonSnakeCaseDiag<'a> {
638     pub sort: &'a str,
639     pub name: &'a str,
640     pub sc: String,
641     #[subdiagnostic]
642     pub sub: NonSnakeCaseDiagSub,
643 }
644
645 pub enum NonSnakeCaseDiagSub {
646     Label { span: Span },
647     Help,
648     RenameOrConvertSuggestion { span: Span, suggestion: Ident },
649     ConvertSuggestion { span: Span, suggestion: String },
650     SuggestionAndNote { span: Span },
651 }
652
653 impl AddToDiagnostic for NonSnakeCaseDiagSub {
654     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
655     where
656         F: Fn(
657             &mut rustc_errors::Diagnostic,
658             rustc_errors::SubdiagnosticMessage,
659         ) -> rustc_errors::SubdiagnosticMessage,
660     {
661         match self {
662             NonSnakeCaseDiagSub::Label { span } => {
663                 diag.span_label(span, fluent::label);
664             }
665             NonSnakeCaseDiagSub::Help => {
666                 diag.help(fluent::help);
667             }
668             NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
669                 diag.span_suggestion(
670                     span,
671                     fluent::convert_suggestion,
672                     suggestion,
673                     Applicability::MaybeIncorrect,
674                 );
675             }
676             NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
677                 diag.span_suggestion(
678                     span,
679                     fluent::rename_or_convert_suggestion,
680                     suggestion,
681                     Applicability::MaybeIncorrect,
682                 );
683             }
684             NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
685                 diag.note(fluent::cannot_convert_note);
686                 diag.span_suggestion(
687                     span,
688                     fluent::rename_suggestion,
689                     "",
690                     Applicability::MaybeIncorrect,
691                 );
692             }
693         }
694     }
695 }
696
697 #[derive(LintDiagnostic)]
698 #[diag(lint_non_upper_case_global)]
699 pub struct NonUpperCaseGlobal<'a> {
700     pub sort: &'a str,
701     pub name: &'a str,
702     #[subdiagnostic]
703     pub sub: NonUpperCaseGlobalSub,
704 }
705
706 #[derive(Subdiagnostic)]
707 pub enum NonUpperCaseGlobalSub {
708     #[label(label)]
709     Label {
710         #[primary_span]
711         span: Span,
712     },
713     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
714     Suggestion {
715         #[primary_span]
716         span: Span,
717         replace: String,
718     },
719 }
720
721 // noop_method_call.rs
722 #[derive(LintDiagnostic)]
723 #[diag(lint_noop_method_call)]
724 #[note]
725 pub struct NoopMethodCallDiag<'a> {
726     pub method: Symbol,
727     pub receiver_ty: Ty<'a>,
728     #[label]
729     pub label: Span,
730 }
731
732 // pass_by_value.rs
733 #[derive(LintDiagnostic)]
734 #[diag(lint_pass_by_value)]
735 pub struct PassByValueDiag {
736     pub ty: String,
737     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
738     pub suggestion: Span,
739 }
740
741 // redundant_semicolon.rs
742 #[derive(LintDiagnostic)]
743 #[diag(lint_redundant_semicolons)]
744 pub struct RedundantSemicolonsDiag {
745     pub multiple: bool,
746     #[suggestion(code = "", applicability = "maybe-incorrect")]
747     pub suggestion: Span,
748 }
749
750 // traits.rs
751 pub struct DropTraitConstraintsDiag<'a> {
752     pub predicate: Predicate<'a>,
753     pub tcx: TyCtxt<'a>,
754     pub def_id: DefId,
755 }
756
757 impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> {
758     fn decorate_lint<'b>(
759         self,
760         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
761     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
762         diag.set_arg("predicate", self.predicate);
763         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id))
764     }
765
766     fn msg(&self) -> rustc_errors::DiagnosticMessage {
767         fluent::lint_drop_trait_constraints
768     }
769 }
770
771 pub struct DropGlue<'a> {
772     pub tcx: TyCtxt<'a>,
773     pub def_id: DefId,
774 }
775
776 impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
777     fn decorate_lint<'b>(
778         self,
779         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
780     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
781         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id))
782     }
783
784     fn msg(&self) -> rustc_errors::DiagnosticMessage {
785         fluent::lint_drop_glue
786     }
787 }
788
789 // types.rs
790 #[derive(LintDiagnostic)]
791 #[diag(lint_range_endpoint_out_of_range)]
792 pub struct RangeEndpointOutOfRange<'a> {
793     pub ty: &'a str,
794     #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
795     pub suggestion: Span,
796     pub start: String,
797     pub literal: u128,
798     pub suffix: &'a str,
799 }
800
801 #[derive(LintDiagnostic)]
802 #[diag(lint_overflowing_bin_hex)]
803 pub struct OverflowingBinHex<'a> {
804     pub ty: &'a str,
805     pub lit: String,
806     pub dec: u128,
807     pub actually: String,
808     #[subdiagnostic]
809     pub sign: OverflowingBinHexSign,
810     #[subdiagnostic]
811     pub sub: Option<OverflowingBinHexSub<'a>>,
812 }
813
814 pub enum OverflowingBinHexSign {
815     Positive,
816     Negative,
817 }
818
819 impl AddToDiagnostic for OverflowingBinHexSign {
820     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
821     where
822         F: Fn(
823             &mut rustc_errors::Diagnostic,
824             rustc_errors::SubdiagnosticMessage,
825         ) -> rustc_errors::SubdiagnosticMessage,
826     {
827         match self {
828             OverflowingBinHexSign::Positive => {
829                 diag.note(fluent::positive_note);
830             }
831             OverflowingBinHexSign::Negative => {
832                 diag.note(fluent::negative_note);
833                 diag.note(fluent::negative_becomes_note);
834             }
835         }
836     }
837 }
838
839 #[derive(Subdiagnostic)]
840 pub enum OverflowingBinHexSub<'a> {
841     #[suggestion(
842         suggestion,
843         code = "{sans_suffix}{suggestion_ty}",
844         applicability = "machine-applicable"
845     )]
846     Suggestion {
847         #[primary_span]
848         span: Span,
849         suggestion_ty: &'a str,
850         sans_suffix: &'a str,
851     },
852     #[help(help)]
853     Help { suggestion_ty: &'a str },
854 }
855
856 pub struct OverflowingInt<'a> {
857     pub ty: &'a str,
858     pub lit: String,
859     pub min: i128,
860     pub max: u128,
861     pub suggestion_ty: Option<&'a str>,
862 }
863
864 // FIXME: refactor with `Option<&'a str>` in macro
865 impl<'a> DecorateLint<'a, ()> for OverflowingInt<'_> {
866     fn decorate_lint<'b>(
867         self,
868         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
869     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
870         diag.set_arg("ty", self.ty);
871         diag.set_arg("lit", self.lit);
872         diag.set_arg("min", self.min);
873         diag.set_arg("max", self.max);
874         diag.note(fluent::note);
875         if let Some(suggestion_ty) = self.suggestion_ty {
876             diag.set_arg("suggestion_ty", suggestion_ty);
877             diag.help(fluent::help);
878         }
879         diag
880     }
881
882     fn msg(&self) -> rustc_errors::DiagnosticMessage {
883         fluent::lint_overflowing_int
884     }
885 }
886
887 #[derive(LintDiagnostic)]
888 #[diag(lint_only_cast_u8_to_char)]
889 pub struct OnlyCastu8ToChar {
890     #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
891     pub span: Span,
892     pub literal: u128,
893 }
894
895 #[derive(LintDiagnostic)]
896 #[diag(lint_overflowing_uint)]
897 #[note]
898 pub struct OverflowingUInt<'a> {
899     pub ty: &'a str,
900     pub lit: String,
901     pub min: u128,
902     pub max: u128,
903 }
904
905 #[derive(LintDiagnostic)]
906 #[diag(lint_overflowing_literal)]
907 #[note]
908 pub struct OverflowingLiteral<'a> {
909     pub ty: &'a str,
910     pub lit: String,
911 }
912
913 #[derive(LintDiagnostic)]
914 #[diag(lint_unused_comparisons)]
915 pub struct UnusedComparisons;
916
917 pub struct ImproperCTypes<'a> {
918     pub ty: Ty<'a>,
919     pub desc: &'a str,
920     pub label: Span,
921     pub help: Option<DiagnosticMessage>,
922     pub note: DiagnosticMessage,
923     pub span_note: Option<Span>,
924 }
925
926 impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
927     fn decorate_lint<'b>(
928         self,
929         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
930     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
931         diag.set_arg("ty", self.ty);
932         diag.set_arg("desc", self.desc);
933         diag.span_label(self.label, fluent::label);
934         if let Some(help) = self.help {
935             diag.help(help);
936         }
937         diag.note(self.note);
938         if let Some(note) = self.span_note {
939             diag.span_note(note, fluent::note);
940         }
941         diag
942     }
943
944     fn msg(&self) -> rustc_errors::DiagnosticMessage {
945         fluent::lint_improper_ctypes
946     }
947 }
948
949 #[derive(LintDiagnostic)]
950 #[diag(lint_variant_size_differences)]
951 pub struct VariantSizeDifferencesDiag {
952     pub largest: u64,
953 }
954
955 #[derive(LintDiagnostic)]
956 #[diag(lint_atomic_ordering_load)]
957 #[help]
958 pub struct AtomicOrderingLoad;
959
960 #[derive(LintDiagnostic)]
961 #[diag(lint_atomic_ordering_store)]
962 #[help]
963 pub struct AtomicOrderingStore;
964
965 #[derive(LintDiagnostic)]
966 #[diag(lint_atomic_ordering_fence)]
967 #[help]
968 pub struct AtomicOrderingFence;
969
970 #[derive(LintDiagnostic)]
971 #[diag(lint_atomic_ordering_invalid)]
972 #[help]
973 pub struct InvalidAtomicOrderingDiag {
974     pub method: Symbol,
975     #[label]
976     pub fail_order_arg_span: Span,
977 }
978
979 // unused.rs
980 #[derive(LintDiagnostic)]
981 #[diag(lint_unused_op)]
982 pub struct UnusedOp<'a> {
983     pub op: &'a str,
984     #[label]
985     pub label: Span,
986     #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")]
987     pub suggestion: Span,
988 }
989
990 #[derive(LintDiagnostic)]
991 #[diag(lint_unused_result)]
992 pub struct UnusedResult<'a> {
993     pub ty: Ty<'a>,
994 }
995
996 // FIXME(davidtwco): this isn't properly translatable becauses of the
997 // pre/post strings
998 #[derive(LintDiagnostic)]
999 #[diag(lint_unused_closure)]
1000 #[note]
1001 pub struct UnusedClosure<'a> {
1002     pub count: usize,
1003     pub pre: &'a str,
1004     pub post: &'a str,
1005 }
1006
1007 // FIXME(davidtwco): this isn't properly translatable becauses of the
1008 // pre/post strings
1009 #[derive(LintDiagnostic)]
1010 #[diag(lint_unused_generator)]
1011 #[note]
1012 pub struct UnusedGenerator<'a> {
1013     pub count: usize,
1014     pub pre: &'a str,
1015     pub post: &'a str,
1016 }
1017
1018 // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
1019 // strings
1020 pub struct UnusedDef<'a, 'b> {
1021     pub pre: &'a str,
1022     pub post: &'a str,
1023     pub cx: &'a LateContext<'b>,
1024     pub def_id: DefId,
1025     pub note: Option<Symbol>,
1026 }
1027
1028 // FIXME: refactor with `Option<String>` in macro
1029 impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
1030     fn decorate_lint<'b>(
1031         self,
1032         diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
1033     ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
1034         diag.set_arg("pre", self.pre);
1035         diag.set_arg("post", self.post);
1036         diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
1037         // check for #[must_use = "..."]
1038         if let Some(note) = self.note {
1039             diag.note(note.as_str());
1040         }
1041         diag
1042     }
1043
1044     fn msg(&self) -> rustc_errors::DiagnosticMessage {
1045         fluent::lint_unused_def
1046     }
1047 }
1048
1049 #[derive(LintDiagnostic)]
1050 #[diag(lint_path_statement_drop)]
1051 pub struct PathStatementDrop {
1052     #[subdiagnostic]
1053     pub sub: PathStatementDropSub,
1054 }
1055
1056 #[derive(Subdiagnostic)]
1057 pub enum PathStatementDropSub {
1058     #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
1059     Suggestion {
1060         #[primary_span]
1061         span: Span,
1062         snippet: String,
1063     },
1064     #[help(help)]
1065     Help {
1066         #[primary_span]
1067         span: Span,
1068     },
1069 }
1070
1071 #[derive(LintDiagnostic)]
1072 #[diag(lint_path_statement_no_effect)]
1073 pub struct PathStatementNoEffect;
1074
1075 #[derive(LintDiagnostic)]
1076 #[diag(lint_unused_delim)]
1077 pub struct UnusedDelim<'a> {
1078     pub delim: &'static str,
1079     pub item: &'a str,
1080     #[subdiagnostic]
1081     pub suggestion: Option<UnusedDelimSuggestion>,
1082 }
1083
1084 #[derive(Subdiagnostic)]
1085 #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
1086 pub struct UnusedDelimSuggestion {
1087     #[suggestion_part(code = "{start_replace}")]
1088     pub start_span: Span,
1089     pub start_replace: &'static str,
1090     #[suggestion_part(code = "{end_replace}")]
1091     pub end_span: Span,
1092     pub end_replace: &'static str,
1093 }
1094
1095 #[derive(LintDiagnostic)]
1096 #[diag(lint_unused_import_braces)]
1097 pub struct UnusedImportBracesDiag {
1098     pub node: Symbol,
1099 }
1100
1101 #[derive(LintDiagnostic)]
1102 #[diag(lint_unused_allocation)]
1103 pub struct UnusedAllocationDiag;
1104
1105 #[derive(LintDiagnostic)]
1106 #[diag(lint_unused_allocation_mut)]
1107 pub struct UnusedAllocationMutDiag;