When NLL has illegal move due to borrowed content, provide feedback about why the move wasn't a copy.
This should address #51190.
This commit is contained in:
parent
cb8ab33ed2
commit
fbe7d5bce8
5 changed files with 37 additions and 11 deletions
|
@ -147,7 +147,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
Categorization::Interior(ref b, mc::InteriorElement(ik)) => {
|
Categorization::Interior(ref b, mc::InteriorElement(ik)) => {
|
||||||
bccx.cannot_move_out_of_interior_noncopy(
|
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, _) |
|
Categorization::Downcast(ref b, _) |
|
||||||
|
|
|
@ -132,14 +132,21 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||||
IllegalMoveOriginKind::Static => {
|
IllegalMoveOriginKind::Static => {
|
||||||
tcx.cannot_move_out_of(span, "static item", origin)
|
tcx.cannot_move_out_of(span, "static item", origin)
|
||||||
}
|
}
|
||||||
IllegalMoveOriginKind::BorrowedContent => {
|
IllegalMoveOriginKind::BorrowedContent { target_ty: ty } => {
|
||||||
tcx.cannot_move_out_of(span, "borrowed content", origin)
|
// 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 } => {
|
IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
|
||||||
tcx.cannot_move_out_of_interior_of_drop(span, ty, origin)
|
tcx.cannot_move_out_of_interior_of_drop(span, ty, origin)
|
||||||
}
|
}
|
||||||
IllegalMoveOriginKind::InteriorOfSliceOrArray { ty, is_index } => {
|
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();
|
err.emit();
|
||||||
|
|
|
@ -119,8 +119,8 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_move_path(&mut self, place: &Place<'tcx>) {
|
fn create_move_path(&mut self, place: &Place<'tcx>) {
|
||||||
// This is an assignment, not a move, so this not being a valid
|
// This is an non-moving access (such as an overwrite or
|
||||||
// move path is OK.
|
// drop), so this not being a valid move path is OK.
|
||||||
let _ = self.move_path_for(place);
|
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);
|
let place_ty = proj.base.ty(mir, tcx).to_ty(tcx);
|
||||||
match place_ty.sty {
|
match place_ty.sty {
|
||||||
ty::TyRef(..) | ty::TyRawPtr(..) =>
|
ty::TyRef(..) | ty::TyRawPtr(..) =>
|
||||||
return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span,
|
return Err(MoveError::cannot_move_out_of(
|
||||||
BorrowedContent)),
|
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() =>
|
ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() =>
|
||||||
return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span,
|
return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span,
|
||||||
InteriorOfTypeWithDestructor {
|
InteriorOfTypeWithDestructor {
|
||||||
|
|
|
@ -277,9 +277,23 @@ pub struct IllegalMoveOrigin<'tcx> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum IllegalMoveOriginKind<'tcx> {
|
pub(crate) enum IllegalMoveOriginKind<'tcx> {
|
||||||
|
/// Illegal move due to attempt to move from `static` variable.
|
||||||
Static,
|
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> },
|
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, },
|
InteriorOfSliceOrArray { ty: ty::Ty<'tcx>, is_index: bool, },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -312,15 +312,19 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
|
||||||
self.cancel_if_wrong_origin(err, o)
|
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,
|
fn cannot_move_out_of_interior_noncopy(self,
|
||||||
move_from_span: Span,
|
move_from_span: Span,
|
||||||
ty: ty::Ty,
|
ty: ty::Ty,
|
||||||
is_index: bool,
|
is_index: Option<bool>,
|
||||||
o: Origin)
|
o: Origin)
|
||||||
-> DiagnosticBuilder<'cx>
|
-> DiagnosticBuilder<'cx>
|
||||||
{
|
{
|
||||||
let type_name = match (&ty.sty, is_index) {
|
let type_name = match (&ty.sty, is_index) {
|
||||||
(&ty::TyArray(_, _), true) => "array",
|
(&ty::TyArray(_, _), Some(true)) |
|
||||||
|
(&ty::TyArray(_, _), None) => "array",
|
||||||
(&ty::TySlice(_), _) => "slice",
|
(&ty::TySlice(_), _) => "slice",
|
||||||
_ => span_bug!(move_from_span, "this path should not cause illegal move"),
|
_ => span_bug!(move_from_span, "this path should not cause illegal move"),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue