Skip to content

Rollup of 3 pull requests #57930

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

Closed
wants to merge 6 commits into from
Closed
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
29 changes: 1 addition & 28 deletions src/libcore/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {

/// Disposes of a value.
///
/// While this does call the argument's implementation of [`Drop`][drop],
/// it will not release any borrows, as borrows are based on lexical scope.
/// This does call the argument's implementation of [`Drop`][drop].
///
/// This effectively does nothing for types which implement `Copy`, e.g.
/// integers. Such values are copied and _then_ moved into the function, so the
Expand All @@ -741,32 +740,6 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
/// drop(v); // explicitly drop the vector
/// ```
///
/// Borrows are based on lexical scope, so this produces an error:
///
/// ```compile_fail,E0502
/// let mut v = vec![1, 2, 3];
/// let x = &v[0];
///
/// drop(x); // explicitly drop the reference, but the borrow still exists
///
/// v.push(4); // error: cannot borrow `v` as mutable because it is also
/// // borrowed as immutable
/// ```
///
/// An inner scope is needed to fix this:
///
/// ```
/// let mut v = vec![1, 2, 3];
///
/// {
/// let x = &v[0];
///
/// drop(x); // this is now redundant, as `x` is going out of scope anyway
/// }
///
/// v.push(4); // no problems
/// ```
///
/// Since [`RefCell`] enforces the borrow rules at runtime, `drop` can
/// release a [`RefCell`] borrow:
///
Expand Down
83 changes: 52 additions & 31 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ use ty::query::{Providers, queries};
use lint;
use errors::Applicability;
use util::nodemap::{NodeMap, HirIdMap, HirIdSet};
use rustc_data_structures::fx::FxHashMap;

use std::collections::VecDeque;
use std::{fmt, u32};
Expand Down Expand Up @@ -1446,7 +1447,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 +1456,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: FxHashMap<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 +1569,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 +1581,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,29 +1605,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_with_applicability(sp, "try ignoring the field",
format!("{}: _", name),
Applicability::MachineApplicable);
err.multipart_suggestion_with_applicability(
"try ignoring the field",
spans.iter().map(|span| (*span, format!("{}: _", name))).collect(),
Applicability::MachineApplicable
);
} else {
err.span_suggestion_short_with_applicability(
sp, &suggest_underscore_msg,
format!("_{}", name),
err.multipart_suggestion_with_applicability(
"consider prefixing with an underscore",
spans.iter().map(|span| (*span, format!("_{}", name))).collect(),
Applicability::MachineApplicable,
);
}

err.emit()
}
}
Expand All @@ -1619,11 +1644,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
2 changes: 1 addition & 1 deletion src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub fn target() -> TargetResult {
linker: Some("rust-lld".to_string()),
cpu: "generic-rv32".to_string(),
max_atomic_width: Some(32),
atomic_cas: false, // incomplete +a extension
atomic_cas: true,
features: "+m,+a,+c".to_string(),
executables: true,
panic_strategy: PanicStrategy::Abort,
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: `b`
--> $DIR/issue-56685.rs:27:17
|
LL | F::C(a, b) => { 3 }
| ^ help: consider prefixing with an underscore: `_b`

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: `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
Loading