about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_error_messages/locales/en-US/lint.ftl12
-rw-r--r--compiler/rustc_lint/src/let_underscore.rs49
-rw-r--r--compiler/rustc_lint/src/lints.rs46
3 files changed, 74 insertions, 33 deletions
diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl
index babdbb1cc19..2423d9c0ef9 100644
--- a/compiler/rustc_error_messages/locales/en-US/lint.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl
@@ -16,6 +16,18 @@ lint_enum_intrinsics_mem_variant =
 lint_expectation = this lint expectation is unfulfilled
     .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
 
+lint_non_binding_let_on_sync_lock =
+    non-binding let on a synchronization lock
+
+lint_non_binding_let_on_drop_type =
+    non-binding let on a type that implements `Drop`
+
+lint_non_binding_let_suggestion =
+    consider binding to an unused variable to avoid immediately dropping the value
+
+lint_non_binding_let_multi_suggestion =
+    consider immediately dropping the value
+
 lint_deprecated_lint_name =
     lint name `{$name}` is deprecated and may not have an effect in the future.
     .suggestion = change it to
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index 04d844d21dc..991b3e920ad 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -1,5 +1,10 @@
-use crate::{LateContext, LateLintPass, LintContext};
-use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan};
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+use crate::{
+    lints::{NonBindingLet, NonBindingLetSub},
+    LateContext, LateLintPass, LintContext,
+};
+use rustc_errors::MultiSpan;
 use rustc_hir as hir;
 use rustc_middle::ty;
 use rustc_span::Symbol;
@@ -119,6 +124,11 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
                 _ => false,
             };
 
+            let sub = NonBindingLetSub {
+                suggestion: local.pat.span,
+                multi_suggestion_start: local.span.until(init.span),
+                multi_suggestion_end: init.span.shrink_to_hi(),
+            };
             if is_sync_lock {
                 let mut span = MultiSpan::from_spans(vec![local.pat.span, init.span]);
                 span.push_span_label(
@@ -129,41 +139,14 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
                     init.span,
                     "this binding will immediately drop the value assigned to it".to_string(),
                 );
-                cx.struct_span_lint(
-                    LET_UNDERSCORE_LOCK,
-                    span,
-                    "non-binding let on a synchronization lock",
-                    |lint| build_lint(lint, local, init.span),
-                )
+                cx.emit_spanned_lint(LET_UNDERSCORE_LOCK, span, NonBindingLet::SyncLock { sub });
             } else {
-                cx.struct_span_lint(
+                cx.emit_spanned_lint(
                     LET_UNDERSCORE_DROP,
                     local.span,
-                    "non-binding let on a type that implements `Drop`",
-                    |lint| build_lint(lint, local, init.span),
-                )
+                    NonBindingLet::DropType { sub },
+                );
             }
         }
     }
 }
-
-fn build_lint<'a, 'b>(
-    lint: &'a mut DiagnosticBuilder<'b, ()>,
-    local: &hir::Local<'_>,
-    init_span: rustc_span::Span,
-) -> &'a mut DiagnosticBuilder<'b, ()> {
-    lint.span_suggestion_verbose(
-        local.pat.span,
-        "consider binding to an unused variable to avoid immediately dropping the value",
-        "_unused",
-        Applicability::MachineApplicable,
-    )
-    .multipart_suggestion(
-        "consider immediately dropping the value",
-        vec![
-            (local.span.until(init_span), "drop(".to_string()),
-            (init_span.shrink_to_hi(), ")".to_string()),
-        ],
-        Applicability::MachineApplicable,
-    )
-}
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index eb86bb7b925..0f314606a94 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -49,6 +49,52 @@ pub struct EnumIntrinsicsMemVariant<'a> {
     pub ty_param: Ty<'a>,
 }
 
+// let_underscore.rs
+#[derive(LintDiagnostic)]
+pub enum NonBindingLet {
+    #[diag(lint::non_binding_let_on_sync_lock)]
+    SyncLock {
+        #[subdiagnostic]
+        sub: NonBindingLetSub,
+    },
+    #[diag(lint::non_binding_let_on_drop_type)]
+    DropType {
+        #[subdiagnostic]
+        sub: NonBindingLetSub,
+    },
+}
+
+pub struct NonBindingLetSub {
+    pub suggestion: Span,
+    pub multi_suggestion_start: Span,
+    pub multi_suggestion_end: Span,
+}
+
+impl AddToDiagnostic for NonBindingLetSub {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
+    where
+        F: Fn(
+            &mut rustc_errors::Diagnostic,
+            rustc_errors::SubdiagnosticMessage,
+        ) -> rustc_errors::SubdiagnosticMessage,
+    {
+        diag.span_suggestion_verbose(
+            self.suggestion,
+            fluent::lint::non_binding_let_suggestion,
+            "_unused",
+            Applicability::MachineApplicable,
+        );
+        diag.multipart_suggestion(
+            fluent::lint::non_binding_let_multi_suggestion,
+            vec![
+                (self.multi_suggestion_start, "drop(".to_string()),
+                (self.multi_suggestion_end, ")".to_string()),
+            ],
+            Applicability::MachineApplicable,
+        );
+    }
+}
+
 // levels.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_overruled_attribute)]