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 pub enum NonBindingLet {
55 #[diag(lint_non_binding_let_on_sync_lock)]
58 sub: NonBindingLetSub,
60 #[diag(lint_non_binding_let_on_drop_type)]
63 sub: NonBindingLetSub,
67 pub struct NonBindingLetSub {
69 pub multi_suggestion_start: Span,
70 pub multi_suggestion_end: Span,
73 impl AddToDiagnostic for NonBindingLetSub {
74 fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
77 &mut rustc_errors::Diagnostic,
78 rustc_errors::SubdiagnosticMessage,
79 ) -> rustc_errors::SubdiagnosticMessage,
81 diag.span_suggestion_verbose(
83 fluent::lint_non_binding_let_suggestion,
85 Applicability::MachineApplicable,
87 diag.multipart_suggestion(
88 fluent::lint_non_binding_let_multi_suggestion,
90 (self.multi_suggestion_start, "drop(".to_string()),
91 (self.multi_suggestion_end, ")".to_string()),
93 Applicability::MachineApplicable,
99 #[derive(LintDiagnostic)]
100 #[diag(lint_overruled_attribute)]
101 pub struct OverruledAtributeLint<'a> {
104 pub lint_level: &'a str,
105 pub lint_source: Symbol,
107 pub sub: OverruledAttributeSub,
110 #[derive(LintDiagnostic)]
111 #[diag(lint_deprecated_lint_name)]
112 pub struct DeprecatedLintName<'a> {
114 #[suggestion(code = "{replace}", applicability = "machine-applicable")]
115 pub suggestion: Span,
116 pub replace: &'a str,
119 pub struct RenamedOrRemovedLint<'a> {
121 pub suggestion: Span,
122 pub renamed: &'a Option<String>,
125 impl<'a> DecorateLint<'a, ()> for RenamedOrRemovedLint<'_> {
126 fn decorate_lint<'b>(
128 diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
129 ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
130 if let Some(new_name) = self.renamed {
131 diag.span_suggestion(
133 fluent::lint_renamed_or_removed_lint_suggestion,
135 Applicability::MachineApplicable,
141 fn msg(&self) -> rustc_errors::DiagnosticMessage {
142 rustc_errors::DiagnosticMessage::Str(self.msg.to_string())
146 pub struct UnknownLint<'a> {
148 pub suggestion: Span,
149 pub replace: &'a Option<Symbol>,
152 impl<'a> DecorateLint<'a, ()> for UnknownLint<'_> {
153 fn decorate_lint<'b>(
155 diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
156 ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
157 diag.set_arg("name", self.name);
158 if let Some(replace) = self.replace {
159 diag.span_suggestion(
163 Applicability::MaybeIncorrect,
169 fn msg(&self) -> rustc_errors::DiagnosticMessage {
170 fluent::lint_unknown_lint
174 #[derive(LintDiagnostic)]
175 #[diag(lint_ignored_unless_crate_specified)]
176 pub struct IgnoredUnlessCrateSpecified<'a> {
182 #[derive(LintDiagnostic)]
183 #[diag(lint_cstring_ptr)]
186 pub struct CStringPtr {
187 #[label(as_ptr_label)]
189 #[label(unwrap_label)]
193 // non_ascii_idents.rs
194 #[derive(LintDiagnostic)]
195 #[diag(lint_identifier_non_ascii_char)]
196 pub struct IdentifierNonAsciiChar;
198 #[derive(LintDiagnostic)]
199 #[diag(lint_identifier_uncommon_codepoints)]
200 pub struct IdentifierUncommonCodepoints;
202 #[derive(LintDiagnostic)]
203 #[diag(lint_confusable_identifier_pair)]
204 pub struct ConfusableIdentifierPair {
205 pub existing_sym: Symbol,
211 #[derive(LintDiagnostic)]
212 #[diag(lint_mixed_script_confusables)]
213 #[note(includes_note)]
215 pub struct MixedScriptConfusables {
217 pub includes: String,
221 pub struct NonFmtPanicUnused {
223 pub suggestion: Option<Span>,
226 impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
227 fn decorate_lint<'b>(
229 diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
230 ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
231 diag.set_arg("count", self.count);
232 diag.note(fluent::note);
233 if let Some(span) = self.suggestion {
234 diag.span_suggestion(
236 fluent::add_args_suggestion,
238 Applicability::HasPlaceholders,
240 diag.span_suggestion(
242 fluent::add_fmt_suggestion,
244 Applicability::MachineApplicable,
250 fn msg(&self) -> rustc_errors::DiagnosticMessage {
251 fluent::lint_non_fmt_panic_unused
255 #[derive(LintDiagnostic)]
256 #[diag(lint_non_fmt_panic_braces)]
258 pub struct NonFmtPanicBraces {
260 #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
261 pub suggestion: Option<Span>,
264 // nonstandard_style.rs
265 #[derive(LintDiagnostic)]
266 #[diag(lint_non_camel_case_type)]
267 pub struct NonCamelCaseType<'a> {
271 pub sub: NonCamelCaseTypeSub,
274 #[derive(Subdiagnostic)]
275 pub enum NonCamelCaseTypeSub {
281 #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
289 #[derive(LintDiagnostic)]
290 #[diag(lint_non_snake_case)]
291 pub struct NonSnakeCaseDiag<'a> {
296 pub sub: NonSnakeCaseDiagSub,
299 pub enum NonSnakeCaseDiagSub {
300 Label { span: Span },
302 RenameOrConvertSuggestion { span: Span, suggestion: Ident },
303 ConvertSuggestion { span: Span, suggestion: String },
304 SuggestionAndNote { span: Span },
307 impl AddToDiagnostic for NonSnakeCaseDiagSub {
308 fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
311 &mut rustc_errors::Diagnostic,
312 rustc_errors::SubdiagnosticMessage,
313 ) -> rustc_errors::SubdiagnosticMessage,
316 NonSnakeCaseDiagSub::Label { span } => {
317 diag.span_label(span, fluent::label);
319 NonSnakeCaseDiagSub::Help => {
320 diag.help(fluent::help);
322 NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
323 diag.span_suggestion(
325 fluent::convert_suggestion,
327 Applicability::MaybeIncorrect,
330 NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
331 diag.span_suggestion(
333 fluent::rename_or_convert_suggestion,
335 Applicability::MaybeIncorrect,
338 NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
339 diag.note(fluent::cannot_convert_note);
340 diag.span_suggestion(
342 fluent::rename_suggestion,
344 Applicability::MaybeIncorrect,
351 #[derive(LintDiagnostic)]
352 #[diag(lint_non_upper_case_global)]
353 pub struct NonUpperCaseGlobal<'a> {
357 pub sub: NonUpperCaseGlobalSub,
360 #[derive(Subdiagnostic)]
361 pub enum NonUpperCaseGlobalSub {
367 #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
375 // noop_method_call.rs
376 #[derive(LintDiagnostic)]
377 #[diag(lint_noop_method_call)]
379 pub struct NoopMethodCallDiag<'a> {
381 pub receiver_ty: Ty<'a>,
387 #[derive(LintDiagnostic)]
388 #[diag(lint_pass_by_value)]
389 pub struct PassByValueDiag {
391 #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
392 pub suggestion: Span,
395 // redundant_semicolon.rs
396 #[derive(LintDiagnostic)]
397 #[diag(lint_redundant_semicolons)]
398 pub struct RedundantSemicolonsDiag {
400 #[suggestion(code = "", applicability = "maybe-incorrect")]
401 pub suggestion: Span,
405 pub struct DropTraitConstraintsDiag<'a> {
406 pub predicate: Predicate<'a>,
411 impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> {
412 fn decorate_lint<'b>(
414 diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
415 ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
416 diag.set_arg("predicate", self.predicate);
417 diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id))
420 fn msg(&self) -> rustc_errors::DiagnosticMessage {
421 fluent::lint_drop_trait_constraints
425 pub struct DropGlue<'a> {
430 impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
431 fn decorate_lint<'b>(
433 diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
434 ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
435 diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id))
438 fn msg(&self) -> rustc_errors::DiagnosticMessage {
439 fluent::lint_drop_glue
444 #[derive(LintDiagnostic)]
445 #[diag(lint_range_endpoint_out_of_range)]
446 pub struct RangeEndpointOutOfRange<'a> {
448 #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
449 pub suggestion: Span,
455 #[derive(LintDiagnostic)]
456 #[diag(lint_overflowing_bin_hex)]
457 pub struct OverflowingBinHex<'a> {
461 pub actually: String,
463 pub sign: OverflowingBinHexSign,
465 pub sub: Option<OverflowingBinHexSub<'a>>,
468 pub enum OverflowingBinHexSign {
473 impl AddToDiagnostic for OverflowingBinHexSign {
474 fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
477 &mut rustc_errors::Diagnostic,
478 rustc_errors::SubdiagnosticMessage,
479 ) -> rustc_errors::SubdiagnosticMessage,
482 OverflowingBinHexSign::Positive => {
483 diag.note(fluent::positive_note);
485 OverflowingBinHexSign::Negative => {
486 diag.note(fluent::negative_note);
487 diag.note(fluent::negative_becomes_note);
493 #[derive(Subdiagnostic)]
494 pub enum OverflowingBinHexSub<'a> {
497 code = "{sans_suffix}{suggestion_ty}",
498 applicability = "machine-applicable"
503 suggestion_ty: &'a str,
504 sans_suffix: &'a str,
507 Help { suggestion_ty: &'a str },
510 pub struct OverflowingInt<'a> {
515 pub suggestion_ty: Option<&'a str>,
518 // FIXME: refactor with `Option<&'a str>` in macro
519 impl<'a> DecorateLint<'a, ()> for OverflowingInt<'_> {
520 fn decorate_lint<'b>(
522 diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
523 ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
524 diag.set_arg("ty", self.ty);
525 diag.set_arg("lit", self.lit);
526 diag.set_arg("min", self.min);
527 diag.set_arg("max", self.max);
528 diag.note(fluent::note);
529 if let Some(suggestion_ty) = self.suggestion_ty {
530 diag.set_arg("suggestion_ty", suggestion_ty);
531 diag.help(fluent::help);
536 fn msg(&self) -> rustc_errors::DiagnosticMessage {
537 fluent::lint_overflowing_int
541 #[derive(LintDiagnostic)]
542 #[diag(lint_only_cast_u8_to_char)]
543 pub struct OnlyCastu8ToChar {
544 #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
549 #[derive(LintDiagnostic)]
550 #[diag(lint_overflowing_uint)]
552 pub struct OverflowingUInt<'a> {
559 #[derive(LintDiagnostic)]
560 #[diag(lint_overflowing_literal)]
562 pub struct OverflowingLiteral<'a> {
567 #[derive(LintDiagnostic)]
568 #[diag(lint_unused_comparisons)]
569 pub struct UnusedComparisons;
571 pub struct ImproperCTypes<'a> {
575 pub help: Option<DiagnosticMessage>,
576 pub note: DiagnosticMessage,
577 pub span_note: Option<Span>,
580 impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
581 fn decorate_lint<'b>(
583 diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
584 ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
585 diag.set_arg("ty", self.ty);
586 diag.set_arg("desc", self.desc);
587 diag.span_label(self.label, fluent::label);
588 if let Some(help) = self.help {
591 diag.note(self.note);
592 if let Some(note) = self.span_note {
593 diag.span_note(note, fluent::note);
598 fn msg(&self) -> rustc_errors::DiagnosticMessage {
599 fluent::lint_improper_ctypes
603 #[derive(LintDiagnostic)]
604 #[diag(lint_variant_size_differences)]
605 pub struct VariantSizeDifferencesDiag {
609 #[derive(LintDiagnostic)]
610 #[diag(lint_atomic_ordering_load)]
612 pub struct AtomicOrderingLoad;
614 #[derive(LintDiagnostic)]
615 #[diag(lint_atomic_ordering_store)]
617 pub struct AtomicOrderingStore;
619 #[derive(LintDiagnostic)]
620 #[diag(lint_atomic_ordering_fence)]
622 pub struct AtomicOrderingFence;
624 #[derive(LintDiagnostic)]
625 #[diag(lint_atomic_ordering_invalid)]
627 pub struct InvalidAtomicOrderingDiag {
630 pub fail_order_arg_span: Span,
634 #[derive(LintDiagnostic)]
635 #[diag(lint_unused_op)]
636 pub struct UnusedOp<'a> {
640 #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")]
641 pub suggestion: Span,
644 #[derive(LintDiagnostic)]
645 #[diag(lint_unused_result)]
646 pub struct UnusedResult<'a> {
650 // FIXME(davidtwco): this isn't properly translatable becauses of the
652 #[derive(LintDiagnostic)]
653 #[diag(lint_unused_closure)]
655 pub struct UnusedClosure<'a> {
661 // FIXME(davidtwco): this isn't properly translatable becauses of the
663 #[derive(LintDiagnostic)]
664 #[diag(lint_unused_generator)]
666 pub struct UnusedGenerator<'a> {
672 // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
674 pub struct UnusedDef<'a, 'b> {
677 pub cx: &'a LateContext<'b>,
679 pub note: Option<Symbol>,
682 // FIXME: refactor with `Option<String>` in macro
683 impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
684 fn decorate_lint<'b>(
686 diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
687 ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
688 diag.set_arg("pre", self.pre);
689 diag.set_arg("post", self.post);
690 diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
691 // check for #[must_use = "..."]
692 if let Some(note) = self.note {
693 diag.note(note.as_str());
698 fn msg(&self) -> rustc_errors::DiagnosticMessage {
699 fluent::lint_unused_def
703 #[derive(LintDiagnostic)]
704 #[diag(lint_path_statement_drop)]
705 pub struct PathStatementDrop {
707 pub sub: PathStatementDropSub,
710 #[derive(Subdiagnostic)]
711 pub enum PathStatementDropSub {
712 #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
725 #[derive(LintDiagnostic)]
726 #[diag(lint_path_statement_no_effect)]
727 pub struct PathStatementNoEffect;
729 #[derive(LintDiagnostic)]
730 #[diag(lint_unused_delim)]
731 pub struct UnusedDelim<'a> {
732 pub delim: &'static str,
735 pub suggestion: Option<UnusedDelimSuggestion>,
738 #[derive(Subdiagnostic)]
739 #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
740 pub struct UnusedDelimSuggestion {
741 #[suggestion_part(code = "{start_replace}")]
742 pub start_span: Span,
743 pub start_replace: &'static str,
744 #[suggestion_part(code = "{end_replace}")]
746 pub end_replace: &'static str,
749 #[derive(LintDiagnostic)]
750 #[diag(lint_unused_import_braces)]
751 pub struct UnusedImportBracesDiag {
755 #[derive(LintDiagnostic)]
756 #[diag(lint_unused_allocation)]
757 pub struct UnusedAllocationDiag;
759 #[derive(LintDiagnostic)]
760 #[diag(lint_unused_allocation_mut)]
761 pub struct UnusedAllocationMutDiag;