From fbe7d5bce8f618ce0fc8d78d4153c05dc85e62bb Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 31 May 2018 12:46:43 +0200 Subject: [PATCH 1/3] When NLL has illegal move due to borrowed content, provide feedback about why the move wasn't a copy. This should address #51190. --- .../borrowck/gather_loans/move_error.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 13 ++++++++++--- src/librustc_mir/dataflow/move_paths/builder.rs | 9 +++++---- src/librustc_mir/dataflow/move_paths/mod.rs | 16 +++++++++++++++- src/librustc_mir/util/borrowck_errors.rs | 8 ++++++-- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index 18026a14259..84931907964 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -147,7 +147,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, } Categorization::Interior(ref b, mc::InteriorElement(ik)) => { bccx.cannot_move_out_of_interior_noncopy( - move_from.span, b.ty, ik == Kind::Index, Origin::Ast) + move_from.span, b.ty, Some(ik == Kind::Index), Origin::Ast) } Categorization::Downcast(ref b, _) | diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 5efbdeafd1b..ba0557d062f 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -132,14 +132,21 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( IllegalMoveOriginKind::Static => { tcx.cannot_move_out_of(span, "static item", origin) } - IllegalMoveOriginKind::BorrowedContent => { - tcx.cannot_move_out_of(span, "borrowed content", origin) + IllegalMoveOriginKind::BorrowedContent { target_ty: ty } => { + // Inspect the type of the content behind the + // borrow to provide feedback about why this + // was a move rather than a copy. + match ty.sty { + ty::TyArray(..) | ty::TySlice(..) => + tcx.cannot_move_out_of_interior_noncopy(span, ty, None, origin), + _ => tcx.cannot_move_out_of(span, "borrowed content", origin) + } } IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => { tcx.cannot_move_out_of_interior_of_drop(span, ty, origin) } IllegalMoveOriginKind::InteriorOfSliceOrArray { ty, is_index } => { - tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin) + tcx.cannot_move_out_of_interior_noncopy(span, ty, Some(is_index), origin) } }; err.emit(); diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 2ff22842141..590f9917015 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -119,8 +119,8 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { } fn create_move_path(&mut self, place: &Place<'tcx>) { - // This is an assignment, not a move, so this not being a valid - // move path is OK. + // This is an non-moving access (such as an overwrite or + // drop), so this not being a valid move path is OK. let _ = self.move_path_for(place); } @@ -135,8 +135,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { let place_ty = proj.base.ty(mir, tcx).to_ty(tcx); match place_ty.sty { ty::TyRef(..) | ty::TyRawPtr(..) => - return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span, - BorrowedContent)), + return Err(MoveError::cannot_move_out_of( + mir.source_info(self.loc).span, + BorrowedContent { target_ty: place.ty(mir, tcx).to_ty(tcx) })), ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span, InteriorOfTypeWithDestructor { diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 610963af9e1..a73e47bc16a 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -277,9 +277,23 @@ pub struct IllegalMoveOrigin<'tcx> { #[derive(Debug)] pub(crate) enum IllegalMoveOriginKind<'tcx> { + /// Illegal move due to attempt to move from `static` variable. Static, - BorrowedContent, + + /// 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>, + }, + + /// Illegal move due to attempt to move from field of an ADT that + /// implements `Drop`. Rust maintains invariant that all `Drop` + /// ADT's remain fully-initialized so that user-defined destructor + /// can safely read from all of the ADT's fields. InteriorOfTypeWithDestructor { container_ty: ty::Ty<'tcx> }, + + /// Illegal move due to attempt to move out of a slice or array. InteriorOfSliceOrArray { ty: ty::Ty<'tcx>, is_index: bool, }, } diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index d6b3e674f8f..d01b90ad262 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -312,15 +312,19 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { self.cancel_if_wrong_origin(err, o) } + /// Signal an error due to an attempt to move out of the interior + /// of an array or slice. `is_index` is None when error origin + /// didn't capture whether there was an indexing operation or not. fn cannot_move_out_of_interior_noncopy(self, move_from_span: Span, ty: ty::Ty, - is_index: bool, + is_index: Option, o: Origin) -> DiagnosticBuilder<'cx> { let type_name = match (&ty.sty, is_index) { - (&ty::TyArray(_, _), true) => "array", + (&ty::TyArray(_, _), Some(true)) | + (&ty::TyArray(_, _), None) => "array", (&ty::TySlice(_), _) => "slice", _ => span_bug!(move_from_span, "this path should not cause illegal move"), }; From 9b24595226f3290e09aada4d3d370331d71e6241 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 31 May 2018 12:58:10 +0200 Subject: [PATCH 2/3] Drive-by: Make assignment conflict tests in borrowck-vec-pattern-nesting.rs robust for NLL. --- src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs index 111968e9c93..63dac0a8300 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs @@ -19,6 +19,7 @@ fn a() { //~^ borrow of `vec[..]` occurs here vec[0] = box 4; //~ ERROR cannot assign //~^ assignment to borrowed `vec[..]` occurs here + _a.use_ref(); } } } @@ -31,6 +32,7 @@ fn b() { //~^ borrow of `vec[..]` occurs here vec[0] = box 4; //~ ERROR cannot assign //~^ assignment to borrowed `vec[..]` occurs here + _b.use_ref(); } } } @@ -82,3 +84,6 @@ fn e() { } fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } From e5b378b18df428e296243a82e4a2c5856ef0cb75 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 31 May 2018 12:58:34 +0200 Subject: [PATCH 3/3] Update the expected error output to reflect changes in this PR. --- .../borrowck-move-out-of-vec-tail.nll.stderr | 10 +-- .../borrowck-vec-pattern-nesting.nll.stderr | 77 ++++++++++++------- .../borrowck-vec-pattern-nesting.stderr | 14 ++-- 3 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr index a430c97158a..96b376ea7ae 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr @@ -1,15 +1,15 @@ -error[E0507]: cannot move out of borrowed content +error[E0508]: cannot move out of type `[Foo]`, a non-copy slice --> $DIR/borrowck-move-out-of-vec-tail.rs:30:33 | LL | &[Foo { string: a }, - | ^ cannot move out of borrowed content + | ^ cannot move out of here -error[E0507]: cannot move out of borrowed content +error[E0508]: cannot move out of type `[Foo]`, a non-copy slice --> $DIR/borrowck-move-out-of-vec-tail.rs:34:33 | LL | Foo { string: b }] => { - | ^ cannot move out of borrowed content + | ^ cannot move out of here error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0508`. diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr index d5a66a6c706..6d28a37463b 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr @@ -1,51 +1,76 @@ -error[E0507]: cannot move out of borrowed content - --> $DIR/borrowck-vec-pattern-nesting.rs:42:15 +error[E0506]: cannot assign to `vec[..]` because it is borrowed + --> $DIR/borrowck-vec-pattern-nesting.rs:20:13 + | +LL | [box ref _a, _, _] => { + | ------ borrow of `vec[..]` occurs here +LL | //~^ borrow of `vec[..]` occurs here +LL | vec[0] = box 4; //~ ERROR cannot assign + | ^^^^^^ assignment to borrowed `vec[..]` occurs here +LL | //~^ assignment to borrowed `vec[..]` occurs here +LL | _a.use_ref(); + | -- borrow later used here + +error[E0506]: cannot assign to `vec[..]` because it is borrowed + --> $DIR/borrowck-vec-pattern-nesting.rs:33:13 + | +LL | &mut [ref _b..] => { + | ------ borrow of `vec[..]` occurs here +LL | //~^ borrow of `vec[..]` occurs here +LL | vec[0] = box 4; //~ ERROR cannot assign + | ^^^^^^ assignment to borrowed `vec[..]` occurs here +LL | //~^ assignment to borrowed `vec[..]` occurs here +LL | _b.use_ref(); + | -- borrow later used here + +error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:44:15 | LL | &mut [_a, //~ ERROR cannot move out - | ^^ cannot move out of borrowed content + | ^^ cannot move out of here -error[E0507]: cannot move out of borrowed content - --> $DIR/borrowck-vec-pattern-nesting.rs:55:13 +error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:57:13 | LL | let a = vec[0]; //~ ERROR cannot move out - | ^^^^^^ cannot move out of borrowed content + | ^^^^^^ cannot move out of here -error[E0507]: cannot move out of borrowed content - --> $DIR/borrowck-vec-pattern-nesting.rs:65:10 +error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:67:10 | LL | _b] => {} - | ^^ cannot move out of borrowed content + | ^^ cannot move out of here -error[E0507]: cannot move out of borrowed content - --> $DIR/borrowck-vec-pattern-nesting.rs:68:13 +error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:70:13 | LL | let a = vec[0]; //~ ERROR cannot move out - | ^^^^^^ cannot move out of borrowed content + | ^^^^^^ cannot move out of here -error[E0507]: cannot move out of borrowed content - --> $DIR/borrowck-vec-pattern-nesting.rs:76:15 +error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:78:15 | LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out - | ^^ cannot move out of borrowed content + | ^^ cannot move out of here -error[E0507]: cannot move out of borrowed content - --> $DIR/borrowck-vec-pattern-nesting.rs:76:19 +error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:78:19 | LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out - | ^^ cannot move out of borrowed content + | ^^ cannot move out of here -error[E0507]: cannot move out of borrowed content - --> $DIR/borrowck-vec-pattern-nesting.rs:76:23 +error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:78:23 | LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out - | ^^ cannot move out of borrowed content + | ^^ cannot move out of here -error[E0507]: cannot move out of borrowed content - --> $DIR/borrowck-vec-pattern-nesting.rs:80:13 +error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:82:13 | LL | let a = vec[0]; //~ ERROR cannot move out - | ^^^^^^ cannot move out of borrowed content + | ^^^^^^ cannot move out of here -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors -For more information about this error, try `rustc --explain E0507`. +Some errors occurred: E0506, E0508. +For more information about an error, try `rustc --explain E0506`. diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr index 6673549e239..a03e1eab7ad 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr @@ -8,7 +8,7 @@ LL | vec[0] = box 4; //~ ERROR cannot assign | ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here error[E0506]: cannot assign to `vec[..]` because it is borrowed - --> $DIR/borrowck-vec-pattern-nesting.rs:32:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:33:13 | LL | &mut [ref _b..] => { | ------ borrow of `vec[..]` occurs here @@ -17,7 +17,7 @@ LL | vec[0] = box 4; //~ ERROR cannot assign | ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:42:14 + --> $DIR/borrowck-vec-pattern-nesting.rs:44:14 | LL | &mut [_a, //~ ERROR cannot move out | ^-- hint: to prevent move, use `ref _a` or `ref mut _a` @@ -30,7 +30,7 @@ LL | | ] => { | |_________^ cannot move out of here error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:55:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:57:13 | LL | let a = vec[0]; //~ ERROR cannot move out | ^^^^^^ @@ -39,7 +39,7 @@ LL | let a = vec[0]; //~ ERROR cannot move out | help: consider using a reference instead: `&vec[0]` error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:63:14 + --> $DIR/borrowck-vec-pattern-nesting.rs:65:14 | LL | &mut [ //~ ERROR cannot move out | ______________^ @@ -50,7 +50,7 @@ LL | | _b] => {} | hint: to prevent move, use `ref _b` or `ref mut _b` error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:68:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:70:13 | LL | let a = vec[0]; //~ ERROR cannot move out | ^^^^^^ @@ -59,7 +59,7 @@ LL | let a = vec[0]; //~ ERROR cannot move out | help: consider using a reference instead: `&vec[0]` error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:76:14 + --> $DIR/borrowck-vec-pattern-nesting.rs:78:14 | LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out | ^--^^--^^--^ @@ -70,7 +70,7 @@ LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out | cannot move out of here error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:80:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:82:13 | LL | let a = vec[0]; //~ ERROR cannot move out | ^^^^^^