Skip to content

Commit

Permalink
Rollup merge of #72465 - tmiasko:liveness-upvars, r=nikomatsakis
Browse files Browse the repository at this point in the history
Warn about unused captured variables

Include captured variables in liveness analysis. Warn when captured variables
are unused (but possibly read or written to). Warn about dead assignments to
captured variables.

Fixes #37707.
Fixes #47128.
Fixes #63220.
  • Loading branch information
Dylan-DPC authored May 29, 2020
2 parents 8bce240 + 4dc5661 commit 9ef6227
Show file tree
Hide file tree
Showing 12 changed files with 543 additions and 123 deletions.
321 changes: 208 additions & 113 deletions src/librustc_passes/liveness.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ fn foo(mut f: Box<dyn FnMut()>) {

fn main() {
let mut y = true;
foo(Box::new(move || y = false) as Box<_>);
foo(Box::new(move || y = !y) as Box<_>);
//~^ ERROR cannot assign to `y`, as it is not declared as mutable
}
2 changes: 1 addition & 1 deletion src/test/ui/closures/closure-immutable-outer-variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ fn foo(mut f: Box<dyn FnMut()>) {

fn main() {
let y = true;
foo(Box::new(move || y = false) as Box<_>);
foo(Box::new(move || y = !y) as Box<_>);
//~^ ERROR cannot assign to `y`, as it is not declared as mutable
}
4 changes: 2 additions & 2 deletions src/test/ui/closures/closure-immutable-outer-variable.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ error[E0594]: cannot assign to `y`, as it is not declared as mutable
|
LL | let y = true;
| - help: consider changing this to be mutable: `mut y`
LL | foo(Box::new(move || y = false) as Box<_>);
| ^^^^^^^^^ cannot assign
LL | foo(Box::new(move || y = !y) as Box<_>);
| ^^^^^^ cannot assign

error: aborting due to previous error

Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/issues/issue-11958.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// run-pass
#![forbid(warnings)]

// We shouldn't need to rebind a moved upvar as mut if it's already
// marked as mut

pub fn main() {
let mut x = 1;
let _thunk = Box::new(move|| { x = 2; });
//~^ WARN value assigned to `x` is never read
//~| WARN unused variable: `x`
}
20 changes: 20 additions & 0 deletions src/test/ui/issues/issue-11958.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
warning: value assigned to `x` is never read
--> $DIR/issue-11958.rs:8:36
|
LL | let _thunk = Box::new(move|| { x = 2; });
| ^
|
= note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?

warning: unused variable: `x`
--> $DIR/issue-11958.rs:8:36
|
LL | let _thunk = Box::new(move|| { x = 2; });
| ^
|
= note: `#[warn(unused_variables)]` on by default
= help: did you mean to capture by reference instead?

warning: 2 warnings emitted

108 changes: 108 additions & 0 deletions src/test/ui/liveness/liveness-upvars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// edition:2018
// check-pass
#![warn(unused)]
#![allow(unreachable_code)]

pub fn unintentional_copy_one() {
let mut last = None;
let mut f = move |s| {
last = Some(s); //~ WARN value assigned to `last` is never read
//~| WARN unused variable: `last`
};
f("a");
f("b");
f("c");
dbg!(last.unwrap());
}

pub fn unintentional_copy_two() {
let mut sum = 0;
(1..10).for_each(move |x| {
sum += x; //~ WARN unused variable: `sum`
});
dbg!(sum);
}

pub fn f() {
let mut c = 0;

// Captured by value, but variable is dead on entry.
move || {
c = 1; //~ WARN value captured by `c` is never read
println!("{}", c);
};
let _ = async move {
c = 1; //~ WARN value captured by `c` is never read
println!("{}", c);
};

// Read and written to, but never actually used.
move || {
c += 1; //~ WARN unused variable: `c`
};
let _ = async move {
c += 1; //~ WARN value assigned to `c` is never read
//~| WARN unused variable: `c`
};

move || {
println!("{}", c);
// Value is read by closure itself on later invocations.
c += 1;
};
let b = Box::new(42);
move || {
println!("{}", c);
// Never read because this is FnOnce closure.
c += 1; //~ WARN value assigned to `c` is never read
drop(b);
};
let _ = async move {
println!("{}", c);
// Never read because this is a generator.
c += 1; //~ WARN value assigned to `c` is never read
};
}

pub fn nested() {
let mut d = None;
let mut e = None;
|| {
|| {
d = Some("d1"); //~ WARN value assigned to `d` is never read
d = Some("d2");
};
move || {
e = Some("e1"); //~ WARN value assigned to `e` is never read
//~| WARN unused variable: `e`
e = Some("e2"); //~ WARN value assigned to `e` is never read
};
};
}

pub fn g<T: Default>(mut v: T) {
|r| {
if r {
v = T::default(); //~ WARN value assigned to `v` is never read
} else {
drop(v);
}
};
}

pub fn h<T: Copy + Default + std::fmt::Debug>() {
let mut z = T::default();
move |b| {
loop {
if b {
z = T::default(); //~ WARN value assigned to `z` is never read
//~| WARN unused variable: `z`
} else {
return;
}
}
dbg!(z);
};
}

fn main() {}
150 changes: 150 additions & 0 deletions src/test/ui/liveness/liveness-upvars.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
warning: value assigned to `last` is never read
--> $DIR/liveness-upvars.rs:9:9
|
LL | last = Some(s);
| ^^^^
|
note: the lint level is defined here
--> $DIR/liveness-upvars.rs:3:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
= help: maybe it is overwritten before being read?

warning: unused variable: `last`
--> $DIR/liveness-upvars.rs:9:9
|
LL | last = Some(s);
| ^^^^
|
note: the lint level is defined here
--> $DIR/liveness-upvars.rs:3:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
= help: did you mean to capture by reference instead?

warning: unused variable: `sum`
--> $DIR/liveness-upvars.rs:21:9
|
LL | sum += x;
| ^^^
|
= help: did you mean to capture by reference instead?

warning: value captured by `c` is never read
--> $DIR/liveness-upvars.rs:31:9
|
LL | c = 1;
| ^
|
= help: did you mean to capture by reference instead?

warning: value captured by `c` is never read
--> $DIR/liveness-upvars.rs:35:9
|
LL | c = 1;
| ^
|
= help: did you mean to capture by reference instead?

warning: unused variable: `c`
--> $DIR/liveness-upvars.rs:41:9
|
LL | c += 1;
| ^
|
= help: did you mean to capture by reference instead?

warning: value assigned to `c` is never read
--> $DIR/liveness-upvars.rs:44:9
|
LL | c += 1;
| ^
|
= help: maybe it is overwritten before being read?

warning: unused variable: `c`
--> $DIR/liveness-upvars.rs:44:9
|
LL | c += 1;
| ^
|
= help: did you mean to capture by reference instead?

warning: value assigned to `c` is never read
--> $DIR/liveness-upvars.rs:57:9
|
LL | c += 1;
| ^
|
= help: maybe it is overwritten before being read?

warning: value assigned to `c` is never read
--> $DIR/liveness-upvars.rs:63:9
|
LL | c += 1;
| ^
|
= help: maybe it is overwritten before being read?

warning: value assigned to `d` is never read
--> $DIR/liveness-upvars.rs:72:13
|
LL | d = Some("d1");
| ^
|
= help: maybe it is overwritten before being read?

warning: value assigned to `e` is never read
--> $DIR/liveness-upvars.rs:76:13
|
LL | e = Some("e1");
| ^
|
= help: maybe it is overwritten before being read?

warning: value assigned to `e` is never read
--> $DIR/liveness-upvars.rs:78:13
|
LL | e = Some("e2");
| ^
|
= help: maybe it is overwritten before being read?

warning: unused variable: `e`
--> $DIR/liveness-upvars.rs:76:13
|
LL | e = Some("e1");
| ^
|
= help: did you mean to capture by reference instead?

warning: value assigned to `v` is never read
--> $DIR/liveness-upvars.rs:86:13
|
LL | v = T::default();
| ^
|
= help: maybe it is overwritten before being read?

warning: value assigned to `z` is never read
--> $DIR/liveness-upvars.rs:98:17
|
LL | z = T::default();
| ^
|
= help: maybe it is overwritten before being read?

warning: unused variable: `z`
--> $DIR/liveness-upvars.rs:98:17
|
LL | z = T::default();
| ^
|
= help: did you mean to capture by reference instead?

warning: 17 warnings emitted

Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// run-pass
#![allow(unused_variables)]
// Test that we mutate a counter on the stack only when we expect to.

fn call<F>(f: F) where F : FnOnce() {
Expand All @@ -13,7 +12,7 @@ fn main() {
call(|| {
// Move `y`, but do not move `counter`, even though it is read
// by value (note that it is also mutated).
for item in y {
for item in y { //~ WARN unused variable: `item`
let v = counter;
counter += v;
}
Expand All @@ -22,7 +21,8 @@ fn main() {

call(move || {
// this mutates a moved copy, and hence doesn't affect original
counter += 1;
counter += 1; //~ WARN value assigned to `counter` is never read
//~| WARN unused variable: `counter`
});
assert_eq!(counter, 88);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
warning: unused variable: `item`
--> $DIR/unboxed-closures-counter-not-moved.rs:15:13
|
LL | for item in y {
| ^^^^ help: if this is intentional, prefix it with an underscore: `_item`
|
= note: `#[warn(unused_variables)]` on by default

warning: value assigned to `counter` is never read
--> $DIR/unboxed-closures-counter-not-moved.rs:24:9
|
LL | counter += 1;
| ^^^^^^^
|
= note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?

warning: unused variable: `counter`
--> $DIR/unboxed-closures-counter-not-moved.rs:24:9
|
LL | counter += 1;
| ^^^^^^^
|
= help: did you mean to capture by reference instead?

warning: 3 warnings emitted

4 changes: 2 additions & 2 deletions src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ fn set(x: &mut usize) { *x = 42; }
fn main() {
{
let mut x = 0_usize;
move || x += 1;
move || x += 1; //~ WARN unused variable: `x`
}
{
let mut x = 0_usize;
move || x += 1;
move || x += 1; //~ WARN unused variable: `x`
}
{
let mut x = 0_usize;
Expand Down
Loading

0 comments on commit 9ef6227

Please sign in to comment.