Skip to content

Commit 433f5df

Browse files
committed
Fix error message of move into closure while being borrowed
1 parent 37c2657 commit 433f5df

File tree

3 files changed

+43
-6
lines changed

3 files changed

+43
-6
lines changed

src/librustc_mir/borrow_check/error_reporting.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
141141
err.emit();
142142
}
143143

144+
pub(super) fn report_move_into_closure(
145+
&mut self,
146+
context: Context,
147+
(place, span): (&Place<'tcx>, Span),
148+
borrow: &BorrowData<'tcx>,
149+
) {
150+
let borrow_msg = match self.describe_place(&borrow.borrowed_place) {
151+
Some(name) => format!("`{}`", name),
152+
None => "value".to_owned(),
153+
};
154+
let mut err = self.tcx.cannot_move_into_closure(
155+
span,
156+
&self.describe_place(place).unwrap_or("_".to_owned()),
157+
Origin::Mir,
158+
);
159+
err.span_label(
160+
self.retrieve_borrow_span(borrow),
161+
format!("borrow of {} occurs here", borrow_msg),
162+
);
163+
err.span_label(span, format!("move into closure occurs here"));
164+
self.explain_why_borrow_contains_point(context, borrow, &mut err);
165+
err.emit();
166+
}
167+
144168
pub(super) fn report_use_while_mutably_borrowed(
145169
&mut self,
146170
context: Context,
@@ -164,7 +188,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
164188
/// the local assigned at `location`.
165189
/// This is done by searching in statements succeeding `location`
166190
/// and originating from `maybe_closure_span`.
167-
fn find_closure_span(
191+
pub(super) fn find_closure_span(
168192
&self,
169193
maybe_closure_span: Span,
170194
location: Location,
@@ -177,7 +201,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
177201
_ => return None,
178202
};
179203

180-
181204
// When a closure upvar is assigned, it generates the necessary borrows and moves just
182205
// above it and they all have the same span (including the upvar assignment). So, we are
183206
// searching for closure upvar assignment.

src/librustc_mir/borrow_check/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
849849
}
850850
WriteKind::Move => {
851851
error_reported = true;
852-
this.report_move_out_while_borrowed(context, place_span, &borrow)
852+
853+
// If the move occurs due to a closure, then we want to show the span
854+
// of the place where it's used in the closure.
855+
let closure_span = this.find_closure_span(place_span.1, context.loc);
856+
if let Some((_, var_span)) = closure_span {
857+
let place_span = (place_span.0, var_span);
858+
this.report_move_into_closure(context, place_span, &borrow);
859+
} else {
860+
this.report_move_out_while_borrowed(context, place_span, &borrow);
861+
}
862+
853863
}
854864
}
855865
Control::Break

src/test/compile-fail/E0504.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,22 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// revisions: ast mir
12+
//[mir]compile-flags: -Z borrowck=mir
13+
1114
struct FancyNum {
1215
num: u8,
1316
}
1417

1518
fn main() {
16-
let fancy_num = FancyNum { num: 5 };
19+
let mut fancy_num = FancyNum { num: 5 };
1720
let fancy_ref = &fancy_num;
1821

1922
let x = move || {
20-
println!("child function: {}", fancy_num.num); //~ ERROR E0504
23+
println!("child function: {}", fancy_num.num);
24+
//[ast]~^ ERROR cannot move `fancy_num` into closure because it is borrowed
25+
//[mir]~^^ ERROR cannot move `fancy_num` into closure because it is borrowed
2126
};
2227

23-
x();
2428
println!("main function: {}", fancy_ref.num);
2529
}

0 commit comments

Comments
 (0)