]> git.lizzy.rs Git - rust.git/commitdiff
Show code suggestions in `let_undescore` lint messages.
authorAaron Kofsky <aaronko@umich.edu>
Sat, 4 Jun 2022 01:33:13 +0000 (21:33 -0400)
committerAaron Kofsky <aaronko@umich.edu>
Sat, 4 Jun 2022 19:35:13 +0000 (15:35 -0400)
This commit uses `span_suggestion_verbose` to add what specific code
changes can be done as suggested by the lint--in this case, either binding
the expression to an unused variable or using `std::mem::drop` to drop
the value explicitly.

compiler/rustc_lint/src/let_underscore.rs
src/test/ui/let_underscore/let_underscore_drop.stderr
src/test/ui/let_underscore/let_underscore_lock.stderr
src/test/ui/let_underscore/let_underscore_must_use.stderr

index 985c7300efa95e4da4bd4befada1337005d30dd7..4e4cedaeb782174713e3f57275d5a472861371cc 100644 (file)
@@ -1,6 +1,10 @@
 use crate::{LateContext, LateLintPass, LintContext};
+use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
+use rustc_middle::{
+    lint::LintDiagnosticBuilder,
+    ty::{self, subst::GenericArgKind, Ty},
+};
 use rustc_span::Symbol;
 
 declare_lint! {
@@ -141,30 +145,60 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
             });
             let is_must_use_ty = is_must_use_ty(cx, cx.typeck_results().expr_ty(init));
             let is_must_use_func_call = is_must_use_func_call(cx, init);
+
             if is_sync_lock {
                 cx.struct_span_lint(LET_UNDERSCORE_LOCK, local.span, |lint| {
-                    lint.build("non-binding let on a synchronization lock")
-                        .help("consider binding to an unused variable")
-                        .help("consider explicitly droping with `std::mem::drop`")
-                        .emit();
+                    build_and_emit_lint(
+                        lint,
+                        local,
+                        init.span,
+                        "non-binding let on a synchronization lock",
+                    )
                 })
             } else if is_must_use_ty || is_must_use_func_call {
                 cx.struct_span_lint(LET_UNDERSCORE_MUST_USE, local.span, |lint| {
-                    lint.build("non-binding let on a expression marked `must_use`")
-                        .help("consider binding to an unused variable")
-                        .help("consider explicitly droping with `std::mem::drop`")
-                        .emit();
+                    build_and_emit_lint(
+                        lint,
+                        local,
+                        init.span,
+                        "non-binding let on a expression marked `must_use`",
+                    );
                 })
             } else if needs_drop {
                 cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
-                    lint.build("non-binding let on a type that implements `Drop`")
-                        .help("consider binding to an unused variable")
-                        .help("consider explicitly droping with `std::mem::drop`")
-                        .emit();
+                    build_and_emit_lint(
+                        lint,
+                        local,
+                        init.span,
+                        "non-binding let on a type that implements `Drop`",
+                    );
                 })
             }
         }
 
+        fn build_and_emit_lint(
+            lint: LintDiagnosticBuilder<'_, ()>,
+            local: &hir::Local<'_>,
+            init_span: rustc_span::Span,
+            msg: &str,
+        ) {
+            lint.build(msg)
+                .span_suggestion_verbose(
+                    local.pat.span,
+                    "consider binding to an unused variable",
+                    "_unused",
+                    Applicability::MachineApplicable,
+                )
+                .span_suggestion_verbose(
+                    init_span,
+                    "consider explicitly droping with `std::mem::drop`",
+                    "drop(...)",
+                    Applicability::HasPlaceholders,
+                )
+                .emit();
+        }
+
+        // return true if `ty` is a type that is marked as `must_use`
         fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
             match ty.kind() {
                 ty::Adt(adt, _) => has_must_use_attr(cx, adt.did()),
index f4fd663c7f9ea980dac99fe8b98890056f952dd0..5034f682bb76bf73b0b8f2783352701fc9a8a9f2 100644 (file)
@@ -5,8 +5,14 @@ LL |     let _ = NontrivialDrop;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: requested on the command line with `-W let-underscore-drop`
-   = help: consider binding to an unused variable
-   = help: consider explicitly droping with `std::mem::drop`
+help: consider binding to an unused variable
+   |
+LL |     let _unused = NontrivialDrop;
+   |         ~~~~~~~
+help: consider explicitly droping with `std::mem::drop`
+   |
+LL |     let _ = drop(...);
+   |             ~~~~~~~~~
 
 warning: 1 warning emitted
 
index 77379d8c3db2c6cb56effc56e9976ec99f22fe05..08f81962f3c6553a0abd72e55d09a04eaf6d40a0 100644 (file)
@@ -5,8 +5,14 @@ LL |     let _ = data.lock().unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(let_underscore_lock)]` on by default
-   = help: consider binding to an unused variable
-   = help: consider explicitly droping with `std::mem::drop`
+help: consider binding to an unused variable
+   |
+LL |     let _unused = data.lock().unwrap();
+   |         ~~~~~~~
+help: consider explicitly droping with `std::mem::drop`
+   |
+LL |     let _ = drop(...);
+   |             ~~~~~~~~~
 
 warning: 1 warning emitted
 
index ea1de45e17b5759250674fbb28f4dd0085d2370e..959572edd7c0da419c639d8629f6929c928e653a 100644 (file)
@@ -5,8 +5,14 @@ LL |     let _ = MustUseType;
    |     ^^^^^^^^^^^^^^^^^^^^
    |
    = note: requested on the command line with `-W let-underscore-must-use`
-   = help: consider binding to an unused variable
-   = help: consider explicitly droping with `std::mem::drop`
+help: consider binding to an unused variable
+   |
+LL |     let _unused = MustUseType;
+   |         ~~~~~~~
+help: consider explicitly droping with `std::mem::drop`
+   |
+LL |     let _ = drop(...);
+   |             ~~~~~~~~~
 
 warning: non-binding let on a expression marked `must_use`
   --> $DIR/let_underscore_must_use.rs:12:5
@@ -14,8 +20,14 @@ warning: non-binding let on a expression marked `must_use`
 LL |     let _ = must_use_function();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: consider binding to an unused variable
-   = help: consider explicitly droping with `std::mem::drop`
+help: consider binding to an unused variable
+   |
+LL |     let _unused = must_use_function();
+   |         ~~~~~~~
+help: consider explicitly droping with `std::mem::drop`
+   |
+LL |     let _ = drop(...);
+   |             ~~~~~~~~~
 
 warning: 2 warnings emitted