]> git.lizzy.rs Git - rust.git/commitdiff
Add specific message when moving from upvars in a non-FnOnce closure
authorMatthew Jasper <mjjasper1@gmail.com>
Fri, 13 Jul 2018 22:39:10 +0000 (23:39 +0100)
committerMatthew Jasper <mjjasper1@gmail.com>
Sat, 21 Jul 2018 17:40:46 +0000 (18:40 +0100)
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/dataflow/move_paths/mod.rs
src/test/ui/borrowck/borrowck-in-static.nll.stderr
src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
src/test/ui/error-codes/E0161.nll.stderr [deleted file]
src/test/ui/issue-4335.nll.stderr
src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr

index d979851376a2616e8504c2a8c31ce93b747b3a5d..0b49260f88a4ed6b524faa49e73103641da9d5ab 100644 (file)
@@ -11,6 +11,7 @@
 use rustc::hir;
 use rustc::mir::*;
 use rustc::ty;
+use rustc_data_structures::indexed_vec::Idx;
 use rustc_errors::DiagnosticBuilder;
 use syntax_pos::Span;
 
@@ -230,14 +231,43 @@ fn report(&self, error: GroupedMoveError<'tcx>) {
                     IllegalMoveOriginKind::Static => {
                         self.tcx.cannot_move_out_of(span, "static item", origin)
                     }
-                    IllegalMoveOriginKind::BorrowedContent { target_ty: ty } => {
+                    IllegalMoveOriginKind::BorrowedContent { target_place: place } => {
                         // Inspect the type of the content behind the
                         // borrow to provide feedback about why this
                         // was a move rather than a copy.
+                        let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
                         match ty.sty {
                             ty::TyArray(..) | ty::TySlice(..) => self
                                 .tcx
                                 .cannot_move_out_of_interior_noncopy(span, ty, None, origin),
+                            ty::TyClosure(def_id, closure_substs)
+                                if !self.mir.upvar_decls.is_empty()
+                                    && {
+                                        match place {
+                                            Place::Projection(ref proj) => {
+                                                proj.base == Place::Local(Local::new(1))
+                                            }
+                                            Place::Local(_) | Place::Static(_) => unreachable!(),
+                                        }
+                                    } =>
+                            {
+                                let closure_kind_ty =
+                                    closure_substs.closure_kind_ty(def_id, self.tcx);
+                                let closure_kind = closure_kind_ty.to_opt_closure_kind();
+                                let place_description = match closure_kind {
+                                    Some(ty::ClosureKind::Fn) => {
+                                        "captured variable in an `Fn` closure"
+                                    }
+                                    Some(ty::ClosureKind::FnMut) => {
+                                        "captured variable in an `FnMut` closure"
+                                    }
+                                    Some(ty::ClosureKind::FnOnce) => {
+                                        bug!("closure kind does not match first argument type")
+                                    }
+                                    None => bug!("closure kind not inferred by borrowck"),
+                                };
+                                self.tcx.cannot_move_out_of(span, place_description, origin)
+                            }
                             _ => self
                                 .tcx
                                 .cannot_move_out_of(span, "borrowed content", origin),
index 9ffbe21e1e2cce12dc35ec2987e97e8a7a251b09..48236e5fdd145e4fd1174f74dd2a7afcde66b5be 100644 (file)
@@ -132,11 +132,11 @@ fn move_path_for_projection(&mut self,
         let mir = self.builder.mir;
         let tcx = self.builder.tcx;
         let place_ty = proj.base.ty(mir, tcx).to_ty(tcx);
- match place_ty.sty {
       match place_ty.sty {
             ty::TyRef(..) | ty::TyRawPtr(..) =>
                 return Err(MoveError::cannot_move_out_of(
                     self.loc,
-                    BorrowedContent { target_ty: place.ty(mir, tcx).to_ty(tcx) })),
+                    BorrowedContent { target_place: place.clone() })),
             ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() =>
                 return Err(MoveError::cannot_move_out_of(self.loc,
                                                          InteriorOfTypeWithDestructor {
index 3051a687eac7008c519c32b4d51ed3b854e39ce6..54609674a47d4fe06c30563b6b4c65acdeed2667 100644 (file)
@@ -282,9 +282,9 @@ pub(crate) enum IllegalMoveOriginKind<'tcx> {
 
     /// Illegal move due to attempt to move from behind a reference.
     BorrowedContent {
-        /// The content's type: if erroneous code was trying to move
-        /// from `*x` where `x: &T`, then this will be `T`.
-        target_ty: ty::Ty<'tcx>,
+        /// The place the reference refers to: if erroneous code was trying to
+        /// move from `(*x).f` this will be `*x`.
+        target_place: Place<'tcx>,
     },
 
     /// Illegal move due to attempt to move from field of an ADT that
index 927d8c3745885b39b35f7b8f96a4237567810363..05a022a726cd977b8013c8bfb45b07db329944cd 100644 (file)
@@ -1,8 +1,8 @@
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/borrowck-in-static.rs:15:17
    |
 LL |     Box::new(|| x) //~ ERROR cannot move out of captured outer variable
-   |                 ^ cannot move out of borrowed content
+   |                 ^ cannot move out of captured variable in an `Fn` closure
 
 error: aborting due to previous error
 
index 7464e33e8c101b7b3119071146e01655ab276d4a..07a9f374b2c3935fd2368bd4bdee6ab7c960082d 100644 (file)
@@ -1,8 +1,8 @@
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9
    |
 LL |         y.into_iter();
-   |         ^ cannot move out of borrowed content
+   |         ^ cannot move out of captured variable in an `Fn` closure
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0161.nll.stderr b/src/test/ui/error-codes/E0161.nll.stderr
deleted file mode 100644 (file)
index 6aaff74..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0507]: cannot move out of borrowed content
-  --> $DIR/E0161.rs:14:28
-   |
-LL |     let _x: Box<str> = box *"hello"; //~ ERROR E0161
-   |                            ^^^^^^^^ cannot move out of borrowed content
-
-error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
-  --> $DIR/E0161.rs:14:28
-   |
-LL |     let _x: Box<str> = box *"hello"; //~ ERROR E0161
-   |                            ^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-Some errors occurred: E0161, E0507.
-For more information about an error, try `rustc --explain E0161`.
index 8eede34747827f313a0d19fae5db147a28465aaa..eacd8b5e58047878ddf102835b172c4edb859809 100644 (file)
@@ -1,8 +1,8 @@
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/issue-4335.rs:16:20
    |
 LL |     id(Box::new(|| *v))
-   |                    ^^ cannot move out of borrowed content
+   |                    ^^ cannot move out of captured variable in an `FnMut` closure
 
 error[E0597]: `v` does not live long enough
   --> $DIR/issue-4335.rs:16:17
index f752015c650b9d825c447eabe7efffd334793404..b3563f1b6203cfa0ef91b900b6f4ef3a261abcc7 100644 (file)
@@ -28,11 +28,11 @@ LL | fn test4(f: &Test) {
 LL |     f.f.call_mut(())
    |     ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
    |
 LL |         foo(f);
-   |             ^ cannot move out of borrowed content
+   |             ^ cannot move out of captured variable in an `FnMut` closure
 
 error[E0505]: cannot move out of `f` because it is borrowed
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:65:16