Explain why closure is moved in error message
This commit is contained in:
parent
bf25b5eb82
commit
ee88a870b6
@ -230,9 +230,9 @@ pub struct TypeckTables<'tcx> {
|
||||
/// Records the type of each closure.
|
||||
pub closure_tys: NodeMap<ty::PolyFnSig<'tcx>>,
|
||||
|
||||
/// Records the kind of each closure and the span of the variable that
|
||||
/// cause the closure to be this kind.
|
||||
pub closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
|
||||
/// Records the kind of each closure and the span and name of the variable
|
||||
/// that caused the closure to be this kind.
|
||||
pub closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
|
||||
|
||||
/// For each fn, records the "liberated" types of its arguments
|
||||
/// and return type. Liberated means that all bound regions
|
||||
|
@ -39,8 +39,6 @@ use rustc::middle::free_region::RegionRelations;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::maps::Providers;
|
||||
|
||||
use syntax_pos::DUMMY_SP;
|
||||
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use std::hash::{Hash, Hasher};
|
||||
@ -594,12 +592,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
verb, msg, nl);
|
||||
let need_note = match lp.ty.sty {
|
||||
ty::TypeVariants::TyClosure(id, _) => {
|
||||
if let Ok(ty::ClosureKind::FnOnce) =
|
||||
ty::queries::closure_kind::try_get(self.tcx, DUMMY_SP, id) {
|
||||
err.help("closure was moved because it only implements `FnOnce`");
|
||||
if let Some(&(_kind, Some(span))) = self.tables.closure_kinds.get( ) {
|
||||
err.span_label(span, "move occured here");
|
||||
}
|
||||
let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
|
||||
if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) =
|
||||
self.tables.closure_kinds.get(&node_id)
|
||||
{
|
||||
err.help(&format!("closure cannot be invoked more than once because \
|
||||
it moves the variable `{}` out of its environment",
|
||||
name));
|
||||
err.span_label(span, format!("{} moved here", name));
|
||||
false
|
||||
} else {
|
||||
true
|
||||
|
@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
|
||||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> {
|
||||
@ -143,12 +143,12 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
|
||||
|
||||
struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>,
|
||||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<Span>)>)
|
||||
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>)
|
||||
-> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds }
|
||||
}
|
||||
@ -211,8 +211,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
|
||||
// If we are also inferred the closure kind here, update the
|
||||
// main table and process any deferred resolutions.
|
||||
if let Some(&(kind, span)) = self.temp_closure_kinds.get(&id) {
|
||||
self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, span));
|
||||
if let Some(&(kind, context)) = self.temp_closure_kinds.get(&id) {
|
||||
self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, context));
|
||||
let closure_def_id = self.fcx.tcx.hir.local_def_id(id);
|
||||
debug!("closure_kind({:?}) = {:?}", closure_def_id, kind);
|
||||
|
||||
@ -272,11 +272,12 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
euv::Move(_) => { }
|
||||
}
|
||||
|
||||
let tcx = self.fcx.tcx;
|
||||
|
||||
// watch out for a move of the deref of a borrowed pointer;
|
||||
// for that to be legal, the upvar would have to be borrowed
|
||||
// by value instead
|
||||
let guarantor = cmt.guarantor();
|
||||
let tcx = self.fcx.tcx;
|
||||
debug!("adjust_upvar_borrow_kind_for_consume: guarantor={:?}",
|
||||
guarantor);
|
||||
match guarantor.cat {
|
||||
@ -291,7 +292,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
// to move out of an upvar, this must be a FnOnce closure
|
||||
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
||||
ty::ClosureKind::FnOnce,
|
||||
tcx.hir.span(upvar_id.var_id));
|
||||
guarantor.span,
|
||||
tcx.hir.name(upvar_id.var_id));
|
||||
|
||||
let upvar_capture_map =
|
||||
&mut self.fcx.tables.borrow_mut().upvar_capture_map;
|
||||
@ -306,7 +308,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
// of the environment.
|
||||
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
||||
ty::ClosureKind::FnOnce,
|
||||
tcx.hir.span(upvar_id.var_id));
|
||||
guarantor.span,
|
||||
tcx.hir.name(upvar_id.var_id));
|
||||
}
|
||||
mc::NoteNone => {
|
||||
}
|
||||
@ -334,7 +337,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
|
||||
Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
|
||||
Categorization::Deref(base, _, mc::Implicit(..)) => {
|
||||
if !self.try_adjust_upvar_deref(&cmt.note, ty::MutBorrow) {
|
||||
if !self.try_adjust_upvar_deref(cmt, ty::MutBorrow) {
|
||||
// assignment to deref of an `&mut`
|
||||
// borrowed pointer implies that the
|
||||
// pointer itself must be unique, but not
|
||||
@ -368,7 +371,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
|
||||
Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
|
||||
Categorization::Deref(base, _, mc::Implicit(..)) => {
|
||||
if !self.try_adjust_upvar_deref(&cmt.note, ty::UniqueImmBorrow) {
|
||||
if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
|
||||
// for a borrowed pointer to be unique, its
|
||||
// base must be unique
|
||||
self.adjust_upvar_borrow_kind_for_unique(base);
|
||||
@ -385,7 +388,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn try_adjust_upvar_deref(&mut self,
|
||||
note: &mc::Note,
|
||||
cmt: mc::cmt<'tcx>,
|
||||
borrow_kind: ty::BorrowKind)
|
||||
-> bool
|
||||
{
|
||||
@ -399,7 +402,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
|
||||
let tcx = self.fcx.tcx;
|
||||
|
||||
match *note {
|
||||
match cmt.note {
|
||||
mc::NoteUpvarRef(upvar_id) => {
|
||||
// if this is an implicit deref of an
|
||||
// upvar, then we need to modify the
|
||||
@ -414,7 +417,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
// also need to be in an FnMut closure since this is not an ImmBorrow
|
||||
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
||||
ty::ClosureKind::FnMut,
|
||||
tcx.hir.span(upvar_id.var_id));
|
||||
cmt.span,
|
||||
tcx.hir.name(upvar_id.var_id));
|
||||
|
||||
true
|
||||
}
|
||||
@ -424,7 +428,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
// upvar, we need to be an FnMut closure
|
||||
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
||||
ty::ClosureKind::FnMut,
|
||||
tcx.hir.span(upvar_id.var_id));
|
||||
cmt.span,
|
||||
tcx.hir.name(upvar_id.var_id));
|
||||
|
||||
true
|
||||
}
|
||||
@ -472,9 +477,10 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
fn adjust_closure_kind(&mut self,
|
||||
closure_id: ast::NodeId,
|
||||
new_kind: ty::ClosureKind,
|
||||
upvar_span: Span) {
|
||||
debug!("adjust_closure_kind(closure_id={}, new_kind={:?})",
|
||||
closure_id, new_kind);
|
||||
upvar_span: Span,
|
||||
var_name: ast::Name) {
|
||||
debug!("adjust_closure_kind(closure_id={}, new_kind={:?}, upvar_span={:?}, var_name={})",
|
||||
closure_id, new_kind, upvar_span, var_name);
|
||||
|
||||
if let Some(&(existing_kind, _)) = self.temp_closure_kinds.get(&closure_id) {
|
||||
debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
|
||||
@ -492,7 +498,10 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
|
||||
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
|
||||
// new kind is stronger than the old kind
|
||||
self.temp_closure_kinds.insert(closure_id, (new_kind, Some(upvar_span)));
|
||||
self.temp_closure_kinds.insert(
|
||||
closure_id,
|
||||
(new_kind, Some((upvar_span, var_name)))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user