From 37c2657d7a9dba99cb9f0beb9489837181ffc0e2 Mon Sep 17 00:00:00 2001 From: Ramana Venkata Date: Sun, 31 Dec 2017 18:24:00 +0530 Subject: [PATCH 1/2] Add comment --- src/librustc_mir/borrow_check/error_reporting.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 1d9e05f677439..949ee7e2a06b5 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -177,6 +177,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => return None, }; + + // When a closure upvar is assigned, it generates the necessary borrows and moves just + // above it and they all have the same span (including the upvar assignment). So, we are + // searching for closure upvar assignment. for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { if maybe_closure_span != stmt.source_info.span { break; From 433f5df85137d6cc5776dad90df561515c3a3502 Mon Sep 17 00:00:00 2001 From: Ramana Venkata Date: Mon, 1 Jan 2018 19:51:17 +0530 Subject: [PATCH 2/2] Fix error message of move into closure while being borrowed --- .../borrow_check/error_reporting.rs | 27 +++++++++++++++++-- src/librustc_mir/borrow_check/mod.rs | 12 ++++++++- src/test/compile-fail/E0504.rs | 10 ++++--- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 949ee7e2a06b5..ae52cf053b321 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -141,6 +141,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.emit(); } + pub(super) fn report_move_into_closure( + &mut self, + context: Context, + (place, span): (&Place<'tcx>, Span), + borrow: &BorrowData<'tcx>, + ) { + let borrow_msg = match self.describe_place(&borrow.borrowed_place) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + let mut err = self.tcx.cannot_move_into_closure( + span, + &self.describe_place(place).unwrap_or("_".to_owned()), + Origin::Mir, + ); + err.span_label( + self.retrieve_borrow_span(borrow), + format!("borrow of {} occurs here", borrow_msg), + ); + err.span_label(span, format!("move into closure occurs here")); + self.explain_why_borrow_contains_point(context, borrow, &mut err); + err.emit(); + } + pub(super) fn report_use_while_mutably_borrowed( &mut self, context: Context, @@ -164,7 +188,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// the local assigned at `location`. /// This is done by searching in statements succeeding `location` /// and originating from `maybe_closure_span`. - fn find_closure_span( + pub(super) fn find_closure_span( &self, maybe_closure_span: Span, location: Location, @@ -177,7 +201,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => return None, }; - // When a closure upvar is assigned, it generates the necessary borrows and moves just // above it and they all have the same span (including the upvar assignment). So, we are // searching for closure upvar assignment. diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4eb664e4856b4..c804340330050 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -849,7 +849,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } WriteKind::Move => { error_reported = true; - this.report_move_out_while_borrowed(context, place_span, &borrow) + + // If the move occurs due to a closure, then we want to show the span + // of the place where it's used in the closure. + let closure_span = this.find_closure_span(place_span.1, context.loc); + if let Some((_, var_span)) = closure_span { + let place_span = (place_span.0, var_span); + this.report_move_into_closure(context, place_span, &borrow); + } else { + this.report_move_out_while_borrowed(context, place_span, &borrow); + } + } } Control::Break diff --git a/src/test/compile-fail/E0504.rs b/src/test/compile-fail/E0504.rs index c594f2415209d..713193d9317e0 100644 --- a/src/test/compile-fail/E0504.rs +++ b/src/test/compile-fail/E0504.rs @@ -8,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z borrowck=mir + struct FancyNum { num: u8, } fn main() { - let fancy_num = FancyNum { num: 5 }; + let mut fancy_num = FancyNum { num: 5 }; let fancy_ref = &fancy_num; let x = move || { - println!("child function: {}", fancy_num.num); //~ ERROR E0504 + println!("child function: {}", fancy_num.num); + //[ast]~^ ERROR cannot move `fancy_num` into closure because it is borrowed + //[mir]~^^ ERROR cannot move `fancy_num` into closure because it is borrowed }; - x(); println!("main function: {}", fancy_ref.num); }