Improved how upvars are detected when presenting errors using prefixes.
This commit is contained in:
parent
2c6b0e5cf7
commit
5532e9dec5
@ -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 {
|
||||
|
@ -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};
|
||||
@ -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);
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
23
src/test/ui/nll/issue-52663-span-decl-captured-variable.rs
Normal file
23
src/test/ui/nll/issue-52663-span-decl-captured-variable.rs
Normal file
@ -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]
|
||||
}
|
||||
}
|
@ -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));
|
||||
| ^^^ 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`.
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user