Skip to content

Commit 821d50a

Browse files
committed
Make closures and generators a must use types
Warn about unused expressions with closure or generator type. This follows existing precedence of must use annotations present on `FnOnce`, `FnMut`, `Fn` traits, which already indirectly apply to closures in some cases, e.g.,: ```rust fn f() -> impl FnOnce() { || {} } fn main() { // an existing warning: unused implementer of `std::ops::FnOnce` that must be used: f(); // a new warning: unused closure that must be used: || {}; } ```
1 parent 1f5d69d commit 821d50a

36 files changed

+355
-31
lines changed

src/librustc_lint/unused.rs

+22
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,28 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
203203
// Otherwise, we don't lint, to avoid false positives.
204204
_ => false,
205205
},
206+
ty::Closure(..) => {
207+
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
208+
let mut err = lint.build(&format!(
209+
"unused {}closure{}{} that must be used",
210+
descr_pre, plural_suffix, descr_post,
211+
));
212+
err.note("closures are lazy and do nothing unless called");
213+
err.emit();
214+
});
215+
true
216+
}
217+
ty::Generator(..) => {
218+
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
219+
let mut err = lint.build(&format!(
220+
"unused {}generator{}{} that must be used",
221+
descr_pre, plural_suffix, descr_post,
222+
));
223+
err.note("generators are lazy and do nothing unless resumed");
224+
err.emit();
225+
});
226+
true
227+
}
206228
_ => false,
207229
}
208230
}

src/test/ui/generator/issue-52398.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ impl A {
1414
fn main() {
1515
// Test that the MIR local with type &A created for the auto-borrow adjustment
1616
// is caught by typeck
17-
move || {
17+
move || { //~ WARN unused generator that must be used
1818
A.test(yield);
1919
};
2020

2121
// Test that the std::cell::Ref temporary returned from the `borrow` call
2222
// is caught by typeck
2323
let y = RefCell::new(true);
24-
static move || {
24+
static move || { //~ WARN unused generator that must be used
2525
yield *y.borrow();
2626
return "Done";
2727
};
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
warning: unused generator that must be used
2+
--> $DIR/issue-52398.rs:17:5
3+
|
4+
LL | / move || {
5+
LL | | A.test(yield);
6+
LL | | };
7+
| |______^
8+
|
9+
= note: `#[warn(unused_must_use)]` on by default
10+
= note: generators are lazy and do nothing unless resumed
11+
12+
warning: unused generator that must be used
13+
--> $DIR/issue-52398.rs:24:5
14+
|
15+
LL | / static move || {
16+
LL | | yield *y.borrow();
17+
LL | | return "Done";
18+
LL | | };
19+
| |______^
20+
|
21+
= note: generators are lazy and do nothing unless resumed
22+
23+
warning: 2 warnings emitted
24+

src/test/ui/generator/issue-57084.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ where F: Fn() -> ()
1919

2020
fn main() {
2121
let data = &vec![1];
22-
|| {
22+
|| { //~ WARN unused generator that must be used
2323
let _to_pin = with(move || println!("{:p}", data));
2424
loop {
2525
yield
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
warning: unused generator that must be used
2+
--> $DIR/issue-57084.rs:22:5
3+
|
4+
LL | / || {
5+
LL | | let _to_pin = with(move || println!("{:p}", data));
6+
LL | | loop {
7+
LL | | yield
8+
LL | | }
9+
LL | | };
10+
| |______^
11+
|
12+
= note: `#[warn(unused_must_use)]` on by default
13+
= note: generators are lazy and do nothing unless resumed
14+
15+
warning: 1 warning emitted
16+

src/test/ui/generator/match-bindings.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ enum Enum {
99
}
1010

1111
fn main() {
12-
|| {
12+
|| { //~ WARN unused generator that must be used
1313
loop {
1414
if let true = true {
1515
match Enum::A(String::new()) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: unused generator that must be used
2+
--> $DIR/match-bindings.rs:12:5
3+
|
4+
LL | / || {
5+
LL | | loop {
6+
LL | | if let true = true {
7+
LL | | match Enum::A(String::new()) {
8+
... |
9+
LL | | }
10+
LL | | };
11+
| |______^
12+
|
13+
= note: `#[warn(unused_must_use)]` on by default
14+
= note: generators are lazy and do nothing unless resumed
15+
16+
warning: 1 warning emitted
17+

src/test/ui/generator/reborrow-mut-upvar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![feature(generators)]
44

55
fn _run(bar: &mut i32) {
6-
|| {
6+
|| { //~ WARN unused generator that must be used
77
{
88
let _baz = &*bar;
99
yield;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: unused generator that must be used
2+
--> $DIR/reborrow-mut-upvar.rs:6:5
3+
|
4+
LL | / || {
5+
LL | | {
6+
LL | | let _baz = &*bar;
7+
LL | | yield;
8+
... |
9+
LL | | *bar = 2;
10+
LL | | };
11+
| |______^
12+
|
13+
= note: `#[warn(unused_must_use)]` on by default
14+
= note: generators are lazy and do nothing unless resumed
15+
16+
warning: 1 warning emitted
17+

src/test/ui/generator/too-live-local-in-immovable-gen.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
fn main() {
77
unsafe {
8-
static move || {
8+
static move || { //~ WARN unused generator that must be used
99
// Tests that the generator transformation finds out that `a` is not live
1010
// during the yield expression. Type checking will also compute liveness
1111
// and it should also find out that `a` is not live.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: unused generator that must be used
2+
--> $DIR/too-live-local-in-immovable-gen.rs:8:9
3+
|
4+
LL | / static move || {
5+
LL | | // Tests that the generator transformation finds out that `a` is not live
6+
LL | | // during the yield expression. Type checking will also compute liveness
7+
LL | | // and it should also find out that `a` is not live.
8+
... |
9+
LL | | &a;
10+
LL | | };
11+
| |__________^
12+
|
13+
= note: `#[warn(unused_must_use)]` on by default
14+
= note: generators are lazy and do nothing unless resumed
15+
16+
warning: 1 warning emitted
17+

src/test/ui/generator/yield-in-args-rev.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
fn foo(_a: (), _b: &bool) {}
1111

1212
fn bar() {
13-
|| {
13+
|| { //~ WARN unused generator that must be used
1414
let b = true;
1515
foo(yield, &b);
1616
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
warning: unused generator that must be used
2+
--> $DIR/yield-in-args-rev.rs:13:5
3+
|
4+
LL | / || {
5+
LL | | let b = true;
6+
LL | | foo(yield, &b);
7+
LL | | };
8+
| |______^
9+
|
10+
= note: `#[warn(unused_must_use)]` on by default
11+
= note: generators are lazy and do nothing unless resumed
12+
13+
warning: 1 warning emitted
14+

src/test/ui/generator/yield-in-box.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
fn main() {
88
let x = 0i32;
9-
|| {
9+
|| { //~ WARN unused generator that must be used
1010
let y = 2u32;
1111
{
1212
let _t = box (&x, yield 0, &y);
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: unused generator that must be used
2+
--> $DIR/yield-in-box.rs:9:5
3+
|
4+
LL | / || {
5+
LL | | let y = 2u32;
6+
LL | | {
7+
LL | | let _t = box (&x, yield 0, &y);
8+
... |
9+
LL | | }
10+
LL | | };
11+
| |______^
12+
|
13+
= note: `#[warn(unused_must_use)]` on by default
14+
= note: generators are lazy and do nothing unless resumed
15+
16+
warning: 1 warning emitted
17+

src/test/ui/generator/yield-in-initializer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![feature(generators)]
44

55
fn main() {
6-
static || {
6+
static || { //~ WARN unused generator that must be used
77
loop {
88
// Test that `opt` is not live across the yield, even when borrowed in a loop
99
// See https://github.com/rust-lang/rust/issues/52792
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: unused generator that must be used
2+
--> $DIR/yield-in-initializer.rs:6:5
3+
|
4+
LL | / static || {
5+
LL | | loop {
6+
LL | | // Test that `opt` is not live across the yield, even when borrowed in a loop
7+
LL | | // See https://github.com/rust-lang/rust/issues/52792
8+
... |
9+
LL | | }
10+
LL | | };
11+
| |______^
12+
|
13+
= note: `#[warn(unused_must_use)]` on by default
14+
= note: generators are lazy and do nothing unless resumed
15+
16+
warning: 1 warning emitted
17+

src/test/ui/generator/yield-subtype.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn bar<'a>() {
88
let a: &'static str = "hi";
99
let b: &'a str = a;
1010

11-
|| {
11+
|| { //~ WARN unused generator that must be used
1212
yield a;
1313
yield b;
1414
};
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
warning: unused generator that must be used
2+
--> $DIR/yield-subtype.rs:11:5
3+
|
4+
LL | / || {
5+
LL | | yield a;
6+
LL | | yield b;
7+
LL | | };
8+
| |______^
9+
|
10+
= note: `#[warn(unused_must_use)]` on by default
11+
= note: generators are lazy and do nothing unless resumed
12+
13+
warning: 1 warning emitted
14+

src/test/ui/issues/issue-1460.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
// pretty-expanded FIXME #23616
44

55
pub fn main() {
6-
{|i: u32| if 1 == i { }};
6+
{|i: u32| if 1 == i { }}; //~ WARN unused closure that must be used
77
}

src/test/ui/issues/issue-1460.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: unused closure that must be used
2+
--> $DIR/issue-1460.rs:6:5
3+
|
4+
LL | {|i: u32| if 1 == i { }};
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unused_must_use)]` on by default
8+
= note: closures are lazy and do nothing unless called
9+
10+
warning: 1 warning emitted
11+

src/test/ui/issues/issue-16256.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33

44
fn main() {
55
let mut buf = Vec::new();
6-
|c: u8| buf.push(c);
6+
|c: u8| buf.push(c); //~ WARN unused closure that must be used
77
}

src/test/ui/issues/issue-16256.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: unused closure that must be used
2+
--> $DIR/issue-16256.rs:6:5
3+
|
4+
LL | |c: u8| buf.push(c);
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unused_must_use)]` on by default
8+
= note: closures are lazy and do nothing unless called
9+
10+
warning: 1 warning emitted
11+

src/test/ui/liveness/liveness-upvars.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn f() {
2727
let mut c = 0;
2828

2929
// Captured by value, but variable is dead on entry.
30-
move || {
30+
let _ = move || {
3131
c = 1; //~ WARN value captured by `c` is never read
3232
println!("{}", c);
3333
};
@@ -37,21 +37,21 @@ pub fn f() {
3737
};
3838

3939
// Read and written to, but never actually used.
40-
move || {
40+
let _ = move || {
4141
c += 1; //~ WARN unused variable: `c`
4242
};
4343
let _ = async move {
4444
c += 1; //~ WARN value assigned to `c` is never read
4545
//~| WARN unused variable: `c`
4646
};
4747

48-
move || {
48+
let _ = move || {
4949
println!("{}", c);
5050
// Value is read by closure itself on later invocations.
5151
c += 1;
5252
};
5353
let b = Box::new(42);
54-
move || {
54+
let _ = move || {
5555
println!("{}", c);
5656
// Never read because this is FnOnce closure.
5757
c += 1; //~ WARN value assigned to `c` is never read
@@ -67,12 +67,12 @@ pub fn f() {
6767
pub fn nested() {
6868
let mut d = None;
6969
let mut e = None;
70-
|| {
71-
|| {
70+
let _ = || {
71+
let _ = || {
7272
d = Some("d1"); //~ WARN value assigned to `d` is never read
7373
d = Some("d2");
7474
};
75-
move || {
75+
let _ = move || {
7676
e = Some("e1"); //~ WARN value assigned to `e` is never read
7777
//~| WARN unused variable: `e`
7878
e = Some("e2"); //~ WARN value assigned to `e` is never read
@@ -81,7 +81,7 @@ pub fn nested() {
8181
}
8282

8383
pub fn g<T: Default>(mut v: T) {
84-
|r| {
84+
let _ = |r| {
8585
if r {
8686
v = T::default(); //~ WARN value assigned to `v` is never read
8787
} else {
@@ -92,7 +92,7 @@ pub fn g<T: Default>(mut v: T) {
9292

9393
pub fn h<T: Copy + Default + std::fmt::Debug>() {
9494
let mut z = T::default();
95-
move |b| {
95+
let _ = move |b| {
9696
loop {
9797
if b {
9898
z = T::default(); //~ WARN value assigned to `z` is never read

src/test/ui/nll/capture-mut-ref.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
pub fn mutable_upvar() {
99
let x = &mut 0;
1010
//~^ ERROR
11-
move || {
11+
let _ = move || {
1212
*x = 1;
1313
};
1414
}

0 commit comments

Comments
 (0)