Skip to content

Commit

Permalink
Rollup merge of rust-lang#51247 - pnkfelix:issue-51190-report-type-mo…
Browse files Browse the repository at this point in the history
…ved-from-behind-borrow, r=nikomatsakis

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

When NLL has illegal move due to borrowed content in an array or slice, provide feedback about why the move wasn't a copy.

Drive by: While comparing the resulting `.nll.stderr` files to their old borrowck variants, I noticed that the test for borrowck-vec-pattern-nesting.rs was not signaling some errors under NLL due to the test assuming lexical lifetimes. So I fixed that too.

Fix rust-lang#51190
  • Loading branch information
Mark-Simulacrum authored Jun 6, 2018
2 parents 60d8ed3 + e5b378b commit 0c6094f
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 49 deletions.
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

0 comments on commit 0c6094f

Please sign in to comment.