From 821d50aa0cc73c1ec2fb09bab8a69e1c3ca93f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 28 Jul 2020 00:00:00 +0000 Subject: [PATCH 01/11] 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: || {}; } ``` --- src/librustc_lint/unused.rs | 22 ++++++ src/test/ui/generator/issue-52398.rs | 4 +- src/test/ui/generator/issue-52398.stderr | 24 ++++++ src/test/ui/generator/issue-57084.rs | 2 +- src/test/ui/generator/issue-57084.stderr | 16 ++++ src/test/ui/generator/match-bindings.rs | 2 +- src/test/ui/generator/match-bindings.stderr | 17 +++++ src/test/ui/generator/reborrow-mut-upvar.rs | 2 +- .../ui/generator/reborrow-mut-upvar.stderr | 17 +++++ .../too-live-local-in-immovable-gen.rs | 2 +- .../too-live-local-in-immovable-gen.stderr | 17 +++++ src/test/ui/generator/yield-in-args-rev.rs | 2 +- .../ui/generator/yield-in-args-rev.stderr | 14 ++++ src/test/ui/generator/yield-in-box.rs | 2 +- src/test/ui/generator/yield-in-box.stderr | 17 +++++ src/test/ui/generator/yield-in-initializer.rs | 2 +- .../ui/generator/yield-in-initializer.stderr | 17 +++++ src/test/ui/generator/yield-subtype.rs | 2 +- src/test/ui/generator/yield-subtype.stderr | 14 ++++ src/test/ui/issues/issue-1460.rs | 2 +- src/test/ui/issues/issue-1460.stderr | 11 +++ src/test/ui/issues/issue-16256.rs | 2 +- src/test/ui/issues/issue-16256.stderr | 11 +++ src/test/ui/liveness/liveness-upvars.rs | 18 ++--- src/test/ui/nll/capture-mut-ref.fixed | 2 +- src/test/ui/nll/capture-mut-ref.rs | 2 +- src/test/ui/nll/issue-48623-generator.rs | 2 +- src/test/ui/nll/issue-48623-generator.stderr | 11 +++ .../test-runner-hides-buried-main.rs | 4 +- .../unboxed-closures-move-mutable.rs | 1 + .../unboxed-closures-move-mutable.stderr | 4 +- src/test/ui/unused/unused-closure.rs | 40 ++++++++++ src/test/ui/unused/unused-closure.stderr | 75 +++++++++++++++++++ .../unused-mut-warning-captured-var.fixed | 2 +- .../unused/unused-mut-warning-captured-var.rs | 2 +- src/test/ui/weird-exprs.rs | 2 +- 36 files changed, 355 insertions(+), 31 deletions(-) create mode 100644 src/test/ui/generator/issue-52398.stderr create mode 100644 src/test/ui/generator/issue-57084.stderr create mode 100644 src/test/ui/generator/match-bindings.stderr create mode 100644 src/test/ui/generator/reborrow-mut-upvar.stderr create mode 100644 src/test/ui/generator/too-live-local-in-immovable-gen.stderr create mode 100644 src/test/ui/generator/yield-in-args-rev.stderr create mode 100644 src/test/ui/generator/yield-in-box.stderr create mode 100644 src/test/ui/generator/yield-in-initializer.stderr create mode 100644 src/test/ui/generator/yield-subtype.stderr create mode 100644 src/test/ui/issues/issue-1460.stderr create mode 100644 src/test/ui/issues/issue-16256.stderr create mode 100644 src/test/ui/nll/issue-48623-generator.stderr create mode 100644 src/test/ui/unused/unused-closure.rs create mode 100644 src/test/ui/unused/unused-closure.stderr diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index dcb44ab644498..8d8fb8c3c6098 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -203,6 +203,28 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { // Otherwise, we don't lint, to avoid false positives. _ => false, }, + ty::Closure(..) => { + cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { + let mut err = lint.build(&format!( + "unused {}closure{}{} that must be used", + descr_pre, plural_suffix, descr_post, + )); + err.note("closures are lazy and do nothing unless called"); + err.emit(); + }); + true + } + ty::Generator(..) => { + cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { + let mut err = lint.build(&format!( + "unused {}generator{}{} that must be used", + descr_pre, plural_suffix, descr_post, + )); + err.note("generators are lazy and do nothing unless resumed"); + err.emit(); + }); + true + } _ => false, } } diff --git a/src/test/ui/generator/issue-52398.rs b/src/test/ui/generator/issue-52398.rs index 54a1912582c1a..ada380d116cab 100644 --- a/src/test/ui/generator/issue-52398.rs +++ b/src/test/ui/generator/issue-52398.rs @@ -14,14 +14,14 @@ impl A { fn main() { // Test that the MIR local with type &A created for the auto-borrow adjustment // is caught by typeck - move || { + move || { //~ WARN unused generator that must be used A.test(yield); }; // Test that the std::cell::Ref temporary returned from the `borrow` call // is caught by typeck let y = RefCell::new(true); - static move || { + static move || { //~ WARN unused generator that must be used yield *y.borrow(); return "Done"; }; diff --git a/src/test/ui/generator/issue-52398.stderr b/src/test/ui/generator/issue-52398.stderr new file mode 100644 index 0000000000000..3f8ebb5a7389c --- /dev/null +++ b/src/test/ui/generator/issue-52398.stderr @@ -0,0 +1,24 @@ +warning: unused generator that must be used + --> $DIR/issue-52398.rs:17:5 + | +LL | / move || { +LL | | A.test(yield); +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: unused generator that must be used + --> $DIR/issue-52398.rs:24:5 + | +LL | / static move || { +LL | | yield *y.borrow(); +LL | | return "Done"; +LL | | }; + | |______^ + | + = note: generators are lazy and do nothing unless resumed + +warning: 2 warnings emitted + diff --git a/src/test/ui/generator/issue-57084.rs b/src/test/ui/generator/issue-57084.rs index 8aaa6a0e427d1..2a5c3dd0570f9 100644 --- a/src/test/ui/generator/issue-57084.rs +++ b/src/test/ui/generator/issue-57084.rs @@ -19,7 +19,7 @@ where F: Fn() -> () fn main() { let data = &vec![1]; - || { + || { //~ WARN unused generator that must be used let _to_pin = with(move || println!("{:p}", data)); loop { yield diff --git a/src/test/ui/generator/issue-57084.stderr b/src/test/ui/generator/issue-57084.stderr new file mode 100644 index 0000000000000..32a04f94dcbe8 --- /dev/null +++ b/src/test/ui/generator/issue-57084.stderr @@ -0,0 +1,16 @@ +warning: unused generator that must be used + --> $DIR/issue-57084.rs:22:5 + | +LL | / || { +LL | | let _to_pin = with(move || println!("{:p}", data)); +LL | | loop { +LL | | yield +LL | | } +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/generator/match-bindings.rs b/src/test/ui/generator/match-bindings.rs index 560d8e7103c0c..865904a57d41c 100644 --- a/src/test/ui/generator/match-bindings.rs +++ b/src/test/ui/generator/match-bindings.rs @@ -9,7 +9,7 @@ enum Enum { } fn main() { - || { + || { //~ WARN unused generator that must be used loop { if let true = true { match Enum::A(String::new()) { diff --git a/src/test/ui/generator/match-bindings.stderr b/src/test/ui/generator/match-bindings.stderr new file mode 100644 index 0000000000000..4fd1e26f0c8df --- /dev/null +++ b/src/test/ui/generator/match-bindings.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/match-bindings.rs:12:5 + | +LL | / || { +LL | | loop { +LL | | if let true = true { +LL | | match Enum::A(String::new()) { +... | +LL | | } +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/generator/reborrow-mut-upvar.rs b/src/test/ui/generator/reborrow-mut-upvar.rs index 785e38a7eb8a6..dbd9e24e205c8 100644 --- a/src/test/ui/generator/reborrow-mut-upvar.rs +++ b/src/test/ui/generator/reborrow-mut-upvar.rs @@ -3,7 +3,7 @@ #![feature(generators)] fn _run(bar: &mut i32) { - || { + || { //~ WARN unused generator that must be used { let _baz = &*bar; yield; diff --git a/src/test/ui/generator/reborrow-mut-upvar.stderr b/src/test/ui/generator/reborrow-mut-upvar.stderr new file mode 100644 index 0000000000000..ff511b76672e6 --- /dev/null +++ b/src/test/ui/generator/reborrow-mut-upvar.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/reborrow-mut-upvar.rs:6:5 + | +LL | / || { +LL | | { +LL | | let _baz = &*bar; +LL | | yield; +... | +LL | | *bar = 2; +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/generator/too-live-local-in-immovable-gen.rs b/src/test/ui/generator/too-live-local-in-immovable-gen.rs index f299a8aa72b25..7f118c88e5e6e 100644 --- a/src/test/ui/generator/too-live-local-in-immovable-gen.rs +++ b/src/test/ui/generator/too-live-local-in-immovable-gen.rs @@ -5,7 +5,7 @@ fn main() { unsafe { - static move || { + static move || { //~ WARN unused generator that must be used // Tests that the generator transformation finds out that `a` is not live // during the yield expression. Type checking will also compute liveness // and it should also find out that `a` is not live. diff --git a/src/test/ui/generator/too-live-local-in-immovable-gen.stderr b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr new file mode 100644 index 0000000000000..88dacff7b559b --- /dev/null +++ b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/too-live-local-in-immovable-gen.rs:8:9 + | +LL | / static move || { +LL | | // Tests that the generator transformation finds out that `a` is not live +LL | | // during the yield expression. Type checking will also compute liveness +LL | | // and it should also find out that `a` is not live. +... | +LL | | &a; +LL | | }; + | |__________^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/generator/yield-in-args-rev.rs b/src/test/ui/generator/yield-in-args-rev.rs index f9ab981121a11..4c99bb3ef5ee1 100644 --- a/src/test/ui/generator/yield-in-args-rev.rs +++ b/src/test/ui/generator/yield-in-args-rev.rs @@ -10,7 +10,7 @@ fn foo(_a: (), _b: &bool) {} fn bar() { - || { + || { //~ WARN unused generator that must be used let b = true; foo(yield, &b); }; diff --git a/src/test/ui/generator/yield-in-args-rev.stderr b/src/test/ui/generator/yield-in-args-rev.stderr new file mode 100644 index 0000000000000..a575bf886780a --- /dev/null +++ b/src/test/ui/generator/yield-in-args-rev.stderr @@ -0,0 +1,14 @@ +warning: unused generator that must be used + --> $DIR/yield-in-args-rev.rs:13:5 + | +LL | / || { +LL | | let b = true; +LL | | foo(yield, &b); +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/generator/yield-in-box.rs b/src/test/ui/generator/yield-in-box.rs index d8475715c7ce1..65f368df9cb33 100644 --- a/src/test/ui/generator/yield-in-box.rs +++ b/src/test/ui/generator/yield-in-box.rs @@ -6,7 +6,7 @@ fn main() { let x = 0i32; - || { + || { //~ WARN unused generator that must be used let y = 2u32; { let _t = box (&x, yield 0, &y); diff --git a/src/test/ui/generator/yield-in-box.stderr b/src/test/ui/generator/yield-in-box.stderr new file mode 100644 index 0000000000000..24de18edb0f8c --- /dev/null +++ b/src/test/ui/generator/yield-in-box.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/yield-in-box.rs:9:5 + | +LL | / || { +LL | | let y = 2u32; +LL | | { +LL | | let _t = box (&x, yield 0, &y); +... | +LL | | } +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/generator/yield-in-initializer.rs b/src/test/ui/generator/yield-in-initializer.rs index 8ff35d8ddf10f..2f8754c95715f 100644 --- a/src/test/ui/generator/yield-in-initializer.rs +++ b/src/test/ui/generator/yield-in-initializer.rs @@ -3,7 +3,7 @@ #![feature(generators)] fn main() { - static || { + static || { //~ WARN unused generator that must be used loop { // Test that `opt` is not live across the yield, even when borrowed in a loop // See https://github.com/rust-lang/rust/issues/52792 diff --git a/src/test/ui/generator/yield-in-initializer.stderr b/src/test/ui/generator/yield-in-initializer.stderr new file mode 100644 index 0000000000000..e79047ae7013c --- /dev/null +++ b/src/test/ui/generator/yield-in-initializer.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/yield-in-initializer.rs:6:5 + | +LL | / static || { +LL | | loop { +LL | | // Test that `opt` is not live across the yield, even when borrowed in a loop +LL | | // See https://github.com/rust-lang/rust/issues/52792 +... | +LL | | } +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/generator/yield-subtype.rs b/src/test/ui/generator/yield-subtype.rs index fe88d424dd165..cb3fc909145c2 100644 --- a/src/test/ui/generator/yield-subtype.rs +++ b/src/test/ui/generator/yield-subtype.rs @@ -8,7 +8,7 @@ fn bar<'a>() { let a: &'static str = "hi"; let b: &'a str = a; - || { + || { //~ WARN unused generator that must be used yield a; yield b; }; diff --git a/src/test/ui/generator/yield-subtype.stderr b/src/test/ui/generator/yield-subtype.stderr new file mode 100644 index 0000000000000..bded36a4cdaf7 --- /dev/null +++ b/src/test/ui/generator/yield-subtype.stderr @@ -0,0 +1,14 @@ +warning: unused generator that must be used + --> $DIR/yield-subtype.rs:11:5 + | +LL | / || { +LL | | yield a; +LL | | yield b; +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-1460.rs b/src/test/ui/issues/issue-1460.rs index 143a0387e218f..e663f7fd4c9bf 100644 --- a/src/test/ui/issues/issue-1460.rs +++ b/src/test/ui/issues/issue-1460.rs @@ -3,5 +3,5 @@ // pretty-expanded FIXME #23616 pub fn main() { - {|i: u32| if 1 == i { }}; + {|i: u32| if 1 == i { }}; //~ WARN unused closure that must be used } diff --git a/src/test/ui/issues/issue-1460.stderr b/src/test/ui/issues/issue-1460.stderr new file mode 100644 index 0000000000000..26f95f5af3dc5 --- /dev/null +++ b/src/test/ui/issues/issue-1460.stderr @@ -0,0 +1,11 @@ +warning: unused closure that must be used + --> $DIR/issue-1460.rs:6:5 + | +LL | {|i: u32| if 1 == i { }}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: closures are lazy and do nothing unless called + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-16256.rs b/src/test/ui/issues/issue-16256.rs index e566eede8d227..eec23437bcb06 100644 --- a/src/test/ui/issues/issue-16256.rs +++ b/src/test/ui/issues/issue-16256.rs @@ -3,5 +3,5 @@ fn main() { let mut buf = Vec::new(); - |c: u8| buf.push(c); + |c: u8| buf.push(c); //~ WARN unused closure that must be used } diff --git a/src/test/ui/issues/issue-16256.stderr b/src/test/ui/issues/issue-16256.stderr new file mode 100644 index 0000000000000..9c7312461c4a1 --- /dev/null +++ b/src/test/ui/issues/issue-16256.stderr @@ -0,0 +1,11 @@ +warning: unused closure that must be used + --> $DIR/issue-16256.rs:6:5 + | +LL | |c: u8| buf.push(c); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: closures are lazy and do nothing unless called + +warning: 1 warning emitted + diff --git a/src/test/ui/liveness/liveness-upvars.rs b/src/test/ui/liveness/liveness-upvars.rs index b2837e74b8c51..98ea4d71ccf4f 100644 --- a/src/test/ui/liveness/liveness-upvars.rs +++ b/src/test/ui/liveness/liveness-upvars.rs @@ -27,7 +27,7 @@ pub fn f() { let mut c = 0; // Captured by value, but variable is dead on entry. - move || { + let _ = move || { c = 1; //~ WARN value captured by `c` is never read println!("{}", c); }; @@ -37,7 +37,7 @@ pub fn f() { }; // Read and written to, but never actually used. - move || { + let _ = move || { c += 1; //~ WARN unused variable: `c` }; let _ = async move { @@ -45,13 +45,13 @@ pub fn f() { //~| WARN unused variable: `c` }; - move || { + let _ = move || { println!("{}", c); // Value is read by closure itself on later invocations. c += 1; }; let b = Box::new(42); - move || { + let _ = move || { println!("{}", c); // Never read because this is FnOnce closure. c += 1; //~ WARN value assigned to `c` is never read @@ -67,12 +67,12 @@ pub fn f() { pub fn nested() { let mut d = None; let mut e = None; - || { - || { + let _ = || { + let _ = || { d = Some("d1"); //~ WARN value assigned to `d` is never read d = Some("d2"); }; - move || { + let _ = 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 @@ -81,7 +81,7 @@ pub fn nested() { } pub fn g(mut v: T) { - |r| { + let _ = |r| { if r { v = T::default(); //~ WARN value assigned to `v` is never read } else { @@ -92,7 +92,7 @@ pub fn g(mut v: T) { pub fn h() { let mut z = T::default(); - move |b| { + let _ = move |b| { loop { if b { z = T::default(); //~ WARN value assigned to `z` is never read diff --git a/src/test/ui/nll/capture-mut-ref.fixed b/src/test/ui/nll/capture-mut-ref.fixed index 639de2813a90a..2dacb26b6eba5 100644 --- a/src/test/ui/nll/capture-mut-ref.fixed +++ b/src/test/ui/nll/capture-mut-ref.fixed @@ -8,7 +8,7 @@ pub fn mutable_upvar() { let x = &mut 0; //~^ ERROR - move || { + let _ = move || { *x = 1; }; } diff --git a/src/test/ui/nll/capture-mut-ref.rs b/src/test/ui/nll/capture-mut-ref.rs index 89f49e1ea5186..56e01f7b7764b 100644 --- a/src/test/ui/nll/capture-mut-ref.rs +++ b/src/test/ui/nll/capture-mut-ref.rs @@ -8,7 +8,7 @@ pub fn mutable_upvar() { let mut x = &mut 0; //~^ ERROR - move || { + let _ = move || { *x = 1; }; } diff --git a/src/test/ui/nll/issue-48623-generator.rs b/src/test/ui/nll/issue-48623-generator.rs index ba3eccff495e5..08d2584ee5efd 100644 --- a/src/test/ui/nll/issue-48623-generator.rs +++ b/src/test/ui/nll/issue-48623-generator.rs @@ -12,7 +12,7 @@ impl Drop for WithDrop { fn reborrow_from_generator(r: &mut ()) { let d = WithDrop; - move || { d; yield; &mut *r }; + move || { d; yield; &mut *r }; //~ WARN unused generator that must be used } fn main() {} diff --git a/src/test/ui/nll/issue-48623-generator.stderr b/src/test/ui/nll/issue-48623-generator.stderr new file mode 100644 index 0000000000000..70a83e46ff08e --- /dev/null +++ b/src/test/ui/nll/issue-48623-generator.stderr @@ -0,0 +1,11 @@ +warning: unused generator that must be used + --> $DIR/issue-48623-generator.rs:15:5 + | +LL | move || { d; yield; &mut *r }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: generators are lazy and do nothing unless resumed + +warning: 1 warning emitted + diff --git a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs index 917c09801e175..bf5482056d4b4 100644 --- a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs +++ b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs @@ -7,9 +7,9 @@ mod a { fn b() { - || { + (|| { #[main] fn c() { panic!(); } - }; + })(); } } diff --git a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs index e5b19db782231..470904fd3911b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs @@ -2,6 +2,7 @@ // pretty-expanded FIXME #23616 #![deny(unused_mut)] +#![allow(unused_must_use)] // Test that mutating a mutable upvar in a capture-by-value unboxed // closure does not ice (issue #18238) and marks the upvar as used diff --git a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr index 4dfd1bb307574..1254f8dbc5e2c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr @@ -1,5 +1,5 @@ warning: unused variable: `x` - --> $DIR/unboxed-closures-move-mutable.rs:16:17 + --> $DIR/unboxed-closures-move-mutable.rs:17:17 | LL | move || x += 1; | ^ @@ -8,7 +8,7 @@ LL | move || x += 1; = help: did you mean to capture by reference instead? warning: unused variable: `x` - --> $DIR/unboxed-closures-move-mutable.rs:20:17 + --> $DIR/unboxed-closures-move-mutable.rs:21:17 | LL | move || x += 1; | ^ diff --git a/src/test/ui/unused/unused-closure.rs b/src/test/ui/unused/unused-closure.rs new file mode 100644 index 0000000000000..637d8bb43a77b --- /dev/null +++ b/src/test/ui/unused/unused-closure.rs @@ -0,0 +1,40 @@ +// Test that closures and generators are "must use" types. +// edition:2018 + +#![feature(async_closure)] +#![feature(const_in_array_repeat_expressions)] +#![feature(generators)] +#![deny(unused_must_use)] + +fn unused() { + || { //~ ERROR unused closure that must be used + println!("Hello!"); + }; + + async {}; //~ ERROR unused implementer of `std::future::Future` that must be used + || async {}; //~ ERROR unused closure that must be used + async || {}; //~ ERROR unused closure that must be used + + + [Box::new([|| {}; 10]); 1]; //~ ERROR unused array of boxed arrays of closures that must be used + + [|| { //~ ERROR unused array of generators that must be used + yield 42u32; + }; 42]; + + vec![|| "a"].pop().unwrap(); //~ ERROR unused closure that must be used + + let b = false; + || true; //~ ERROR unused closure that must be used + println!("{}", b); +} + +fn ignored() { + let _ = || {}; + let _ = || yield 42; +} + +fn main() { + unused(); + ignored(); +} diff --git a/src/test/ui/unused/unused-closure.stderr b/src/test/ui/unused/unused-closure.stderr new file mode 100644 index 0000000000000..9dc73fb7abeab --- /dev/null +++ b/src/test/ui/unused/unused-closure.stderr @@ -0,0 +1,75 @@ +error: unused closure that must be used + --> $DIR/unused-closure.rs:10:5 + | +LL | / || { +LL | | println!("Hello!"); +LL | | }; + | |______^ + | +note: the lint level is defined here + --> $DIR/unused-closure.rs:7:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + = note: closures are lazy and do nothing unless called + +error: unused implementer of `std::future::Future` that must be used + --> $DIR/unused-closure.rs:14:5 + | +LL | async {}; + | ^^^^^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused closure that must be used + --> $DIR/unused-closure.rs:15:5 + | +LL | || async {}; + | ^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused closure that must be used + --> $DIR/unused-closure.rs:16:5 + | +LL | async || {}; + | ^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused array of boxed arrays of closures that must be used + --> $DIR/unused-closure.rs:19:5 + | +LL | [Box::new([|| {}; 10]); 1]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused array of generators that must be used + --> $DIR/unused-closure.rs:21:5 + | +LL | / [|| { +LL | | yield 42u32; +LL | | }; 42]; + | |___________^ + | + = note: generators are lazy and do nothing unless resumed + +error: unused closure that must be used + --> $DIR/unused-closure.rs:25:5 + | +LL | vec![|| "a"].pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused closure that must be used + --> $DIR/unused-closure.rs:28:9 + | +LL | || true; + | ^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: aborting due to 8 previous errors + diff --git a/src/test/ui/unused/unused-mut-warning-captured-var.fixed b/src/test/ui/unused/unused-mut-warning-captured-var.fixed index b67b2a7259be0..c21f18015c11a 100644 --- a/src/test/ui/unused/unused-mut-warning-captured-var.fixed +++ b/src/test/ui/unused/unused-mut-warning-captured-var.fixed @@ -5,5 +5,5 @@ fn main() { let x = 1; //~^ ERROR: variable does not need to be mutable - move|| { println!("{}", x); }; + (move|| { println!("{}", x); })(); } diff --git a/src/test/ui/unused/unused-mut-warning-captured-var.rs b/src/test/ui/unused/unused-mut-warning-captured-var.rs index 8726c4f173fa3..3119d83a0ebf8 100644 --- a/src/test/ui/unused/unused-mut-warning-captured-var.rs +++ b/src/test/ui/unused/unused-mut-warning-captured-var.rs @@ -5,5 +5,5 @@ fn main() { let mut x = 1; //~^ ERROR: variable does not need to be mutable - move|| { println!("{}", x); }; + (move|| { println!("{}", x); })(); } diff --git a/src/test/ui/weird-exprs.rs b/src/test/ui/weird-exprs.rs index d812bbd011e0e..916cabbfb8c94 100644 --- a/src/test/ui/weird-exprs.rs +++ b/src/test/ui/weird-exprs.rs @@ -5,7 +5,7 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] #![allow(unreachable_code)] -#![allow(unused_braces, unused_parens)] +#![allow(unused_braces, unused_must_use, unused_parens)] #![recursion_limit = "256"] From 4f28534138ddc268d362e3cb3b22bb0076ad9680 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 28 Jul 2020 14:34:18 +0200 Subject: [PATCH 02/11] symbol mangling: use ty::print::Print for consts --- src/librustc_symbol_mangling/v0.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs index ecf27fbf54220..676fee590b3c5 100644 --- a/src/librustc_symbol_mangling/v0.rs +++ b/src/librustc_symbol_mangling/v0.rs @@ -636,9 +636,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { } GenericArgKind::Const(c) => { self.push("K"); - // FIXME(const_generics) implement `ty::print::Print` on `ty::Const`. - // self = c.print(self)?; - self = self.print_const(c)?; + self = c.print(self)?; } } } From dcce6cb5112a3c3f4ec9e439961ff310bcb878cd Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sat, 25 Jul 2020 14:55:51 +0200 Subject: [PATCH 03/11] Remove links to rejected errata 4406 for RFC 4291 --- library/std/src/net/ip.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 0f0be2c488314..21c2667f63f2a 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1265,15 +1265,12 @@ impl Ipv6Addr { /// # See also /// /// - [IETF RFC 4291 section 2.5.6] - /// - [RFC 4291 errata 4406] /// - [`is_unicast_link_local()`] /// /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 /// [`true`]: ../../std/primitive.bool.html - /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local - /// pub fn is_unicast_link_local_strict(&self) -> bool { (self.segments()[0] & 0xffff) == 0xfe80 && (self.segments()[1] & 0xffff) == 0 @@ -1324,13 +1321,10 @@ impl Ipv6Addr { /// # See also /// /// - [IETF RFC 4291 section 2.4] - /// - [RFC 4291 errata 4406] /// /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 /// [`true`]: ../../std/primitive.bool.html - /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict - /// pub fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 } From 90d00527d147c1ef9bca3ea57ea2f80fbea81e56 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Sun, 26 Jul 2020 22:00:29 +0200 Subject: [PATCH 04/11] Add note to clearly mark the RFC as rejected --- library/std/src/net/ip.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 21c2667f63f2a..a64b43ca3ad45 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1265,11 +1265,14 @@ impl Ipv6Addr { /// # See also /// /// - [IETF RFC 4291 section 2.5.6] + /// - [RFC 4291 errata 4406] (which has been rejected but provides useful + /// insight) /// - [`is_unicast_link_local()`] /// /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local pub fn is_unicast_link_local_strict(&self) -> bool { (self.segments()[0] & 0xffff) == 0xfe80 @@ -1321,9 +1324,12 @@ impl Ipv6Addr { /// # See also /// /// - [IETF RFC 4291 section 2.4] + /// - [RFC 4291 errata 4406] (which has been rejected but provides useful + /// insight) /// /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict pub fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 From 27e1b0632cea37733050b7e130c3fbaf0b70b52d Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 29 Jul 2020 07:38:06 +0000 Subject: [PATCH 05/11] Explain why inline default ToString impl --- library/alloc/src/string.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 05398ca68c8ba..d7d7b6bd157bc 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2196,6 +2196,9 @@ pub trait ToString { /// since `fmt::Write for String` never returns an error itself. #[stable(feature = "rust1", since = "1.0.0")] impl ToString for T { + // A common guideline is to not inline generic functions. However, + // remove `#[inline]` from this method causes non-negligible regression. + // See as last attempt try to remove it. #[inline] default fn to_string(&self) -> String { use fmt::Write; From 1b4a6a5183b6b1cfcbbabc530da3f013e681202b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 27 Jul 2020 00:00:00 +0000 Subject: [PATCH 06/11] Link to syntax section when referencing it --- library/alloc/src/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 26077f3c8d150..b83b3024295b4 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -83,7 +83,7 @@ //! # Formatting Parameters //! //! Each argument being formatted can be transformed by a number of formatting -//! parameters (corresponding to `format_spec` in the syntax above). These +//! parameters (corresponding to `format_spec` in [the syntax](#syntax)). These //! parameters affect the string representation of what's being formatted. //! //! ## Width From 1fb67363bfeb66a956297a81bc1c95c8aaee056a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 29 Jul 2020 10:57:16 +0200 Subject: [PATCH 07/11] =?UTF-8?q?Remove=20deprecated=20unstable=20`{Box,Rc?= =?UTF-8?q?,Arc}::into=5Fraw=5Fnon=5Fnull`=C2=A0functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FCP: https://github.com/rust-lang/rust/issues/47336#issuecomment-619369613 --- library/alloc/src/boxed.rs | 46 +------------------------------------- library/alloc/src/rc.rs | 23 ------------------- library/alloc/src/sync.rs | 23 ------------------- 3 files changed, 1 insertion(+), 91 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index f225aa18853c7..65e0c984fe893 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -143,7 +143,7 @@ use core::ops::{ CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, }; use core::pin::Pin; -use core::ptr::{self, NonNull, Unique}; +use core::ptr::{self, Unique}; use core::task::{Context, Poll}; use crate::alloc::{self, AllocInit, AllocRef, Global}; @@ -451,50 +451,6 @@ impl Box { Box::leak(b) as *mut T } - /// Consumes the `Box`, returning the wrapped pointer as `NonNull`. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `Box`. In particular, the - /// caller should properly destroy `T` and release the memory. The - /// easiest way to do so is to convert the `NonNull` pointer - /// into a raw pointer and back into a `Box` with the [`Box::from_raw`] - /// function. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `Box::into_raw_non_null(b)` - /// instead of `b.into_raw_non_null()`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// [`Box::from_raw`]: struct.Box.html#method.from_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(box_into_raw_non_null)] - /// #![allow(deprecated)] - /// - /// let x = Box::new(5); - /// let ptr = Box::into_raw_non_null(x); - /// - /// // Clean up the memory by converting the NonNull pointer back - /// // into a Box and letting the Box be dropped. - /// let x = unsafe { Box::from_raw(ptr.as_ptr()) }; - /// ``` - #[unstable(feature = "box_into_raw_non_null", issue = "47336")] - #[rustc_deprecated( - since = "1.44.0", - reason = "use `Box::leak(b).into()` or `NonNull::from(Box::leak(b))` instead" - )] - #[inline] - pub fn into_raw_non_null(b: Box) -> NonNull { - // Box is recognized as a "unique pointer" by Stacked Borrows, but internally it is a - // raw pointer for the type system. Turning it directly into a raw pointer would not be - // recognized as "releasing" the unique pointer to permit aliased raw accesses, - // so all raw pointer methods go through `leak` which creates a (unique) - // mutable reference. Turning *that* to a raw pointer behaves correctly. - Box::leak(b).into() - } - #[unstable( feature = "ptr_internals", issue = "none", diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 96dfc2f42519b..d3450cfbc814e 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -645,29 +645,6 @@ impl Rc { unsafe { Self::from_ptr(rc_ptr) } } - /// Consumes the `Rc`, returning the wrapped pointer as `NonNull`. - /// - /// # Examples - /// - /// ``` - /// #![feature(rc_into_raw_non_null)] - /// #![allow(deprecated)] - /// - /// use std::rc::Rc; - /// - /// let x = Rc::new("hello".to_owned()); - /// let ptr = Rc::into_raw_non_null(x); - /// let deref = unsafe { ptr.as_ref() }; - /// assert_eq!(deref, "hello"); - /// ``` - #[unstable(feature = "rc_into_raw_non_null", issue = "47336")] - #[rustc_deprecated(since = "1.44.0", reason = "use `Rc::into_raw` instead")] - #[inline] - pub fn into_raw_non_null(this: Self) -> NonNull { - // safe because Rc guarantees its pointer is non-null - unsafe { NonNull::new_unchecked(Rc::into_raw(this) as *mut _) } - } - /// Creates a new [`Weak`][weak] pointer to this allocation. /// /// [weak]: struct.Weak.html diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 8a5f1ee5076b9..906beba2a6296 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -646,29 +646,6 @@ impl Arc { } } - /// Consumes the `Arc`, returning the wrapped pointer as `NonNull`. - /// - /// # Examples - /// - /// ``` - /// #![feature(rc_into_raw_non_null)] - /// #![allow(deprecated)] - /// - /// use std::sync::Arc; - /// - /// let x = Arc::new("hello".to_owned()); - /// let ptr = Arc::into_raw_non_null(x); - /// let deref = unsafe { ptr.as_ref() }; - /// assert_eq!(deref, "hello"); - /// ``` - #[unstable(feature = "rc_into_raw_non_null", issue = "47336")] - #[rustc_deprecated(since = "1.44.0", reason = "use `Arc::into_raw` instead")] - #[inline] - pub fn into_raw_non_null(this: Self) -> NonNull { - // safe because Arc guarantees its pointer is non-null - unsafe { NonNull::new_unchecked(Arc::into_raw(this) as *mut _) } - } - /// Creates a new [`Weak`][weak] pointer to this allocation. /// /// [weak]: struct.Weak.html From 82766cb78ae41547e1e331ef0cb417a637ea0e6e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 29 Jul 2020 03:25:38 -0700 Subject: [PATCH 08/11] Fix some typos in src/librustdoc/clean/auto_trait.rs --- src/librustdoc/clean/auto_trait.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 98d8f100b27d9..b170b4131464a 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -430,14 +430,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } // Converts the calculated ParamEnv and lifetime information to a clean::Generics, suitable for - // display on the docs page. Cleaning the Predicates produces sub-optimal WherePredicate's, + // display on the docs page. Cleaning the Predicates produces sub-optimal `WherePredicate`s, // so we fix them up: // // * Multiple bounds for the same type are coalesced into one: e.g., 'T: Copy', 'T: Debug' // becomes 'T: Copy + Debug' // * Fn bounds are handled specially - instead of leaving it as 'T: Fn(), = // K', we use the dedicated syntax 'T: Fn() -> K' - // * We explcitly add a '?Sized' bound if we didn't find any 'Sized' predicates for a type + // * We explicitly add a '?Sized' bound if we didn't find any 'Sized' predicates for a type fn param_env_to_generics( &self, tcx: TyCtxt<'tcx>, @@ -588,7 +588,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .args; match args { - // Convert somethiung like ' = u8' + // Convert something like ' = u8' // to 'T: Iterator' GenericArgs::AngleBracketed { ref mut bindings, .. @@ -712,7 +712,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // since FxHasher has different behavior for 32-bit and 64-bit platforms. // // Obviously, it's extremely undesirable for documentation rendering - // to be depndent on the platform it's run on. Apart from being confusing + // to be dependent on the platform it's run on. Apart from being confusing // to end users, it makes writing tests much more difficult, as predicates // can appear in any order in the final result. // From 897149a88323f0b5b9bc16e9b41b39cbc3bdae0e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Jul 2020 15:44:19 +0200 Subject: [PATCH 09/11] fence docs: fix example Mutex --- library/core/src/sync/atomic.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index fcae6c86774f2..f31a4a0b7518d 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2649,7 +2649,8 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { /// } /// /// pub fn lock(&self) { -/// while !self.flag.compare_and_swap(false, true, Ordering::Relaxed) {} +/// // Wait until the old value is `false`. +/// while self.flag.compare_and_swap(false, true, Ordering::Relaxed) != false {} /// // This fence synchronizes-with store in `unlock`. /// fence(Ordering::Acquire); /// } From ab166cfffab62128e78f18f0ba6e0e9d7d65e108 Mon Sep 17 00:00:00 2001 From: Takayuki Nakata Date: Wed, 29 Jul 2020 23:21:56 +0900 Subject: [PATCH 10/11] Fix broken link in unstable book `plugin` --- src/doc/unstable-book/src/language-features/plugin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 47ac986c224a9..1f010656bb854 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -35,7 +35,7 @@ of a library. Plugins can extend [Rust's lint infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with additional checks for code style, safety, etc. Now let's write a plugin -[`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs) +[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs) that warns about any item named `lintme`. ```rust,ignore From e9509273e6581dbdcebbcdb32f8aea3eb7604060 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Wed, 29 Jul 2020 16:26:09 -0600 Subject: [PATCH 11/11] Change the target data layout to specify more values This does not actually alter the previously specified important parts, but apparently `rustc` cares about more layout components than `cargo-xbuild` ever did. This extends the data layout to be fully specified layout, as given in the error from issue #74767 --- src/librustc_target/spec/thumbv4t_none_eabi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_target/spec/thumbv4t_none_eabi.rs b/src/librustc_target/spec/thumbv4t_none_eabi.rs index 31417b0154759..a8c78f057fc8a 100644 --- a/src/librustc_target/spec/thumbv4t_none_eabi.rs +++ b/src/librustc_target/spec/thumbv4t_none_eabi.rs @@ -29,7 +29,7 @@ pub fn target() -> TargetResult { * native integers are 32-bit * All other elements are default */ - data_layout: "e-S64-p:32:32-i64:64-m:e-n32".to_string(), + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), linker_flavor: LinkerFlavor::Ld, options: TargetOptions { linker: Some("arm-none-eabi-ld".to_string()),