Skip to content

Unused variable suggestions apply on all patterns. #57899

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 50 additions & 34 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ use lint;
use errors::Applicability;
use util::nodemap::{NodeMap, HirIdMap, HirIdSet};

use std::collections::VecDeque;
use std::collections::{BTreeMap, VecDeque};
use std::{fmt, u32};
use std::io::prelude::*;
use std::io;
Expand Down Expand Up @@ -1446,7 +1446,7 @@ 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| {
let span = local.pat.simple_ident().map_or(sp, |ident| ident.span);
this.warn_about_unused(span, id, ln, var);
this.warn_about_unused(vec![span], id, ln, var);
})
}
}
Expand All @@ -1455,12 +1455,29 @@ fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local)
}

fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) {
// only consider the first pattern; any later patterns must have
// the same bindings, and we also consider the first pattern to be
// the "authoritative" set of ids
this.arm_pats_bindings(arm.pats.first().map(|p| &**p), |this, ln, var, sp, id| {
this.warn_about_unused(sp, id, ln, var);
});
// Only consider the variable from the first pattern; any later patterns must have
// the same bindings, and we also consider the first pattern to be the "authoritative" set of
// ids. However, we should take the spans of variables with the same name from the later
// patterns so the suggestions to prefix with underscores will apply to those too.
let mut vars: BTreeMap<String, (LiveNode, Variable, HirId, Vec<Span>)> = Default::default();

for pat in &arm.pats {
this.arm_pats_bindings(Some(&*pat), |this, ln, var, sp, id| {
let name = this.ir.variable_name(var);
vars.entry(name)
.and_modify(|(.., spans)| {
spans.push(sp);
})
.or_insert_with(|| {
(ln, var, id, vec![sp])
});
});
}

for (_, (ln, var, id, spans)) in vars {
this.warn_about_unused(spans, id, ln, var);
}

intravisit::walk_arm(this, arm);
}

Expand Down Expand Up @@ -1551,7 +1568,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let var = self.variable(hir_id, sp);
// Ignore unused self.
if ident.name != keywords::SelfLower.name() {
if !self.warn_about_unused(sp, hir_id, entry_ln, var) {
if !self.warn_about_unused(vec![sp], hir_id, entry_ln, var) {
if self.live_on_entry(entry_ln, var).is_none() {
self.report_dead_assign(hir_id, sp, var, true);
}
Expand All @@ -1563,14 +1580,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &hir::Pat) {
self.pat_bindings(pat, |this, ln, var, sp, id| {
if !this.warn_about_unused(sp, id, ln, var) {
if !this.warn_about_unused(vec![sp], id, ln, var) {
this.warn_about_dead_assign(sp, id, ln, var);
}
})
}

fn warn_about_unused(&self,
sp: Span,
spans: Vec<Span>,
hir_id: HirId,
ln: LiveNode,
var: Variable)
Expand All @@ -1587,33 +1604,36 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.assigned_on_exit(ln, var).is_some()
};

let suggest_underscore_msg = format!("consider using `_{}` instead", name);

if is_assigned {
self.ir.tcx
.lint_hir_note(lint::builtin::UNUSED_VARIABLES, hir_id, sp,
&format!("variable `{}` is assigned to, but never used",
name),
&suggest_underscore_msg);
self.ir.tcx.lint_hir_note(
lint::builtin::UNUSED_VARIABLES,
hir_id,
spans.clone(),
&format!("variable `{}` is assigned to, but never used", name),
&format!("consider using `_{}` instead", name),
);
} else if name != "self" {
let msg = format!("unused variable: `{}`", name);
let mut err = self.ir.tcx
.struct_span_lint_hir(lint::builtin::UNUSED_VARIABLES, hir_id, sp, &msg);
let mut err = self.ir.tcx.struct_span_lint_hir(
lint::builtin::UNUSED_VARIABLES,
hir_id,
spans.clone(),
&format!("unused variable: `{}`", name),
);

if self.ir.variable_is_shorthand(var) {
err.span_suggestion(
sp,
err.multipart_suggestion(
"try ignoring the field",
format!("{}: _", name),
Applicability::MachineApplicable,
spans.iter().map(|span| (*span, format!("{}: _", name))).collect(),
Applicability::MachineApplicable
);
} else {
err.span_suggestion_short(
sp,
&suggest_underscore_msg,
format!("_{}", name),
err.multipart_suggestion(
"consider prefixing with an underscore",
spans.iter().map(|span| (*span, format!("_{}", name))).collect(),
Applicability::MachineApplicable,
);
}

err.emit()
}
}
Expand All @@ -1623,11 +1643,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
}

fn warn_about_dead_assign(&self,
sp: Span,
hir_id: HirId,
ln: LiveNode,
var: Variable) {
fn warn_about_dead_assign(&self, sp: Span, hir_id: HirId, ln: LiveNode, var: Variable) {
if self.live_on_exit(ln, var).is_none() {
self.report_dead_assign(hir_id, sp, var, false);
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-17999.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error: unused variable: `x`
--> $DIR/issue-17999.rs:5:13
|
LL | let x = (); //~ ERROR: unused variable: `x`
| ^ help: consider using `_x` instead
| ^ help: consider prefixing with an underscore: `_x`
|
note: lint level defined here
--> $DIR/issue-17999.rs:1:9
Expand All @@ -14,7 +14,7 @@ error: unused variable: `a`
--> $DIR/issue-17999.rs:7:13
|
LL | a => {} //~ ERROR: unused variable: `a`
| ^ help: consider using `_a` instead
| ^ help: consider prefixing with an underscore: `_a`

error: aborting due to 2 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-22599.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error: unused variable: `a`
--> $DIR/issue-22599.rs:8:19
|
LL | v = match 0 { a => 0 }; //~ ERROR: unused variable: `a`
| ^ help: consider using `_a` instead
| ^ help: consider prefixing with an underscore: `_a`
|
note: lint level defined here
--> $DIR/issue-22599.rs:1:9
Expand Down
44 changes: 44 additions & 0 deletions src/test/ui/issues/issue-56685.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#![allow(dead_code)]
#![deny(unused_variables)]

// This test aims to check that unused variable suggestions update bindings in all
// match arms.

fn main() {
enum E {
A(i32,),
B(i32,),
}

match E::A(1) {
E::A(x) | E::B(x) => {}
//~^ ERROR unused variable: `x`
}

enum F {
A(i32, i32,),
B(i32, i32,),
C(i32, i32,),
}

let _ = match F::A(1, 2) {
F::A(x, y) | F::B(x, y) => { y },
//~^ ERROR unused variable: `x`
F::C(a, b) => { 3 }
//~^ ERROR unused variable: `a`
//~^^ ERROR unused variable: `b`
};

let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
//~^ ERROR unused variable: `x`
y
} else {
3
};

while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
//~^ ERROR unused variable: `x`
let _ = y;
break;
}
}
60 changes: 60 additions & 0 deletions src/test/ui/issues/issue-56685.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
error: unused variable: `x`
--> $DIR/issue-56685.rs:14:14
|
LL | E::A(x) | E::B(x) => {}
| ^ ^
|
note: lint level defined here
--> $DIR/issue-56685.rs:2:9
|
LL | #![deny(unused_variables)]
| ^^^^^^^^^^^^^^^^
help: consider prefixing with an underscore
|
LL | E::A(_x) | E::B(_x) => {}
| ^^ ^^

error: unused variable: `x`
--> $DIR/issue-56685.rs:25:14
|
LL | F::A(x, y) | F::B(x, y) => { y },
| ^ ^
help: consider prefixing with an underscore
|
LL | F::A(_x, y) | F::B(_x, y) => { y },
| ^^ ^^

error: unused variable: `a`
--> $DIR/issue-56685.rs:27:14
|
LL | F::C(a, b) => { 3 }
| ^ help: consider prefixing with an underscore: `_a`

error: unused variable: `b`
--> $DIR/issue-56685.rs:27:17
|
LL | F::C(a, b) => { 3 }
| ^ help: consider prefixing with an underscore: `_b`

error: unused variable: `x`
--> $DIR/issue-56685.rs:32:25
|
LL | let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
| ^ ^
help: consider prefixing with an underscore
|
LL | let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
| ^^ ^^

error: unused variable: `x`
--> $DIR/issue-56685.rs:39:20
|
LL | while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
| ^ ^
help: consider prefixing with an underscore
|
LL | while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
| ^^ ^^

error: aborting due to 6 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ warning: unused variable: `i_think_continually`
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9
|
LL | let i_think_continually = 2;
| ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead
| ^^^^^^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_i_think_continually`
|
note: lint level defined here
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
Expand All @@ -15,19 +15,19 @@ warning: unused variable: `mut_unused_var`
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:13
|
LL | let mut mut_unused_var = 1;
| ^^^^^^^^^^^^^^ help: consider using `_mut_unused_var` instead
| ^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_mut_unused_var`

warning: unused variable: `var`
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:14
|
LL | let (mut var, unused_var) = (1, 2);
| ^^^ help: consider using `_var` instead
| ^^^ help: consider prefixing with an underscore: `_var`

warning: unused variable: `unused_var`
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:19
|
LL | let (mut var, unused_var) = (1, 2);
| ^^^^^^^^^^ help: consider using `_unused_var` instead
| ^^^^^^^^^^ help: consider prefixing with an underscore: `_unused_var`

warning: unused variable: `corridors_of_light`
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:26
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-removed-allow.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error: unused variable: `unused`
--> $DIR/lint-removed-allow.rs:8:17
|
LL | fn main() { let unused = (); } //~ ERROR unused
| ^^^^^^ help: consider using `_unused` instead
| ^^^^^^ help: consider prefixing with an underscore: `_unused`
|
note: lint level defined here
--> $DIR/lint-removed-allow.rs:7:8
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-removed-cmdline.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ error: unused variable: `unused`
--> $DIR/lint-removed-cmdline.rs:12:17
|
LL | fn main() { let unused = (); }
| ^^^^^^ help: consider using `_unused` instead
| ^^^^^^ help: consider prefixing with an underscore: `_unused`
|
note: lint level defined here
--> $DIR/lint-removed-cmdline.rs:11:8
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-removed.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ error: unused variable: `unused`
--> $DIR/lint-removed.rs:8:17
|
LL | fn main() { let unused = (); } //~ ERROR unused
| ^^^^^^ help: consider using `_unused` instead
| ^^^^^^ help: consider prefixing with an underscore: `_unused`
|
note: lint level defined here
--> $DIR/lint-removed.rs:7:8
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-renamed-allow.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error: unused variable: `unused`
--> $DIR/lint-renamed-allow.rs:8:17
|
LL | fn main() { let unused = (); } //~ ERROR unused
| ^^^^^^ help: consider using `_unused` instead
| ^^^^^^ help: consider prefixing with an underscore: `_unused`
|
note: lint level defined here
--> $DIR/lint-renamed-allow.rs:7:8
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-renamed-cmdline.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ error: unused variable: `unused`
--> $DIR/lint-renamed-cmdline.rs:8:17
|
LL | fn main() { let unused = (); }
| ^^^^^^ help: consider using `_unused` instead
| ^^^^^^ help: consider prefixing with an underscore: `_unused`
|
note: lint level defined here
--> $DIR/lint-renamed-cmdline.rs:7:8
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-renamed.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ error: unused variable: `unused`
--> $DIR/lint-renamed.rs:4:17
|
LL | fn main() { let unused = (); } //~ ERROR unused
| ^^^^^^ help: consider using `_unused` instead
| ^^^^^^ help: consider prefixing with an underscore: `_unused`
|
note: lint level defined here
--> $DIR/lint-renamed.rs:3:8
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/lint-uppercase-variables.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ warning: unused variable: `Foo`
--> $DIR/lint-uppercase-variables.rs:22:9
|
LL | Foo => {}
| ^^^ help: consider using `_Foo` instead
| ^^^ help: consider prefixing with an underscore: `_Foo`
|
note: lint level defined here
--> $DIR/lint-uppercase-variables.rs:1:9
Expand Down
Loading