Skip to content

NLL: report type moved from behind borrow of array/slice #51247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc_borrowck/borrowck/gather_loans/move_error.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
10 changes: 5 additions & 5 deletions src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr
Original file line number Diff line number Diff line change
@@ -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`.
77 changes: 51 additions & 26 deletions src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr
Original file line number Diff line number Diff line change
@@ -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<isize>]`, 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<isize>]`, 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<isize>]`, 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<isize>]`, 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<isize>]`, 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<isize>]`, 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<isize>]`, 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<isize>]`, 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`.
5 changes: 5 additions & 0 deletions src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
Expand All @@ -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();
}
}
}
Expand Down Expand Up @@ -82,3 +84,6 @@ fn e() {
}

fn main() {}

trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } }
impl<T> Fake for T { }
14 changes: 7 additions & 7 deletions src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<isize>]`, 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`
Expand All @@ -30,7 +30,7 @@ LL | | ] => {
| |_________^ cannot move out of here

error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, 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
| ^^^^^^
Expand All @@ -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<isize>]`, 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
| ______________^
Expand All @@ -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<isize>]`, 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
| ^^^^^^
Expand All @@ -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<isize>]`, 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
| ^--^^--^^--^
Expand All @@ -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<isize>]`, 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
| ^^^^^^
Expand Down