diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 270430f40df0..a6dbbee79a48 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1682,7 +1682,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { if let InferTables::InProgress(tables) = self.tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { - return tables.borrow().closure_kinds.get(&id).cloned(); + return tables.borrow() + .closure_kinds + .get(&id) + .cloned() + .map(|(kind, _)| kind); } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 5ee0b1c9e5ea..bc9fd1147b6e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -58,6 +58,7 @@ use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::symbol::{Symbol, keywords}; +use syntax_pos::Span; use hir; @@ -229,8 +230,9 @@ pub struct TypeckTables<'tcx> { /// Records the type of each closure. pub closure_tys: NodeMap>, - /// Records the kind of each closure. - pub closure_kinds: NodeMap, + /// 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)>, /// For each fn, records the "liberated" types of its arguments /// and return type. Liberated means that all bound regions diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 4c3d5c8aaca7..c2e8269aafef 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -103,7 +103,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tables.borrow_mut().closure_tys.insert(expr.id, sig); match opt_kind { Some(kind) => { - self.tables.borrow_mut().closure_kinds.insert(expr.id, kind); + self.tables.borrow_mut().closure_kinds.insert(expr.id, (kind, None)); } None => {} } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 9ad72b2a137e..7981df9211aa 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -802,7 +802,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let closure_kinds = &self.tables.borrow().closure_kinds; let closure_kind = match closure_kinds.get(&closure_id) { - Some(&k) => k, + Some(&(k, _)) => k, None => { return Err(MethodError::ClosureAmbiguity(trait_def_id)); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 24a88140cf04..06af22b9a41e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -702,7 +702,7 @@ fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureKind { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - tcx.typeck_tables_of(def_id).closure_kinds[&node_id] + tcx.typeck_tables_of(def_id).closure_kinds[&node_id].0 } fn adt_destructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 9bfc5f3f0ea5..3d5cb13b0eed 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -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, + temp_closure_kinds: NodeMap<(ty::ClosureKind, Option)>, } impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { @@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { capture_clause: hir::CaptureClause) { if !self.fcx.tables.borrow().closure_kinds.contains_key(&expr.id) { - self.temp_closure_kinds.insert(expr.id, ty::ClosureKind::Fn); + self.temp_closure_kinds.insert(expr.id, (ty::ClosureKind::Fn, None)); debug!("check_closure: adding closure {:?} as Fn", expr.id); } @@ -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, + temp_closure_kinds: NodeMap<(ty::ClosureKind, Option)>, } impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - temp_closure_kinds: NodeMap) + temp_closure_kinds: NodeMap<(ty::ClosureKind, Option)>) -> 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) = self.temp_closure_kinds.get(&id) { - self.fcx.tables.borrow_mut().closure_kinds.insert(id, kind); + if let Some(&(kind, span)) = self.temp_closure_kinds.get(&id) { + self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, span)); let closure_def_id = self.fcx.tcx.hir.local_def_id(id); debug!("closure_kind({:?}) = {:?}", closure_def_id, kind); @@ -276,6 +276,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // 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 { @@ -289,7 +290,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); + ty::ClosureKind::FnOnce, + tcx.hir.span(upvar_id.var_id)); let upvar_capture_map = &mut self.fcx.tables.borrow_mut().upvar_capture_map; @@ -303,7 +305,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // to be a FnOnce closure to permit moves out // of the environment. self.adjust_closure_kind(upvar_id.closure_expr_id, - ty::ClosureKind::FnOnce); + ty::ClosureKind::FnOnce, + tcx.hir.span(upvar_id.var_id)); } mc::NoteNone => { } @@ -394,6 +397,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { ty::ImmBorrow => false, }); + let tcx = self.fcx.tcx; + match *note { mc::NoteUpvarRef(upvar_id) => { // if this is an implicit deref of an @@ -407,7 +412,9 @@ 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); + self.adjust_closure_kind(upvar_id.closure_expr_id, + ty::ClosureKind::FnMut, + tcx.hir.span(upvar_id.var_id)); true } @@ -415,7 +422,9 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // this kind of deref occurs in a `move` closure, or // for a by-value upvar; in either case, to mutate an // upvar, we need to be an FnMut closure - self.adjust_closure_kind(upvar_id.closure_expr_id, ty::ClosureKind::FnMut); + self.adjust_closure_kind(upvar_id.closure_expr_id, + ty::ClosureKind::FnMut, + tcx.hir.span(upvar_id.var_id)); true } @@ -462,11 +471,12 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { fn adjust_closure_kind(&mut self, closure_id: ast::NodeId, - new_kind: ty::ClosureKind) { + new_kind: ty::ClosureKind, + upvar_span: Span) { debug!("adjust_closure_kind(closure_id={}, new_kind={:?})", closure_id, new_kind); - if let Some(&existing_kind) = self.temp_closure_kinds.get(&closure_id) { + if let Some(&(existing_kind, _)) = self.temp_closure_kinds.get(&closure_id) { debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", closure_id, existing_kind, new_kind); @@ -482,7 +492,7 @@ 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); + self.temp_closure_kinds.insert(closure_id, (new_kind, Some(upvar_span))); } } }