diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 1f00a3ab1f5de..13fff3aa34274 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -141,6 +141,15 @@ impl hir::Pat { } } + pub fn simple_span(&self) -> Option { + match self.node { + PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ref path1, None) | + PatKind::Binding(hir::BindingAnnotation::Mutable, _, ref path1, None) => + Some(path1.span), + _ => None, + } + } + /// Return variants that are necessary to exist for the pattern to match. pub fn necessary_variants(&self) -> Vec { let mut variants = vec![]; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d1a46f5f15563..acdd5e6acad04 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -453,11 +453,11 @@ fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { } } - pat.each_binding(|bm, p_id, sp, path1| { + pat.each_binding(|bm, p_id, _sp, path1| { debug!("adding local variable {} from match with bm {:?}", p_id, bm); let name = path1.node; - ir.add_live_node_for_node(p_id, VarDefNode(sp)); + ir.add_live_node_for_node(p_id, VarDefNode(path1.span)); ir.add_variable(Local(LocalInfo { id: p_id, name: name, @@ -628,10 +628,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn pat_bindings(&mut self, pat: &hir::Pat, mut f: F) where F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId), { - pat.each_binding(|_bm, p_id, sp, _n| { + pat.each_binding(|_bm, p_id, sp, n| { let ln = self.live_node(p_id, sp); - let var = self.variable(p_id, sp); - f(self, ln, var, sp, p_id); + let var = self.variable(p_id, n.span); + f(self, ln, var, n.span, p_id); }) } @@ -1398,7 +1398,8 @@ fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local) }, None => { this.pat_bindings(&local.pat, |this, ln, var, sp, id| { - this.warn_about_unused(sp, id, ln, var); + let span = local.pat.simple_span().unwrap_or(sp); + this.warn_about_unused(span, id, ln, var); }) } } @@ -1497,7 +1498,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) { for arg in &body.arguments { - arg.pat.each_binding(|_bm, p_id, sp, path1| { + arg.pat.each_binding(|_bm, p_id, _, path1| { + let sp = path1.span; let var = self.variable(p_id, sp); // Ignore unused self. let name = path1.node; @@ -1541,6 +1543,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let suggest_underscore_msg = format!("consider using `_{}` instead", name); + if is_assigned { self.ir.tcx .lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp, diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index 6994a377a06d7..100fb6d3533f5 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -35,6 +35,10 @@ fn main() { endless_and_singing: true }; + let mut mut_unused_var = 1; + + let (mut var, unused_var) = (1, 2); + if let SoulHistory { corridors_of_light, mut hours_are_suns, endless_and_singing: true } = who_from_the_womb_remembered { diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index 7bfe2c9162ed1..992be2c0a2844 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -11,22 +11,40 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) | ^^^^^^ = note: #[warn(unused_variables)] implied by #[warn(unused)] +warning: unused variable: `mut_unused_var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:13 + | +LL | let mut mut_unused_var = 1; + | ^^^^^^^^^^^^^^ help: consider using `_mut_unused_var` instead + +warning: unused variable: `var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:14 + | +LL | let (mut var, unused_var) = (1, 2); + | ^^^ help: consider using `_var` instead + +warning: unused variable: `unused_var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:19 + | +LL | let (mut var, unused_var) = (1, 2); + | ^^^^^^^^^^ help: consider using `_unused_var` instead + warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:42:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:39:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:43:30 | LL | mut hours_are_suns, - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:45:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ @@ -39,38 +57,61 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = note: #[warn(unused_assignments)] implied by #[warn(unused)] warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:23 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:54:23 | LL | Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:55:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:59:24 | LL | &Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:60:27 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:64:27 | LL | box Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:65:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:69:24 | LL | (Large::Suit { case },) => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:70:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:74:24 | LL | [Large::Suit { case }] => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:75:29 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:79:29 | LL | Tuple(Large::Suit { case }, ()) => {} | ^^^^ help: try ignoring the field: `case: _` +warning: variable does not need to be mutable + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:9 + | +LL | let mut mut_unused_var = 1; + | ----^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + | +note: lint level defined here + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9 + | +LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) + | ^^^^^^ + = note: #[warn(unused_mut)] implied by #[warn(unused)] + +warning: variable does not need to be mutable + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:10 + | +LL | let (mut var, unused_var) = (1, 2); + | ----^^^ + | | + | help: remove this `mut` +