about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-07-28 07:42:13 +0000
committerbors <bors@rust-lang.org>2018-07-28 07:42:13 +0000
commit05607476521732c5c71bc063c8be5056aa573b15 (patch)
treecb47ef452a0aeb4165f265aac52cc2b1c2ffe817
parent4f1e2357447ef7e8066c49560d66c3e18f25d982 (diff)
parentb32caef1ad605c8607ad0c3ccc682f6536f0e812 (diff)
downloadrust-05607476521732c5c71bc063c8be5056aa573b15.tar.gz
rust-05607476521732c5c71bc063c8be5056aa573b15.zip
Auto merge of #52678 - matthewjasper:better-spans, r=nikomatsakis
[NLL] Use better spans in some errors

* Use the span of the discriminant and patterns for "fake" statements created to properly check matches. I plan to special case these soon, but this felt like a good first step
* Use the span of the statement, rather than the initialization, when reporting move errors for `let x = ...`, which avoids giving an unhelpful suggestion to use `&{ }`.

r? @nikomatsakis cc @pnkfelix
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs43
-rw-r--r--src/librustc_mir/build/matches/mod.rs8
-rw-r--r--src/test/ui/borrowck/issue-41962.stderr24
-rw-r--r--src/test/ui/issue-17385.nll.stderr52
-rw-r--r--src/test/ui/issue-20801.nll.stderr20
-rw-r--r--src/test/ui/issue-27282-move-match-input-into-guard.stderr23
-rw-r--r--src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr28
-rw-r--r--src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr29
-rw-r--r--src/test/ui/issue-47412.stderr8
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr16
-rw-r--r--src/test/ui/nll/borrowed-match-issue-45045.stderr21
-rw-r--r--src/test/ui/nll/cannot-move-block-spans.nll.stderr85
-rw-r--r--src/test/ui/nll/cannot-move-block-spans.rs32
-rw-r--r--src/test/ui/nll/cannot-move-block-spans.stderr58
-rw-r--r--src/test/ui/span/issue-40157.nll.stderr10
15 files changed, 295 insertions, 162 deletions
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 4aa38fb5f37..215ade5bd4d 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -87,6 +87,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 cannot_move_out_of: IllegalMoveOrigin { location, kind },
             } => {
                 let stmt_source_info = self.mir.source_info(location);
+                // Note: that the only time we assign a place isn't a temporary
+                // to a user variable is when initializing it.
+                // If that ever stops being the case, then the ever initialized
+                // flow could be used.
                 if let Some(StatementKind::Assign(
                     Place::Local(local),
                     Rvalue::Use(Operand::Move(move_from)),
@@ -109,26 +113,16 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         opt_ty_info: _,
                     }))) = local_decl.is_user_variable
                     {
-                        // HACK use scopes to determine if this assignment is
-                        // the initialization of a variable.
-                        // FIXME(matthewjasper) This would probably be more
-                        // reliable if it used the ever initialized dataflow
-                        // but move errors are currently reported before the
-                        // rest of borrowck has run.
-                        if self
-                            .mir
-                            .is_sub_scope(local_decl.source_info.scope, stmt_source_info.scope)
-                        {
-                            self.append_binding_error(
-                                grouped_errors,
-                                kind,
-                                move_from,
-                                *local,
-                                opt_match_place,
-                                match_span,
-                            );
-                            return;
-                        }
+                        self.append_binding_error(
+                            grouped_errors,
+                            kind,
+                            move_from,
+                            *local,
+                            opt_match_place,
+                            match_span,
+                            stmt_source_info.span,
+                        );
+                        return;
                     }
                 }
                 grouped_errors.push(GroupedMoveError::OtherIllegalMove {
@@ -147,6 +141,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
         bind_to: Local,
         match_place: &Option<Place<'tcx>>,
         match_span: Span,
+        statement_span: Span,
     ) {
         debug!(
             "append_to_grouped_errors(match_place={:?}, match_span={:?})",
@@ -173,13 +168,13 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 debug!("found a new move error location");
 
                 // Don't need to point to x in let x = ... .
-                let binds_to = if from_simple_let {
-                    vec![]
+                let (binds_to, span) = if from_simple_let {
+                    (vec![], statement_span)
                 } else {
-                    vec![bind_to]
+                    (vec![bind_to], match_span)
                 };
                 grouped_errors.push(GroupedMoveError::MovesFromMatchPlace {
-                    span: match_span,
+                    span,
                     move_from: match_place.clone(),
                     kind,
                     binds_to,
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 7c949669028..a509ec08a14 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -63,13 +63,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // injects a borrow of the matched input, which should have the same effect
         // as eddyb's hack. Once NLL is the default, we can remove the hack.
 
-        let dummy_source_info = self.source_info(span);
+        let dummy_source_info = self.source_info(discriminant_span);
         let dummy_access = Rvalue::Discriminant(discriminant_place.clone());
         let dummy_ty = dummy_access.ty(&self.local_decls, tcx);
         let dummy_temp = self.temp(dummy_ty, dummy_source_info.span);
         self.cfg.push_assign(block, dummy_source_info, &dummy_temp, dummy_access);
 
-        let source_info = self.source_info(span);
+        let source_info = self.source_info(discriminant_span);
         let borrowed_input_temp = if tcx.generate_borrow_of_any_match_input() {
             // The region is unknown at this point; we rely on NLL
             // inference to find an appropriate one. Therefore you can
@@ -136,9 +136,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         // This should ensure that you cannot change
                         // the variant for an enum while you are in
                         // the midst of matching on it.
-
+                        let pattern_source_info = self.source_info(pattern.span);
                         self.cfg.push(*pre_binding_block, Statement {
-                            source_info,
+                            source_info: pattern_source_info,
                             kind: StatementKind::ReadForMatch(borrow_temp.clone()),
                         });
                     }
diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr
index bd5d2a46fd8..4048243acfa 100644
--- a/src/test/ui/borrowck/issue-41962.stderr
+++ b/src/test/ui/borrowck/issue-41962.stderr
@@ -17,26 +17,22 @@ LL |         if let Some(thing) = maybe {
    = note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `maybe` (Mir)
-  --> $DIR/issue-41962.rs:17:9
+  --> $DIR/issue-41962.rs:17:30
    |
-LL |           if let Some(thing) = maybe {
-   |           ^           ----- value moved here
-   |  _________|
-   | |
-LL | |         }
-   | |_________^ value used here after move
+LL |         if let Some(thing) = maybe {
+   |                     -----    ^^^^^ value used here after move
+   |                     |
+   |                     value moved here
    |
    = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `maybe` (Mir)
-  --> $DIR/issue-41962.rs:17:9
+  --> $DIR/issue-41962.rs:17:30
    |
-LL |           if let Some(thing) = maybe {
-   |           ^           ----- value moved here
-   |  _________|
-   | |
-LL | |         }
-   | |_________^ value borrowed here after move
+LL |         if let Some(thing) = maybe {
+   |                     -----    ^^^^^ value borrowed here after move
+   |                     |
+   |                     value moved here
    |
    = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
 
diff --git a/src/test/ui/issue-17385.nll.stderr b/src/test/ui/issue-17385.nll.stderr
index c3387e58fcf..85924a75261 100644
--- a/src/test/ui/issue-17385.nll.stderr
+++ b/src/test/ui/issue-17385.nll.stderr
@@ -1,26 +1,20 @@
 error[E0382]: use of moved value: `foo`
-  --> $DIR/issue-17385.rs:28:5
+  --> $DIR/issue-17385.rs:28:11
    |
-LL |       drop(foo);
-   |            --- value moved here
-LL | /     match foo { //~ ERROR use of moved value
-LL | |         X(1) => (),
-LL | |         _ => unreachable!()
-LL | |     }
-   | |_____^ value used here after move
+LL |     drop(foo);
+   |          --- value moved here
+LL |     match foo { //~ ERROR use of moved value
+   |           ^^^ value used here after move
    |
    = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `foo`
-  --> $DIR/issue-17385.rs:28:5
+  --> $DIR/issue-17385.rs:28:11
    |
-LL |       drop(foo);
-   |            --- value moved here
-LL | /     match foo { //~ ERROR use of moved value
-LL | |         X(1) => (),
-LL | |         _ => unreachable!()
-LL | |     }
-   | |_____^ value borrowed here after move
+LL |     drop(foo);
+   |          --- value moved here
+LL |     match foo { //~ ERROR use of moved value
+   |           ^^^ value borrowed here after move
    |
    = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
 
@@ -36,28 +30,22 @@ LL |         X(1) => (),
    = note: move occurs because `foo` has type `X`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `e`
-  --> $DIR/issue-17385.rs:35:5
+  --> $DIR/issue-17385.rs:35:11
    |
-LL |       drop(e);
-   |            - value moved here
-LL | /     match e { //~ ERROR use of moved value
-LL | |         Enum::Variant1 => unreachable!(),
-LL | |         Enum::Variant2 => ()
-LL | |     }
-   | |_____^ value used here after move
+LL |     drop(e);
+   |          - value moved here
+LL |     match e { //~ ERROR use of moved value
+   |           ^ value used here after move
    |
    = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `e`
-  --> $DIR/issue-17385.rs:35:5
+  --> $DIR/issue-17385.rs:35:11
    |
-LL |       drop(e);
-   |            - value moved here
-LL | /     match e { //~ ERROR use of moved value
-LL | |         Enum::Variant1 => unreachable!(),
-LL | |         Enum::Variant2 => ()
-LL | |     }
-   | |_____^ value borrowed here after move
+LL |     drop(e);
+   |          - value moved here
+LL |     match e { //~ ERROR use of moved value
+   |           ^ value borrowed here after move
    |
    = note: move occurs because `e` has type `Enum`, which does not implement the `Copy` trait
 
diff --git a/src/test/ui/issue-20801.nll.stderr b/src/test/ui/issue-20801.nll.stderr
index 0394309a6e2..fc94cc423c5 100644
--- a/src/test/ui/issue-20801.nll.stderr
+++ b/src/test/ui/issue-20801.nll.stderr
@@ -2,25 +2,37 @@ error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:36:22
    |
 LL |     let a = unsafe { *mut_ref() };
-   |                      ^^^^^^^^^^ cannot move out of borrowed content
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      cannot move out of borrowed content
+   |                      help: consider using a reference instead: `&*mut_ref()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:39:22
    |
 LL |     let b = unsafe { *imm_ref() };
-   |                      ^^^^^^^^^^ cannot move out of borrowed content
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      cannot move out of borrowed content
+   |                      help: consider using a reference instead: `&*imm_ref()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:42:22
    |
 LL |     let c = unsafe { *mut_ptr() };
-   |                      ^^^^^^^^^^ cannot move out of borrowed content
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      cannot move out of borrowed content
+   |                      help: consider using a reference instead: `&*mut_ptr()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:45:22
    |
 LL |     let d = unsafe { *const_ptr() };
-   |                      ^^^^^^^^^^^^ cannot move out of borrowed content
+   |                      ^^^^^^^^^^^^
+   |                      |
+   |                      cannot move out of borrowed content
+   |                      help: consider using a reference instead: `&*const_ptr()`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issue-27282-move-match-input-into-guard.stderr
index f89388f1738..d264bf8d273 100644
--- a/src/test/ui/issue-27282-move-match-input-into-guard.stderr
+++ b/src/test/ui/issue-27282-move-match-input-into-guard.stderr
@@ -1,21 +1,14 @@
 error[E0505]: cannot move out of `b` because it is borrowed
   --> $DIR/issue-27282-move-match-input-into-guard.rs:26:16
    |
-LL |        match b {
-   |   _____-
-   |  |_____|
-   | ||
-LL | ||         &mut false => {},
-LL | ||         _ if { (|| { let bar = b; *bar = false; })();
-   | ||                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `b` occurs here
-LL | ||                      //~^ ERROR cannot move out of `b` because it is borrowed [E0505]
-...  ||
-LL | ||         _ => panic!("surely we could never get here, since rustc warns it is unreachable."),
-LL | ||     }
-   | ||     -
-   | ||_____|
-   | |______borrow of `b` occurs here
-   |        borrow later used here
+LL |     match b {
+   |           - borrow of `b` occurs here
+LL |         &mut false => {},
+LL |         _ if { (|| { let bar = b; *bar = false; })();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `b` occurs here
+...
+LL |         &mut true => { println!("You might think we should get here"); },
+   |         --------- borrow later used here
 
 error[E0382]: use of moved value: `*b`
   --> $DIR/issue-27282-move-match-input-into-guard.rs:29:14
diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr
index 8f7fe9d33fe..fb11090c222 100644
--- a/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr
+++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr
@@ -1,24 +1,16 @@
 error[E0500]: closure requires unique access to `x` but it is already borrowed
   --> $DIR/issue-27282-mutate-before-diverging-arm-1.rs:33:14
    |
-LL |        match x {
-   |   _____-
-   |  |_____|
-   | ||
-LL | ||         &mut None => panic!("unreachable"),
-LL | ||         &mut Some(&_) if {
-LL | ||             // ForceFnOnce needed to exploit #27282
-LL | ||             (|| { *x = None; drop(force_fn_once); })();
-   | ||              ^^    - borrow occurs due to use of `x` in closure
-   | ||              |
-   | ||              closure construction occurs here
-...  ||
-LL | ||         _ => panic!("unreachable"),
-LL | ||     }
-   | ||     -
-   | ||_____|
-   | |______borrow occurs here
-   |        borrow later used here
+LL |     match x {
+   |           - borrow occurs here
+...
+LL |             (|| { *x = None; drop(force_fn_once); })();
+   |              ^^    - borrow occurs due to use of `x` in closure
+   |              |
+   |              closure construction occurs here
+...
+LL |         &mut Some(&a) if { // this binds to garbage if we've corrupted discriminant
+   |         ------------- borrow later used here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr
index df5e4300cec..6e643d30185 100644
--- a/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr
+++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr
@@ -1,25 +1,16 @@
 error[E0500]: closure requires unique access to `x` but it is already borrowed
   --> $DIR/issue-27282-mutate-before-diverging-arm-2.rs:38:18
    |
-LL |        match x {
-   |   _____-
-   |  |_____|
-   | ||
-LL | ||         &mut None => panic!("unreachable"),
-LL | ||         &mut Some(&_)
-LL | ||             if {
-LL | ||                 // ForceFnOnce needed to exploit #27282
-LL | ||                 (|| { *x = None; drop(force_fn_once); })();
-   | ||                  ^^    - borrow occurs due to use of `x` in closure
-   | ||                  |
-   | ||                  closure construction occurs here
-...  ||
-LL | ||         _ => panic!("unreachable"),
-LL | ||     }
-   | ||     -
-   | ||_____|
-   | |______borrow occurs here
-   |        borrow later used here
+LL |     match x {
+   |           - borrow occurs here
+...
+LL |                 (|| { *x = None; drop(force_fn_once); })();
+   |                  ^^    - borrow occurs due to use of `x` in closure
+   |                  |
+   |                  closure construction occurs here
+...
+LL |         &mut Some(&2)
+   |         ------------- borrow later used here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-47412.stderr b/src/test/ui/issue-47412.stderr
index 6ca404003a5..d8a47efc0aa 100644
--- a/src/test/ui/issue-47412.stderr
+++ b/src/test/ui/issue-47412.stderr
@@ -1,16 +1,16 @@
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/issue-47412.rs:21:5
+  --> $DIR/issue-47412.rs:21:11
    |
 LL |     match u.void {}
-   |     ^^^^^^^^^^^^^^^ access to union field
+   |           ^^^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/issue-47412.rs:27:5
+  --> $DIR/issue-47412.rs:27:11
    |
 LL |     match *ptr {}
-   |     ^^^^^^^^^^^^^ dereference of raw pointer
+   |           ^^^^ dereference of raw pointer
    |
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr
index 5451562cdfb..e5b001def56 100644
--- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr
@@ -5,18 +5,12 @@ LL |                     other //~ ERROR explicit lifetime
    |                     ^^^^^
 
 error[E0621]: explicit lifetime required in the type of `other`
-  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:18:9
+  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:18:15
    |
-LL |       fn bar(&self, other: Foo) -> Foo<'a> {
-   |                     ----- consider changing the type of `other` to `Foo<'a>`
-LL | /         match *self {
-LL | |             Foo::Bar(s) => {
-LL | |                 if s == "test" {
-LL | |                     other //~ ERROR explicit lifetime
-...  |
-LL | |             }
-LL | |         }
-   | |_________^ lifetime `'a` required
+LL |     fn bar(&self, other: Foo) -> Foo<'a> {
+   |                   ----- consider changing the type of `other` to `Foo<'a>`
+LL |         match *self {
+   |               ^^^^^ lifetime `'a` required
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/borrowed-match-issue-45045.stderr b/src/test/ui/nll/borrowed-match-issue-45045.stderr
index 7904e601579..acbba9ee187 100644
--- a/src/test/ui/nll/borrowed-match-issue-45045.stderr
+++ b/src/test/ui/nll/borrowed-match-issue-45045.stderr
@@ -1,17 +1,14 @@
 error[E0503]: cannot use `e` because it was mutably borrowed
-  --> $DIR/borrowed-match-issue-45045.rs:24:5
+  --> $DIR/borrowed-match-issue-45045.rs:24:11
    |
-LL |       let f = &mut e;
-   |               ------ borrow of `e` occurs here
-LL |       let g = f;
-LL | /     match e { //~ cannot use `e` because it was mutably borrowed [E0503]
-LL | |         Xyz::A => println!("a"),
-LL | |         //~^ cannot use `e` because it was mutably borrowed [E0503]
-LL | |         Xyz::B => println!("b"),
-LL | |     };
-   | |_____^ use of borrowed `e`
-LL |       *g = Xyz::B;
-   |       ----------- borrow later used here
+LL |     let f = &mut e;
+   |             ------ borrow of `e` occurs here
+LL |     let g = f;
+LL |     match e { //~ cannot use `e` because it was mutably borrowed [E0503]
+   |           ^ use of borrowed `e`
+...
+LL |     *g = Xyz::B;
+   |     ----------- borrow later used here
 
 error[E0503]: cannot use `e` because it was mutably borrowed
   --> $DIR/borrowed-match-issue-45045.rs:25:9
diff --git a/src/test/ui/nll/cannot-move-block-spans.nll.stderr b/src/test/ui/nll/cannot-move-block-spans.nll.stderr
new file mode 100644
index 00000000000..814e11b6f06
--- /dev/null
+++ b/src/test/ui/nll/cannot-move-block-spans.nll.stderr
@@ -0,0 +1,85 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:15:15
+   |
+LL |     let x = { *r }; //~ ERROR
+   |               ^^
+   |               |
+   |               cannot move out of borrowed content
+   |               help: consider removing this dereference operator: `r`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:16:22
+   |
+LL |     let y = unsafe { *r }; //~ ERROR
+   |                      ^^
+   |                      |
+   |                      cannot move out of borrowed content
+   |                      help: consider removing this dereference operator: `r`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:17:26
+   |
+LL |     let z = loop { break *r; }; //~ ERROR
+   |                          ^^
+   |                          |
+   |                          cannot move out of borrowed content
+   |                          help: consider removing this dereference operator: `r`
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:21:15
+   |
+LL |     let x = { arr[0] }; //~ ERROR
+   |               ^^^^^^
+   |               |
+   |               cannot move out of here
+   |               help: consider using a reference instead: `&arr[0]`
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:22:22
+   |
+LL |     let y = unsafe { arr[0] }; //~ ERROR
+   |                      ^^^^^^
+   |                      |
+   |                      cannot move out of here
+   |                      help: consider using a reference instead: `&arr[0]`
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:23:26
+   |
+LL |     let z = loop { break arr[0]; }; //~ ERROR
+   |                          ^^^^^^
+   |                          |
+   |                          cannot move out of here
+   |                          help: consider using a reference instead: `&arr[0]`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:27:38
+   |
+LL |     let x = { let mut u = 0; u += 1; *r }; //~ ERROR
+   |                                      ^^
+   |                                      |
+   |                                      cannot move out of borrowed content
+   |                                      help: consider removing this dereference operator: `r`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:28:45
+   |
+LL |     let y = unsafe { let mut u = 0; u += 1; *r }; //~ ERROR
+   |                                             ^^
+   |                                             |
+   |                                             cannot move out of borrowed content
+   |                                             help: consider removing this dereference operator: `r`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:29:49
+   |
+LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; //~ ERROR
+   |                                                 ^^
+   |                                                 |
+   |                                                 cannot move out of borrowed content
+   |                                                 help: consider removing this dereference operator: `r`
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0507, E0508.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/cannot-move-block-spans.rs b/src/test/ui/nll/cannot-move-block-spans.rs
new file mode 100644
index 00000000000..5a84a4ca48e
--- /dev/null
+++ b/src/test/ui/nll/cannot-move-block-spans.rs
@@ -0,0 +1,32 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the we point to the inner expression when moving out to initialize
+// a variable, and that we don't give a useless suggestion such as &{ *r }.
+
+pub fn deref(r: &String) {
+    let x = { *r }; //~ ERROR
+    let y = unsafe { *r }; //~ ERROR
+    let z = loop { break *r; }; //~ ERROR
+}
+
+pub fn index(arr: [String; 2]) {
+    let x = { arr[0] }; //~ ERROR
+    let y = unsafe { arr[0] }; //~ ERROR
+    let z = loop { break arr[0]; }; //~ ERROR
+}
+
+pub fn additional_statement_cases(r: &String) {
+    let x = { let mut u = 0; u += 1; *r }; //~ ERROR
+    let y = unsafe { let mut u = 0; u += 1; *r }; //~ ERROR
+    let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; //~ ERROR
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/cannot-move-block-spans.stderr b/src/test/ui/nll/cannot-move-block-spans.stderr
new file mode 100644
index 00000000000..d4956900239
--- /dev/null
+++ b/src/test/ui/nll/cannot-move-block-spans.stderr
@@ -0,0 +1,58 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:15:15
+   |
+LL |     let x = { *r }; //~ ERROR
+   |               ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:16:22
+   |
+LL |     let y = unsafe { *r }; //~ ERROR
+   |                      ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:17:26
+   |
+LL |     let z = loop { break *r; }; //~ ERROR
+   |                          ^^ cannot move out of borrowed content
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:21:15
+   |
+LL |     let x = { arr[0] }; //~ ERROR
+   |               ^^^^^^ cannot move out of here
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:22:22
+   |
+LL |     let y = unsafe { arr[0] }; //~ ERROR
+   |                      ^^^^^^ cannot move out of here
+
+error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
+  --> $DIR/cannot-move-block-spans.rs:23:26
+   |
+LL |     let z = loop { break arr[0]; }; //~ ERROR
+   |                          ^^^^^^ cannot move out of here
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:27:38
+   |
+LL |     let x = { let mut u = 0; u += 1; *r }; //~ ERROR
+   |                                      ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:28:45
+   |
+LL |     let y = unsafe { let mut u = 0; u += 1; *r }; //~ ERROR
+   |                                             ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/cannot-move-block-spans.rs:29:49
+   |
+LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; //~ ERROR
+   |                                                 ^^ cannot move out of borrowed content
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0507, E0508.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/span/issue-40157.nll.stderr b/src/test/ui/span/issue-40157.nll.stderr
index def4a308bc7..09e634ba725 100644
--- a/src/test/ui/span/issue-40157.nll.stderr
+++ b/src/test/ui/span/issue-40157.nll.stderr
@@ -2,11 +2,11 @@ error[E0597]: `foo` does not live long enough
   --> $DIR/issue-40157.rs:12:53
    |
 LL |     {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });}
-   |                       ------------------------------^^^--------------------
-   |                       |                             |          |
-   |                       |                             |          `foo` dropped here while still borrowed
-   |                       |                             borrowed value does not live long enough
-   |                       borrow later used here
+   |                             ------------------------^^^---------
+   |                             |                       |          |
+   |                             |                       |          `foo` dropped here while still borrowed
+   |                             |                       borrowed value does not live long enough
+   |                             borrow later used here
 
 error: aborting due to previous error