about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGoldstein <root@goldstein.rs>2022-08-01 21:49:12 +0300
committerGoldstein <root@goldstein.rs>2022-08-12 12:32:43 +0300
commit3fb249bebce995ec6fdb1a4a3f49cf1acd5c86b7 (patch)
tree545c11acc986f95dd8afb2610647974cfdeabf59
parentf03ce30962cf1b2a5158667eabae8bf6e8d1cb03 (diff)
downloadrust-3fb249bebce995ec6fdb1a4a3f49cf1acd5c86b7.tar.gz
rust-3fb249bebce995ec6fdb1a4a3f49cf1acd5c86b7.zip
improve "try ignoring the field" diagnostic
Closes #95795
-rw-r--r--compiler/rustc_passes/src/liveness.rs34
-rw-r--r--src/test/ui/suggestions/dont-try-removing-the-field.rs17
-rw-r--r--src/test/ui/suggestions/dont-try-removing-the-field.stderr10
-rw-r--r--src/test/ui/suggestions/try-removing-the-field.rs17
-rw-r--r--src/test/ui/suggestions/try-removing-the-field.stderr12
5 files changed, 88 insertions, 2 deletions
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 461dd52b9f2..7124b84bfef 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -98,7 +98,7 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, DefIdTree, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
 
 use std::collections::VecDeque;
 use std::io;
@@ -1549,6 +1549,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
                 .or_insert_with(|| (ln, var, vec![id_and_sp]));
         });
 
+        let can_remove = matches!(&pat.kind, hir::PatKind::Struct(_, _, true));
+
         for (_, (ln, var, hir_ids_and_spans)) in vars {
             if self.used_on_entry(ln, var) {
                 let id = hir_ids_and_spans[0].0;
@@ -1556,16 +1558,18 @@ impl<'tcx> Liveness<'_, 'tcx> {
                     hir_ids_and_spans.into_iter().map(|(_, _, ident_span)| ident_span).collect();
                 on_used_on_entry(spans, id, ln, var);
             } else {
-                self.report_unused(hir_ids_and_spans, ln, var);
+                self.report_unused(hir_ids_and_spans, ln, var, can_remove);
             }
         }
     }
 
+    #[tracing::instrument(skip(self), level = "INFO")]
     fn report_unused(
         &self,
         hir_ids_and_spans: Vec<(HirId, Span, Span)>,
         ln: LiveNode,
         var: Variable,
+        can_remove: bool,
     ) {
         let first_hir_id = hir_ids_and_spans[0].0;
 
@@ -1590,6 +1594,32 @@ impl<'tcx> Liveness<'_, 'tcx> {
                             .emit();
                     },
                 )
+            } else if can_remove {
+                self.ir.tcx.struct_span_lint_hir(
+                    lint::builtin::UNUSED_VARIABLES,
+                    first_hir_id,
+                    hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::<Vec<_>>(),
+                    |lint| {
+                        let mut err = lint.build(&format!("unused variable: `{}`", name));
+                        err.multipart_suggestion(
+                            "try removing the field",
+                            hir_ids_and_spans
+                                .iter()
+                                .map(|(_, pat_span, _)| {
+                                    let span = self
+                                        .ir
+                                        .tcx
+                                        .sess
+                                        .source_map()
+                                        .span_extend_to_next_char(*pat_span, ',', true);
+                                    (span.with_hi(BytePos(span.hi().0 + 1)), String::new())
+                                })
+                                .collect(),
+                            Applicability::MachineApplicable,
+                        );
+                        err.emit();
+                    },
+                );
             } else {
                 let (shorthands, non_shorthands): (Vec<_>, Vec<_>) =
                     hir_ids_and_spans.iter().copied().partition(|(hir_id, _, ident_span)| {
diff --git a/src/test/ui/suggestions/dont-try-removing-the-field.rs b/src/test/ui/suggestions/dont-try-removing-the-field.rs
new file mode 100644
index 00000000000..948aa2b94d9
--- /dev/null
+++ b/src/test/ui/suggestions/dont-try-removing-the-field.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![allow(dead_code)]
+
+struct Foo {
+    foo: i32,
+    bar: i32,
+    baz: (),
+}
+
+fn use_foo(x: Foo) -> (i32, i32) {
+    let Foo { foo, bar, baz } = x; //~ WARNING unused variable: `baz`
+                                   //~| help: try ignoring the field
+    return (foo, bar);
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/dont-try-removing-the-field.stderr b/src/test/ui/suggestions/dont-try-removing-the-field.stderr
new file mode 100644
index 00000000000..263171a4ac4
--- /dev/null
+++ b/src/test/ui/suggestions/dont-try-removing-the-field.stderr
@@ -0,0 +1,10 @@
+warning: unused variable: `baz`
+  --> $DIR/dont-try-removing-the-field.rs:12:25
+   |
+LL |     let Foo { foo, bar, baz } = x;
+   |                         ^^^ help: try ignoring the field: `baz: _`
+   |
+   = note: `#[warn(unused_variables)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/suggestions/try-removing-the-field.rs b/src/test/ui/suggestions/try-removing-the-field.rs
new file mode 100644
index 00000000000..9d0573ca255
--- /dev/null
+++ b/src/test/ui/suggestions/try-removing-the-field.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![allow(dead_code)]
+
+struct Foo {
+    foo: i32,
+    bar: (),
+    baz: (),
+}
+
+fn use_foo(x: Foo) -> i32 {
+    let Foo { foo, bar, .. } = x; //~ WARNING unused variable: `bar`
+                                  //~| help: try removing the field
+    return foo;
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/try-removing-the-field.stderr b/src/test/ui/suggestions/try-removing-the-field.stderr
new file mode 100644
index 00000000000..448a2c3d2ec
--- /dev/null
+++ b/src/test/ui/suggestions/try-removing-the-field.stderr
@@ -0,0 +1,12 @@
+warning: unused variable: `bar`
+  --> $DIR/try-removing-the-field.rs:12:20
+   |
+LL |     let Foo { foo, bar, .. } = x;
+   |                    ^^^-
+   |                    |
+   |                    help: try removing the field
+   |
+   = note: `#[warn(unused_variables)]` on by default
+
+warning: 1 warning emitted
+