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"), };