From 1ca1483113936b0f23b612f82bb84881435c483b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 24 Apr 2017 20:25:30 -0700 Subject: [PATCH] Point at variable moved by closure --- .../borrowck/gather_loans/move_error.rs | 7 ++-- .../borrowck/borrowck-in-static.rs | 2 +- .../ui/borrowck/borrowck-in-static.stderr | 10 ++++++ ...es-move-upvar-from-non-once-ref-closure.rs | 2 +- ...ove-upvar-from-non-once-ref-closure.stderr | 11 ++++++ .../borrowck-call-is-borrow-issue-12224.rs | 17 ++++++++-- ...borrowck-call-is-borrow-issue-12224.stderr | 34 +++++++++++-------- 7 files changed, 63 insertions(+), 20 deletions(-) rename src/test/{compile-fail => ui}/borrowck/borrowck-in-static.rs (94%) create mode 100644 src/test/ui/borrowck/borrowck-in-static.stderr rename src/test/{compile-fail => ui/borrowck}/unboxed-closures-move-upvar-from-non-once-ref-closure.rs (93%) create mode 100644 src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index 3678c2e55c1fd..ebe2de5840954 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -11,6 +11,7 @@ use borrowck::BorrowckCtxt; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; +use rustc::middle::mem_categorization::NoteClosureEnv; use rustc::middle::mem_categorization::InteriorOffsetKind as Kind; use rustc::ty; use syntax::ast; @@ -71,10 +72,12 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let mut err = report_cannot_move_out_of(bccx, error.move_from.clone()); let mut is_first_note = true; for move_to in &error.move_to_places { - err = note_move_destination(err, move_to.span, - move_to.name, is_first_note); + err = note_move_destination(err, move_to.span, move_to.name, is_first_note); is_first_note = false; } + if let NoteClosureEnv(upvar_id) = error.move_from.note { + err.span_label(bccx.tcx.hir.span(upvar_id.var_id), &"captured outer variable"); + } err.emit(); } } diff --git a/src/test/compile-fail/borrowck/borrowck-in-static.rs b/src/test/ui/borrowck/borrowck-in-static.rs similarity index 94% rename from src/test/compile-fail/borrowck/borrowck-in-static.rs rename to src/test/ui/borrowck/borrowck-in-static.rs index 16b0e8638de39..9244c12347d95 100644 --- a/src/test/compile-fail/borrowck/borrowck-in-static.rs +++ b/src/test/ui/borrowck/borrowck-in-static.rs @@ -11,7 +11,7 @@ // check that borrowck looks inside consts/statics static FN : &'static (Fn() -> (BoxBox>) + Sync) = &|| { - let x = Box::new(0); + let x = Box::new(0); //~ NOTE moved Box::new(|| x) //~ ERROR cannot move out of captured outer variable }; diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr new file mode 100644 index 0000000000000..6083a82b1b6de --- /dev/null +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -0,0 +1,10 @@ +error[E0507]: cannot move out of captured outer variable in an `Fn` closure + --> $DIR/borrowck-in-static.rs:15:17 + | +14 | let x = Box::new(0); //~ NOTE moved + | - captured outer variable +15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable + | ^ cannot move out of captured outer variable in an `Fn` closure + +error: aborting due to previous error + diff --git a/src/test/compile-fail/unboxed-closures-move-upvar-from-non-once-ref-closure.rs b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs similarity index 93% rename from src/test/compile-fail/unboxed-closures-move-upvar-from-non-once-ref-closure.rs rename to src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs index cd9f1636c3f4d..9c89c26de006a 100644 --- a/src/test/compile-fail/unboxed-closures-move-upvar-from-non-once-ref-closure.rs +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs @@ -16,7 +16,7 @@ fn call(f: F) where F : Fn() { } fn main() { - let y = vec![format!("World")]; + let y = vec![format!("World")]; //~ NOTE moved call(|| { y.into_iter(); //~^ ERROR cannot move out of captured outer variable in an `Fn` closure diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr new file mode 100644 index 0000000000000..dbfcb2e0c2f95 --- /dev/null +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -0,0 +1,11 @@ +error[E0507]: cannot move out of captured outer variable in an `Fn` closure + --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9 + | +19 | let y = vec![format!("World")]; //~ NOTE moved + | - captured outer variable +20 | call(|| { +21 | y.into_iter(); + | ^ cannot move out of captured outer variable in an `Fn` closure + +error: aborting due to previous error + diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs index 6264d11186452..29fea052b06c2 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -21,8 +21,11 @@ struct Test<'a> { fn call(mut f: F) where F: FnMut(Fn) { f(Box::new(|| { //~^ ERROR: cannot borrow `f` as mutable more than once + //~| NOTE first mutable borrow occurs here + //~| NOTE second mutable borrow occurs here f((Box::new(|| {}))) })); + //~^ NOTE first borrow ends here } fn test1() { @@ -32,7 +35,10 @@ fn test1() { } fn test2(f: &F) where F: FnMut() { - (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable + //~^ NOTE use `&mut F` here to make mutable + (*f)(); + //~^ ERROR cannot borrow immutable borrowed content `*f` as mutable + //~| NOTE cannot borrow as mutable } fn test3(f: &mut F) where F: FnMut() { @@ -40,7 +46,10 @@ fn test3(f: &mut F) where F: FnMut() { } fn test4(f: &Test) { - f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable + //~^ NOTE use `&mut Test` here to make mutable + f.f.call_mut(()) + //~^ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable + //~| NOTE cannot borrow as mutable } fn test5(f: &mut Test) { @@ -57,10 +66,14 @@ fn test6() { fn test7() { fn foo(_: F) where F: FnMut(Box, isize) {} let mut f = |g: Box, b: isize| {}; + //~^ NOTE moved f(Box::new(|a| { + //~^ NOTE borrow of `f` occurs here foo(f); //~^ ERROR cannot move `f` into closure because it is borrowed //~| ERROR cannot move out of captured outer variable in an `FnMut` closure + //~| NOTE move into closure occurs here + //~| NOTE cannot move out of captured outer variable in an `FnMut` closure }), 3); } diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index 58b3f205fe352..4ece8bc6af10f 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -5,40 +5,46 @@ error[E0499]: cannot borrow `f` as mutable more than once at a time | - ^^ second mutable borrow occurs here | | | first mutable borrow occurs here -23 | //~^ ERROR: cannot borrow `f` as mutable more than once -24 | f((Box::new(|| {}))) +... +26 | f((Box::new(|| {}))) | - borrow occurs due to use of `f` in closure -25 | })); +27 | })); | - first borrow ends here error: cannot borrow immutable borrowed content `*f` as mutable - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:39:5 | -34 | fn test2(f: &F) where F: FnMut() { +37 | fn test2(f: &F) where F: FnMut() { | -- use `&mut F` here to make mutable -35 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable +38 | //~^ NOTE use `&mut F` here to make mutable +39 | (*f)(); | ^^^^ cannot borrow as mutable error: cannot borrow immutable `Box` content `*f.f` as mutable - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:43:5 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:50:5 | -42 | fn test4(f: &Test) { +48 | fn test4(f: &Test) { | ----- use `&mut Test` here to make mutable -43 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable +49 | //~^ NOTE use `&mut Test` here to make mutable +50 | f.f.call_mut(()) | ^^^ cannot borrow as mutable error[E0504]: cannot move `f` into closure because it is borrowed - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:72:13 | -60 | f(Box::new(|a| { +70 | f(Box::new(|a| { | - borrow of `f` occurs here -61 | foo(f); +71 | //~^ NOTE borrow of `f` occurs here +72 | foo(f); | ^ move into closure occurs here error[E0507]: cannot move out of captured outer variable in an `FnMut` closure - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:72:13 | -61 | foo(f); +68 | let mut f = |g: Box, b: isize| {}; + | ----- captured outer variable +... +72 | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure error: aborting due to 5 previous errors