Skip to content

Commit 1241274

Browse files
committed
Add specific message when moving from upvars in a non-FnOnce closure
1 parent 341e5e3 commit 1241274

8 files changed

+44
-30
lines changed

src/librustc_mir/borrow_check/move_errors.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use rustc::hir;
1212
use rustc::mir::*;
1313
use rustc::ty;
14+
use rustc_data_structures::indexed_vec::Idx;
1415
use rustc_errors::DiagnosticBuilder;
1516
use syntax_pos::Span;
1617

@@ -230,14 +231,43 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
230231
IllegalMoveOriginKind::Static => {
231232
self.tcx.cannot_move_out_of(span, "static item", origin)
232233
}
233-
IllegalMoveOriginKind::BorrowedContent { target_ty: ty } => {
234+
IllegalMoveOriginKind::BorrowedContent { target_place: place } => {
234235
// Inspect the type of the content behind the
235236
// borrow to provide feedback about why this
236237
// was a move rather than a copy.
238+
let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
237239
match ty.sty {
238240
ty::TyArray(..) | ty::TySlice(..) => self
239241
.tcx
240242
.cannot_move_out_of_interior_noncopy(span, ty, None, origin),
243+
ty::TyClosure(def_id, closure_substs)
244+
if !self.mir.upvar_decls.is_empty()
245+
&& {
246+
match place {
247+
Place::Projection(ref proj) => {
248+
proj.base == Place::Local(Local::new(1))
249+
}
250+
Place::Local(_) | Place::Static(_) => unreachable!(),
251+
}
252+
} =>
253+
{
254+
let closure_kind_ty =
255+
closure_substs.closure_kind_ty(def_id, self.tcx);
256+
let closure_kind = closure_kind_ty.to_opt_closure_kind();
257+
let place_description = match closure_kind {
258+
Some(ty::ClosureKind::Fn) => {
259+
"captured variable in an `Fn` closure"
260+
}
261+
Some(ty::ClosureKind::FnMut) => {
262+
"captured variable in an `FnMut` closure"
263+
}
264+
Some(ty::ClosureKind::FnOnce) => {
265+
bug!("closure kind does not match first argument type")
266+
}
267+
None => bug!("closure kind not inferred by borrowck"),
268+
};
269+
self.tcx.cannot_move_out_of(span, place_description, origin)
270+
}
241271
_ => self
242272
.tcx
243273
.cannot_move_out_of(span, "borrowed content", origin),

src/librustc_mir/dataflow/move_paths/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
132132
let mir = self.builder.mir;
133133
let tcx = self.builder.tcx;
134134
let place_ty = proj.base.ty(mir, tcx).to_ty(tcx);
135-
match place_ty.sty {
135+
match place_ty.sty {
136136
ty::TyRef(..) | ty::TyRawPtr(..) =>
137137
return Err(MoveError::cannot_move_out_of(
138138
self.loc,
139-
BorrowedContent { target_ty: place.ty(mir, tcx).to_ty(tcx) })),
139+
BorrowedContent { target_place: place.clone() })),
140140
ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() =>
141141
return Err(MoveError::cannot_move_out_of(self.loc,
142142
InteriorOfTypeWithDestructor {

src/librustc_mir/dataflow/move_paths/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,9 @@ pub(crate) enum IllegalMoveOriginKind<'tcx> {
282282

283283
/// Illegal move due to attempt to move from behind a reference.
284284
BorrowedContent {
285-
/// The content's type: if erroneous code was trying to move
286-
/// from `*x` where `x: &T`, then this will be `T`.
287-
target_ty: ty::Ty<'tcx>,
285+
/// The place the reference refers to: if erroneous code was trying to
286+
/// move from `(*x).f` this will be `*x`.
287+
target_place: Place<'tcx>,
288288
},
289289

290290
/// Illegal move due to attempt to move from field of an ADT that

src/test/ui/borrowck/borrowck-in-static.nll.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0507]: cannot move out of borrowed content
1+
error[E0507]: cannot move out of captured variable in an `Fn` closure
22
--> $DIR/borrowck-in-static.rs:15:17
33
|
44
LL | Box::new(|| x) //~ ERROR cannot move out of captured outer variable
5-
| ^ cannot move out of borrowed content
5+
| ^ cannot move out of captured variable in an `Fn` closure
66

77
error: aborting due to previous error
88

src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0507]: cannot move out of borrowed content
1+
error[E0507]: cannot move out of captured variable in an `Fn` closure
22
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9
33
|
44
LL | y.into_iter();
5-
| ^ cannot move out of borrowed content
5+
| ^ cannot move out of captured variable in an `Fn` closure
66

77
error: aborting due to previous error
88

src/test/ui/error-codes/E0161.nll.stderr

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/test/ui/issue-4335.nll.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0507]: cannot move out of borrowed content
1+
error[E0507]: cannot move out of captured variable in an `FnMut` closure
22
--> $DIR/issue-4335.rs:16:20
33
|
44
LL | id(Box::new(|| *v))
5-
| ^^ cannot move out of borrowed content
5+
| ^^ cannot move out of captured variable in an `FnMut` closure
66

77
error[E0597]: `v` does not live long enough
88
--> $DIR/issue-4335.rs:16:17

src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ LL | fn test4(f: &Test) {
2828
LL | f.f.call_mut(())
2929
| ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
3030

31-
error[E0507]: cannot move out of borrowed content
31+
error[E0507]: cannot move out of captured variable in an `FnMut` closure
3232
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
3333
|
3434
LL | foo(f);
35-
| ^ cannot move out of borrowed content
35+
| ^ cannot move out of captured variable in an `FnMut` closure
3636

3737
error[E0505]: cannot move out of `f` because it is borrowed
3838
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:65:16

0 commit comments

Comments
 (0)