Skip to content

Commit

Permalink
When NLL has illegal move due to borrowed content, provide feedback a…
Browse files Browse the repository at this point in the history
…bout why the move wasn't a copy.

This should address #51190.
  • Loading branch information
pnkfelix committed Jun 6, 2018
1 parent cb8ab33 commit fbe7d5b
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/librustc_borrowck/borrowck/gather_loans/move_error.rs
Expand Up @@ -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, _) |
Expand Down
13 changes: 10 additions & 3 deletions src/librustc_mir/borrow_check/mod.rs
Expand Up @@ -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();
Expand Down
9 changes: 5 additions & 4 deletions src/librustc_mir/dataflow/move_paths/builder.rs
Expand Up @@ -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);
}

Expand All @@ -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 {
Expand Down
16 changes: 15 additions & 1 deletion src/librustc_mir/dataflow/move_paths/mod.rs
Expand Up @@ -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, },
}

Expand Down
8 changes: 6 additions & 2 deletions src/librustc_mir/util/borrowck_errors.rs
Expand Up @@ -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<bool>,
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"),
};
Expand Down

0 comments on commit fbe7d5b

Please sign in to comment.