Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Improved how upvars are detected when presenting errors using prefixes.
  • Loading branch information
davidtwco committed Aug 14, 2018
commit 5532e9dec5b2ccb8c746108051f6d0d5378c3b8e
17 changes: 1 addition & 16 deletions src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,25 +151,10 @@ impl<'tcx> Place<'tcx> {
}
},
_ => None,
},
}
_ => None,
}
}

/// Strip the deref projections from a `Place`. For example, given `(*(*((*_1).0: &&T)))`, this
/// will return `((*_1).0)`. Once stripped of any deref projections, places can then be
/// checked as upvar field projections using `is_upvar_field_projection`.
pub fn strip_deref_projections(&self) -> &Place<'tcx> {
let mut current = self;
while let Place::Projection(ref proj) = current {
if let ProjectionElem::Deref = proj.elem {
current = &proj.base;
} else {
break;
}
}
current
}
}

pub enum RvalueInitializationState {
Expand Down
29 changes: 18 additions & 11 deletions src/librustc_mir/borrow_check/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rustc_data_structures::indexed_vec::Idx;
use syntax_pos::Span;

use borrow_check::MirBorrowckCtxt;
use borrow_check::prefixes::PrefixSet;
use dataflow::move_paths::{IllegalMoveOrigin, IllegalMoveOriginKind};
use dataflow::move_paths::{LookupResult, MoveError, MovePathIndex};
use util::borrowck_errors::{BorrowckErrors, Origin};
Expand Down Expand Up @@ -254,15 +255,16 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
// borrow to provide feedback about why this
// was a move rather than a copy.
let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
let is_upvar_field_projection =
self.prefixes(&original_path, PrefixSet::All)
.any(|p| p.is_upvar_field_projection(self.mir, &self.tcx)
.is_some());
match ty.sty {
ty::TyArray(..) | ty::TySlice(..) => self
.tcx
.cannot_move_out_of_interior_noncopy(span, ty, None, origin),
ty::TyClosure(def_id, closure_substs)
if !self.mir.upvar_decls.is_empty() &&
original_path.strip_deref_projections()
.is_upvar_field_projection(self.mir, &self.tcx)
.is_some()
if !self.mir.upvar_decls.is_empty() && is_upvar_field_projection
=> {
let closure_kind_ty =
closure_substs.closure_kind_ty(def_id, self.tcx);
Expand All @@ -286,13 +288,18 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
let mut diag = self.tcx.cannot_move_out_of(
span, place_description, origin);

if let Some(field) = original_path.is_upvar_field_projection(
self.mir, &self.tcx) {
let upvar_decl = &self.mir.upvar_decls[field.index()];
let upvar_hir_id = upvar_decl.var_hir_id.assert_crate_local();
let upvar_node_id = self.tcx.hir.hir_to_node_id(upvar_hir_id);
let upvar_span = self.tcx.hir.span(upvar_node_id);
diag.span_label(upvar_span, "captured outer variable");
for prefix in self.prefixes(&original_path, PrefixSet::All) {
if let Some(field) = prefix.is_upvar_field_projection(
self.mir, &self.tcx) {
let upvar_decl = &self.mir.upvar_decls[field.index()];
let upvar_hir_id =
upvar_decl.var_hir_id.assert_crate_local();
let upvar_node_id =
self.tcx.hir.hir_to_node_id(upvar_hir_id);
let upvar_span = self.tcx.hir.span(upvar_node_id);
diag.span_label(upvar_span, "captured outer variable");
break;
}
}

diag
Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/borrowck/borrowck-move-by-capture.nll.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
error[E0507]: cannot move out of captured variable in an `FnMut` closure
--> $DIR/borrowck-move-by-capture.rs:19:29
|
LL | let bar: Box<_> = box 3;
| --- captured outer variable
LL | let _g = to_fn_mut(|| {
LL | let _h = to_fn_once(move || -> isize { *bar }); //~ ERROR cannot move out of
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of captured variable in an `FnMut` closure

Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/issues/issue-4335.nll.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
error[E0507]: cannot move out of captured variable in an `FnMut` closure
--> $DIR/issue-4335.rs:16:20
|
LL | fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
| - captured outer variable
LL | id(Box::new(|| *v))
| ^^ cannot move out of captured variable in an `FnMut` closure

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
error[E0507]: cannot move out of captured variable in an `Fn` closure
--> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:21:28
|
LL | let i = box 3;
| - captured outer variable
LL | let _f = to_fn(|| test(i)); //~ ERROR cannot move out
| ^ cannot move out of captured variable in an `Fn` closure

Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/nll/issue-52663-span-decl-captured-variable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(nll)]

fn expect_fn<F>(f: F) where F : Fn() {
f();
}

fn main() {
{
let x = (vec![22], vec![44]);
expect_fn(|| drop(x.0));
//~^ ERROR cannot move out of captured variable in an `Fn` closure [E0507]
}
}
11 changes: 11 additions & 0 deletions src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0507]: cannot move out of captured variable in an `Fn` closure
--> $DIR/issue-52663-span-decl-captured-variable.rs:20:26
|
LL | let x = (vec![22], vec![44]);
| - captured outer variable
LL | expect_fn(|| drop(x.0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we highlight something here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, forgot to update the label logic with the same changes that made that branch get used in the first place for complex cases like this one. Fixed now.

| ^^^ cannot move out of captured variable in an `Fn` closure

error: aborting due to previous error

For more information about this error, try `rustc --explain E0507`.
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
error[E0507]: cannot move out of captured variable in an `Fn` closure
--> $DIR/unboxed-closure-illegal-move.rs:25:31
|
LL | let x = Box::new(0);
| - captured outer variable
LL | let f = to_fn(|| drop(x)); //~ ERROR cannot move
| ^ cannot move out of captured variable in an `Fn` closure

error[E0507]: cannot move out of captured variable in an `FnMut` closure
--> $DIR/unboxed-closure-illegal-move.rs:29:35
|
LL | let x = Box::new(0);
| - captured outer variable
LL | let f = to_fn_mut(|| drop(x)); //~ ERROR cannot move
| ^ cannot move out of captured variable in an `FnMut` closure

error[E0507]: cannot move out of captured variable in an `Fn` closure
--> $DIR/unboxed-closure-illegal-move.rs:38:36
|
LL | let x = Box::new(0);
| - captured outer variable
LL | let f = to_fn(move || drop(x)); //~ ERROR cannot move
| ^ cannot move out of captured variable in an `Fn` closure

error[E0507]: cannot move out of captured variable in an `FnMut` closure
--> $DIR/unboxed-closure-illegal-move.rs:42:40
|
LL | let x = Box::new(0);
| - captured outer variable
LL | let f = to_fn_mut(move || drop(x)); //~ ERROR cannot move
| ^ cannot move out of captured variable in an `FnMut` closure

Expand Down