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};
7 use crate::{errors::OverruledAttributeSub, LateContext};
10 #[derive(LintDiagnostic)]
11 #[diag(lint_array_into_iter)]
12 pub struct ArrayIntoIterDiag<'a> {
14 #[suggestion(use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
17 pub sub: Option<ArrayIntoIterDiagSub>,
20 #[derive(Subdiagnostic)]
21 pub enum ArrayIntoIterDiagSub {
22 #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
27 #[multipart_suggestion(use_explicit_into_iter_suggestion, applicability = "maybe-incorrect")]
29 #[suggestion_part(code = "IntoIterator::into_iter(")]
31 #[suggestion_part(code = ")")]
36 // enum_intrinsics_non_enums.rs
37 #[derive(LintDiagnostic)]
38 #[diag(lint_enum_intrinsics_mem_discriminant)]
39 pub struct EnumIntrinsicsMemDiscriminate<'a> {
45 #[derive(LintDiagnostic)]
46 #[diag(lint_enum_intrinsics_mem_variant)]
48 pub struct EnumIntrinsicsMemVariant<'a> {
53 #[derive(LintDiagnostic)]
54 #[diag(lint_default_hash_types)]
56 pub struct DefaultHashTypesDiag<'a> {
57 pub preferred: &'a str,
61 #[derive(LintDiagnostic)]
62 #[diag(lint_query_instability)]
64 pub struct QueryInstability {
68 #[derive(LintDiagnostic)]
69 #[diag(lint_tykind_kind)]
70 pub struct TykindKind {
71 #[suggestion(code = "ty", applicability = "maybe-incorrect")]
75 #[derive(LintDiagnostic)]
78 pub struct TykindDiag;
80 #[derive(LintDiagnostic)]
81 #[diag(lint_ty_qualified)]
82 pub struct TyQualified {
84 #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
88 #[derive(LintDiagnostic)]
89 #[diag(lint_lintpass_by_hand)]
91 pub struct LintPassByHand;
93 #[derive(LintDiagnostic)]
94 #[diag(lint_non_existant_doc_keyword)]
96 pub struct NonExistantDocKeyword {
100 #[derive(LintDiagnostic)]
101 #[diag(lint_diag_out_of_impl)]
102 pub struct DiagOutOfImpl;
104 #[derive(LintDiagnostic)]
105 #[diag(lint_untranslatable_diag)]
106 pub struct UntranslatableDiag;
108 #[derive(LintDiagnostic)]
109 #[diag(lint_bad_opt_access)]
110 pub struct BadOptAccessDiag<'a> {
115 #[derive(LintDiagnostic)]
116 pub enum NonBindingLet {
117 #[diag(lint_non_binding_let_on_sync_lock)]
120 sub: NonBindingLetSub,
122 #[diag(lint_non_binding_let_on_drop_type)]
125 sub: NonBindingLetSub,
129 pub struct NonBindingLetSub {
130 pub suggestion: Span,
131 pub multi_suggestion_start: Span,
132 pub multi_suggestion_end: Span,
135 impl AddToDiagnostic for NonBindingLetSub {
136 fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
139 &mut rustc_errors::Diagnostic,
140 rustc_errors::SubdiagnosticMessage,
141 ) -> rustc_errors::SubdiagnosticMessage,
143 diag.span_suggestion_verbose(
145 fluent::lint_non_binding_let_suggestion,
147 Applicability::MachineApplicable,
149 diag.multipart_suggestion(
150 fluent::lint_non_binding_let_multi_suggestion,
152 (self.multi_suggestion_start, "drop(".to_string()),
153 (self.multi_suggestion_end, ")".to_string()),
155 Applicability::MachineApplicable,
161 #[derive(LintDiagnostic)]
162 #[diag(lint_overruled_attribute)]
163 pub struct OverruledAtributeLint<'a> {
166 pub lint_level: &'a str,
167 pub lint_source: Symbol,
169 pub sub: OverruledAttributeSub,
172 #[derive(LintDiagnostic)]
173 #[diag(lint_deprecated_lint_name)]
174 pub struct DeprecatedLintName<'a> {
176 #[suggestion(code = "{replace}", applicability = "machine-applicable")]
177 pub suggestion: Span,
178 pub replace: &'a str,
181 pub struct RenamedOrRemovedLint<'a> {
183 pub suggestion: Span,
184 pub renamed: &'a Option<String>,
187 impl<'a> DecorateLint<'a, ()> for RenamedOrRemovedLint<'_> {
188 fn decorate_lint<'b>(
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(
195 fluent::lint_renamed_or_removed_lint_suggestion,
197 Applicability::MachineApplicable,
203 fn msg(&self) -> rustc_errors::DiagnosticMessage {
204 rustc_errors::DiagnosticMessage::Str(self.msg.to_string())
208 pub struct UnknownLint<'a> {
210 pub suggestion: Span,
211 pub replace: &'a Option<Symbol>,
214 impl<'a> DecorateLint<'a, ()> for UnknownLint<'_> {
215 fn decorate_lint<'b>(
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(
225 Applicability::MaybeIncorrect,
231 fn msg(&self) -> rustc_errors::DiagnosticMessage {
232 fluent::lint_unknown_lint
236 #[derive(LintDiagnostic)]
237 #[diag(lint_ignored_unless_crate_specified)]
238 pub struct IgnoredUnlessCrateSpecified<'a> {
244 #[derive(LintDiagnostic)]
245 #[diag(lint_cstring_ptr)]
248 pub struct CStringPtr {
249 #[label(as_ptr_label)]
251 #[label(unwrap_label)]
255 // non_ascii_idents.rs
256 #[derive(LintDiagnostic)]
257 #[diag(lint_identifier_non_ascii_char)]
258 pub struct IdentifierNonAsciiChar;
260 #[derive(LintDiagnostic)]
261 #[diag(lint_identifier_uncommon_codepoints)]
262 pub struct IdentifierUncommonCodepoints;
264 #[derive(LintDiagnostic)]
265 #[diag(lint_confusable_identifier_pair)]
266 pub struct ConfusableIdentifierPair {
267 pub existing_sym: Symbol,
273 #[derive(LintDiagnostic)]
274 #[diag(lint_mixed_script_confusables)]
275 #[note(includes_note)]
277 pub struct MixedScriptConfusables {
279 pub includes: String,
283 pub struct NonFmtPanicUnused {
285 pub suggestion: Option<Span>,
288 impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
289 fn decorate_lint<'b>(
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(
298 fluent::add_args_suggestion,
300 Applicability::HasPlaceholders,
302 diag.span_suggestion(
304 fluent::add_fmt_suggestion,
306 Applicability::MachineApplicable,
312 fn msg(&self) -> rustc_errors::DiagnosticMessage {
313 fluent::lint_non_fmt_panic_unused
317 #[derive(LintDiagnostic)]
318 #[diag(lint_non_fmt_panic_braces)]
320 pub struct NonFmtPanicBraces {
322 #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
323 pub suggestion: Option<Span>,
326 // nonstandard_style.rs
327 #[derive(LintDiagnostic)]
328 #[diag(lint_non_camel_case_type)]
329 pub struct NonCamelCaseType<'a> {
333 pub sub: NonCamelCaseTypeSub,
336 #[derive(Subdiagnostic)]
337 pub enum NonCamelCaseTypeSub {
343 #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
351 #[derive(LintDiagnostic)]
352 #[diag(lint_non_snake_case)]
353 pub struct NonSnakeCaseDiag<'a> {
358 pub sub: NonSnakeCaseDiagSub,
361 pub enum NonSnakeCaseDiagSub {
362 Label { span: Span },
364 RenameOrConvertSuggestion { span: Span, suggestion: Ident },
365 ConvertSuggestion { span: Span, suggestion: String },
366 SuggestionAndNote { span: Span },
369 impl AddToDiagnostic for NonSnakeCaseDiagSub {
370 fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
373 &mut rustc_errors::Diagnostic,
374 rustc_errors::SubdiagnosticMessage,
375 ) -> rustc_errors::SubdiagnosticMessage,
378 NonSnakeCaseDiagSub::Label { span } => {
379 diag.span_label(span, fluent::label);
381 NonSnakeCaseDiagSub::Help => {
382 diag.help(fluent::help);
384 NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
385 diag.span_suggestion(
387 fluent::convert_suggestion,
389 Applicability::MaybeIncorrect,
392 NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
393 diag.span_suggestion(
395 fluent::rename_or_convert_suggestion,
397 Applicability::MaybeIncorrect,
400 NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
401 diag.note(fluent::cannot_convert_note);
402 diag.span_suggestion(
404 fluent::rename_suggestion,
406 Applicability::MaybeIncorrect,
413 #[derive(LintDiagnostic)]
414 #[diag(lint_non_upper_case_global)]
415 pub struct NonUpperCaseGlobal<'a> {
419 pub sub: NonUpperCaseGlobalSub,
422 #[derive(Subdiagnostic)]
423 pub enum NonUpperCaseGlobalSub {
429 #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
437 // noop_method_call.rs
438 #[derive(LintDiagnostic)]
439 #[diag(lint_noop_method_call)]
441 pub struct NoopMethodCallDiag<'a> {
443 pub receiver_ty: Ty<'a>,
449 #[derive(LintDiagnostic)]
450 #[diag(lint_pass_by_value)]
451 pub struct PassByValueDiag {
453 #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
454 pub suggestion: Span,
457 // redundant_semicolon.rs
458 #[derive(LintDiagnostic)]
459 #[diag(lint_redundant_semicolons)]
460 pub struct RedundantSemicolonsDiag {
462 #[suggestion(code = "", applicability = "maybe-incorrect")]
463 pub suggestion: Span,
467 pub struct DropTraitConstraintsDiag<'a> {
468 pub predicate: Predicate<'a>,
473 impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> {
474 fn decorate_lint<'b>(
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))
482 fn msg(&self) -> rustc_errors::DiagnosticMessage {
483 fluent::lint_drop_trait_constraints
487 pub struct DropGlue<'a> {
492 impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
493 fn decorate_lint<'b>(
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))
500 fn msg(&self) -> rustc_errors::DiagnosticMessage {
501 fluent::lint_drop_glue
506 #[derive(LintDiagnostic)]
507 #[diag(lint_range_endpoint_out_of_range)]
508 pub struct RangeEndpointOutOfRange<'a> {
510 #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
511 pub suggestion: Span,
517 #[derive(LintDiagnostic)]
518 #[diag(lint_overflowing_bin_hex)]
519 pub struct OverflowingBinHex<'a> {
523 pub actually: String,
525 pub sign: OverflowingBinHexSign,
527 pub sub: Option<OverflowingBinHexSub<'a>>,
530 pub enum OverflowingBinHexSign {
535 impl AddToDiagnostic for OverflowingBinHexSign {
536 fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
539 &mut rustc_errors::Diagnostic,
540 rustc_errors::SubdiagnosticMessage,
541 ) -> rustc_errors::SubdiagnosticMessage,
544 OverflowingBinHexSign::Positive => {
545 diag.note(fluent::positive_note);
547 OverflowingBinHexSign::Negative => {
548 diag.note(fluent::negative_note);
549 diag.note(fluent::negative_becomes_note);
555 #[derive(Subdiagnostic)]
556 pub enum OverflowingBinHexSub<'a> {
559 code = "{sans_suffix}{suggestion_ty}",
560 applicability = "machine-applicable"
565 suggestion_ty: &'a str,
566 sans_suffix: &'a str,
569 Help { suggestion_ty: &'a str },
572 pub struct OverflowingInt<'a> {
577 pub suggestion_ty: Option<&'a str>,
580 // FIXME: refactor with `Option<&'a str>` in macro
581 impl<'a> DecorateLint<'a, ()> for OverflowingInt<'_> {
582 fn decorate_lint<'b>(
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);
598 fn msg(&self) -> rustc_errors::DiagnosticMessage {
599 fluent::lint_overflowing_int
603 #[derive(LintDiagnostic)]
604 #[diag(lint_only_cast_u8_to_char)]
605 pub struct OnlyCastu8ToChar {
606 #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
611 #[derive(LintDiagnostic)]
612 #[diag(lint_overflowing_uint)]
614 pub struct OverflowingUInt<'a> {
621 #[derive(LintDiagnostic)]
622 #[diag(lint_overflowing_literal)]
624 pub struct OverflowingLiteral<'a> {
629 #[derive(LintDiagnostic)]
630 #[diag(lint_unused_comparisons)]
631 pub struct UnusedComparisons;
633 pub struct ImproperCTypes<'a> {
637 pub help: Option<DiagnosticMessage>,
638 pub note: DiagnosticMessage,
639 pub span_note: Option<Span>,
642 impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
643 fn decorate_lint<'b>(
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 {
653 diag.note(self.note);
654 if let Some(note) = self.span_note {
655 diag.span_note(note, fluent::note);
660 fn msg(&self) -> rustc_errors::DiagnosticMessage {
661 fluent::lint_improper_ctypes
665 #[derive(LintDiagnostic)]
666 #[diag(lint_variant_size_differences)]
667 pub struct VariantSizeDifferencesDiag {
671 #[derive(LintDiagnostic)]
672 #[diag(lint_atomic_ordering_load)]
674 pub struct AtomicOrderingLoad;
676 #[derive(LintDiagnostic)]
677 #[diag(lint_atomic_ordering_store)]
679 pub struct AtomicOrderingStore;
681 #[derive(LintDiagnostic)]
682 #[diag(lint_atomic_ordering_fence)]
684 pub struct AtomicOrderingFence;
686 #[derive(LintDiagnostic)]
687 #[diag(lint_atomic_ordering_invalid)]
689 pub struct InvalidAtomicOrderingDiag {
692 pub fail_order_arg_span: Span,
696 #[derive(LintDiagnostic)]
697 #[diag(lint_unused_op)]
698 pub struct UnusedOp<'a> {
702 #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")]
703 pub suggestion: Span,
706 #[derive(LintDiagnostic)]
707 #[diag(lint_unused_result)]
708 pub struct UnusedResult<'a> {
712 // FIXME(davidtwco): this isn't properly translatable becauses of the
714 #[derive(LintDiagnostic)]
715 #[diag(lint_unused_closure)]
717 pub struct UnusedClosure<'a> {
723 // FIXME(davidtwco): this isn't properly translatable becauses of the
725 #[derive(LintDiagnostic)]
726 #[diag(lint_unused_generator)]
728 pub struct UnusedGenerator<'a> {
734 // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
736 pub struct UnusedDef<'a, 'b> {
739 pub cx: &'a LateContext<'b>,
741 pub note: Option<Symbol>,
744 // FIXME: refactor with `Option<String>` in macro
745 impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
746 fn decorate_lint<'b>(
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());
760 fn msg(&self) -> rustc_errors::DiagnosticMessage {
761 fluent::lint_unused_def
765 #[derive(LintDiagnostic)]
766 #[diag(lint_path_statement_drop)]
767 pub struct PathStatementDrop {
769 pub sub: PathStatementDropSub,
772 #[derive(Subdiagnostic)]
773 pub enum PathStatementDropSub {
774 #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
787 #[derive(LintDiagnostic)]
788 #[diag(lint_path_statement_no_effect)]
789 pub struct PathStatementNoEffect;
791 #[derive(LintDiagnostic)]
792 #[diag(lint_unused_delim)]
793 pub struct UnusedDelim<'a> {
794 pub delim: &'static str,
797 pub suggestion: Option<UnusedDelimSuggestion>,
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}")]
808 pub end_replace: &'static str,
811 #[derive(LintDiagnostic)]
812 #[diag(lint_unused_import_braces)]
813 pub struct UnusedImportBracesDiag {
817 #[derive(LintDiagnostic)]
818 #[diag(lint_unused_allocation)]
819 pub struct UnusedAllocationDiag;
821 #[derive(LintDiagnostic)]
822 #[diag(lint_unused_allocation_mut)]
823 pub struct UnusedAllocationMutDiag;