From: Eduard-Mihai Burtescu Date: Thu, 8 Jun 2017 10:38:30 +0000 (+0300) Subject: rustc_typeck: do not mutate tables directly during upvar inference. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=5175bc18b5ece1f66a7bfca09202a97728f1d920;p=rust.git rustc_typeck: do not mutate tables directly during upvar inference. --- diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index f5869b8a20f..6e9d028aa64 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1521,10 +1521,6 @@ pub fn type_moves_by_default(&self, !traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span) } - pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { - self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() - } - pub fn closure_kind(&self, def_id: DefId) -> Option diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 0b2652c7488..4075d28a396 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -270,23 +270,9 @@ pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self - { - ExprUseVisitor::with_options(delegate, - infcx, - param_env, - region_maps, - mc::MemCategorizationOptions::default()) - } - - pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a), - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - region_maps: &'a RegionMaps, - options: mc::MemCategorizationOptions) - -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::with_options(infcx, region_maps, options), + mc: mc::MemCategorizationContext::new(infcx, region_maps), delegate, param_env, } @@ -678,8 +664,8 @@ fn contains_field_named(field: &ty::FieldDef, // consumed or borrowed as part of the automatic adjustment // process. fn walk_adjustment(&mut self, expr: &hir::Expr) { - //NOTE(@jroesch): mixed RefCell borrow causes crash - let adjustments = self.mc.infcx.tables.borrow().expr_adjustments(expr).to_vec(); + let tables = self.mc.infcx.tables.borrow(); + let adjustments = tables.expr_adjustments(expr); let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); @@ -896,7 +882,7 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) { let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id }; - let upvar_capture = self.mc.infcx.upvar_capture(upvar_id).unwrap(); + let upvar_capture = self.mc.infcx.tables.borrow().upvar_capture(upvar_id); let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, fn_decl_span, freevar.def)); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c114aa1d7a8..ddbc7f91097 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -283,18 +283,6 @@ fn span(&self) -> Span { self.span } pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, pub region_maps: &'a RegionMaps, - options: MemCategorizationOptions, -} - -#[derive(Copy, Clone, Default)] -pub struct MemCategorizationOptions { - // If true, then when analyzing a closure upvar, if the closure - // has a missing kind, we treat it like a Fn closure. When false, - // we ICE if the closure has a missing kind. Should be false - // except during closure kind inference. It is used by the - // mem-categorization code to be able to have stricter assertions - // (which are always true except during upvar inference). - pub during_closure_kind_inference: bool, } pub type McResult = Result; @@ -400,20 +388,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, region_maps: &'a RegionMaps) -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext::with_options(infcx, - region_maps, - MemCategorizationOptions::default()) - } - - pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps, - options: MemCategorizationOptions) - -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext { - infcx: infcx, - region_maps: region_maps, - options: options, - } + MemCategorizationContext { infcx, region_maps } } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { @@ -620,38 +595,14 @@ pub fn cat_def(&self, Def::Upvar(def_id, _, fn_node_id) => { let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - let ty = self.node_ty(fn_node_id)?; - match ty.sty { - ty::TyClosure(closure_id, _) => { - match self.infcx.closure_kind(closure_id) { - Some(kind) => { - self.cat_upvar(id, span, var_id, fn_node_id, kind) - } - None => { - if !self.options.during_closure_kind_inference { - span_bug!( - span, - "No closure kind for {:?}", - closure_id); - } - - // during closure kind inference, we - // don't know the closure kind yet, but - // it's ok because we detect that we are - // accessing an upvar and handle that - // case specially anyhow. Use Fn - // arbitrarily. - self.cat_upvar(id, span, var_id, fn_node_id, ty::ClosureKind::Fn) - } - } - } - _ => { - span_bug!( - span, - "Upvar of non-closure {} - {:?}", - fn_node_id, - ty); - } + let closure_id = self.tcx().hir.local_def_id(fn_node_id); + match self.infcx.closure_kind(closure_id) { + Some(kind) => { + self.cat_upvar(id, span, var_id, fn_node_id, kind) + } + None => { + span_bug!(span, "No closure kind for {:?}", closure_id); + } } } @@ -743,7 +694,7 @@ fn cat_upvar(&self, // for that. let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: fn_node_id }; - let upvar_capture = self.infcx.upvar_capture(upvar_id).unwrap(); + let upvar_capture = self.infcx.tables.borrow().upvar_capture(upvar_id); let cmt_result = match upvar_capture { ty::UpvarCapture::ByValue => { cmt_result diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2bbb71610ad..2d81606329e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -376,8 +376,8 @@ pub fn is_method_call(&self, expr: &hir::Expr) -> bool { } } - pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { - Some(self.upvar_capture_map.get(&upvar_id).unwrap().clone()) + pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { + self.upvar_capture_map[&upvar_id] } } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 08a5cb37e57..7490ee60e1f 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -365,13 +365,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { let var_id = tcx.hir.as_local_node_id(fv.def.def_id()).unwrap(); - let by_ref = hir.tables().upvar_capture(ty::UpvarId { + let capture = hir.tables().upvar_capture(ty::UpvarId { var_id: var_id, closure_expr_id: fn_id - }).map_or(false, |capture| match capture { + }); + let by_ref = match capture { ty::UpvarCapture::ByValue => false, ty::UpvarCapture::ByRef(..) => true - }); + }; let mut decl = UpvarDecl { debug_name: keywords::Invalid.name(), by_ref: by_ref diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8cfeecdafb5..474feefabbb 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -758,13 +758,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr_id, }; - let upvar_capture = match cx.tables().upvar_capture(upvar_id) { - Some(c) => c, - None => { - span_bug!(expr.span, "no upvar_capture for {:?}", upvar_id); - } - }; - match upvar_capture { + match cx.tables().upvar_capture(upvar_id) { ty::UpvarCapture::ByValue => field_kind, ty::UpvarCapture::ByRef(borrow) => { ExprKind::Deref { @@ -878,7 +872,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr.id, }; - let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap(); + let upvar_capture = cx.tables().upvar_capture(upvar_id); let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.id); let var_ty = cx.tables().node_id_to_type(id_var); let captured_var = Expr { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b66e311f04c..9c3e5cd1f40 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -834,8 +834,8 @@ fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult { - let upvar_capture_map = &self.tables.borrow_mut().upvar_capture_map; - match upvar_capture_map.get(upvar_id) { + match self.tables.borrow().upvar_capture_map.get(upvar_id) { Some(&ty::UpvarCapture::ByRef(ref upvar_borrow)) => { // The mutability of the upvar may have been modified // by the above adjustment, so update our local variable. diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 25f5418bea9..1f0911bb234 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -53,31 +53,22 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::util::nodemap::NodeMap; -/////////////////////////////////////////////////////////////////////////// -// PUBLIC ENTRY POINTS +use std::collections::hash_map::Entry; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn closure_analyze(&self, body: &'gcx hir::Body) { - let mut seed = SeedBorrowKind::new(self); - seed.visit_body(body); - - let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds); - adjust.visit_body(body); + InferBorrowKindVisitor { fcx: self }.visit_body(body); // it's our job to process these. assert!(self.deferred_call_resolutions.borrow().is_empty()); } } -/////////////////////////////////////////////////////////////////////////// -// SEED BORROW KIND - -struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +struct InferBorrowKindVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, } -impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { NestedVisitorMap::None } @@ -87,7 +78,7 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) { hir::ExprClosure(cc, _, body_id, _) => { let body = self.fcx.tcx.hir.body(body_id); self.visit_body(body); - self.check_closure(expr, cc); + self.fcx.analyze_closure(expr.id, expr.span, body, cc); } _ => { } @@ -97,26 +88,33 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) { } } -impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { - fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>) -> SeedBorrowKind<'a, 'gcx, 'tcx> { - SeedBorrowKind { fcx: fcx, temp_closure_kinds: NodeMap() } - } +impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { + fn analyze_closure(&self, + id: ast::NodeId, + span: Span, + body: &hir::Body, + capture_clause: hir::CaptureClause) { + /*! + * Analysis starting point. + */ - fn check_closure(&mut self, - expr: &hir::Expr, - 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, None)); - debug!("check_closure: adding closure {:?} as Fn", expr.id); - } + debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id()); - self.fcx.tcx.with_freevars(expr.id, |freevars| { + let infer_kind = match self.tables.borrow_mut().closure_kinds.entry(id) { + Entry::Occupied(_) => false, + Entry::Vacant(entry) => { + debug!("check_closure: adding closure {:?} as Fn", id); + entry.insert((ty::ClosureKind::Fn, None)); + true + } + }; + + self.tcx.with_freevars(id, |freevars| { for freevar in freevars { let def_id = freevar.def.def_id(); - let var_node_id = self.fcx.tcx.hir.as_local_node_id(def_id).unwrap(); + let var_node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: var_node_id, - closure_expr_id: expr.id }; + closure_expr_id: id }; debug!("seed upvar_id {:?}", upvar_id); let capture_kind = match capture_clause { @@ -124,58 +122,37 @@ fn check_closure(&mut self, ty::UpvarCapture::ByValue } hir::CaptureByRef => { - let origin = UpvarRegion(upvar_id, expr.span); - let freevar_region = self.fcx.next_region_var(origin); + let origin = UpvarRegion(upvar_id, span); + let freevar_region = self.next_region_var(origin); let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: freevar_region }; ty::UpvarCapture::ByRef(upvar_borrow) } }; - self.fcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, capture_kind); + self.tables.borrow_mut().upvar_capture_map.insert(upvar_id, capture_kind); } }); - } -} - -/////////////////////////////////////////////////////////////////////////// -// ADJUST BORROW KIND - -struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - 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, ast::Name)>)>) - -> AdjustBorrowKind<'a, 'gcx, 'tcx> { - AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds } - } - - fn analyze_closure(&mut self, - id: ast::NodeId, - span: Span, - body: &hir::Body) { - /*! - * Analysis starting point. - */ - - debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id()); { - let body_owner_def_id = self.fcx.tcx.hir.body_owner_def_id(body.id()); - let region_maps = &self.fcx.tcx.region_maps(body_owner_def_id); - let param_env = self.fcx.param_env; - let mut euv = - euv::ExprUseVisitor::with_options(self, - self.fcx, - param_env, - region_maps, - mc::MemCategorizationOptions { - during_closure_kind_inference: true - }); - euv.consume_body(body); + let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id()); + let region_maps = &self.tcx.region_maps(body_owner_def_id); + let mut delegate = InferBorrowKind { + fcx: self, + adjust_closure_kinds: NodeMap(), + adjust_upvar_captures: ty::UpvarCaptureMap::default(), + }; + euv::ExprUseVisitor::new(&mut delegate, region_maps, self, self.param_env) + .consume_body(body); + + // Write the adjusted values back into the main tables. + if infer_kind { + if let Some(kind) = delegate.adjust_closure_kinds.remove(&id) { + self.tables.borrow_mut().closure_kinds.insert(id, kind); + } + } + self.tables.borrow_mut().upvar_capture_map.extend( + delegate.adjust_upvar_captures); } // Now that we've analyzed the closure, we know how each @@ -191,7 +168,7 @@ fn analyze_closure(&mut self, // inference algorithm will reject it). // Extract the type variables UV0...UVn. - let (def_id, closure_substs) = match self.fcx.node_ty(id).sty { + let (def_id, closure_substs) = match self.node_ty(id).sty { ty::TyClosure(def_id, substs) => (def_id, substs), ref t => { span_bug!( @@ -206,44 +183,41 @@ fn analyze_closure(&mut self, debug!("analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}", id, closure_substs, final_upvar_tys); for (upvar_ty, final_upvar_ty) in - closure_substs.upvar_tys(def_id, self.fcx.tcx).zip(final_upvar_tys) + closure_substs.upvar_tys(def_id, self.tcx).zip(final_upvar_tys) { - self.fcx.demand_eqtype(span, final_upvar_ty, upvar_ty); + self.demand_eqtype(span, final_upvar_ty, upvar_ty); } - // If we are also inferred the closure kind here, update the - // main table and process any deferred resolutions. - 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); - + // If we are also inferred the closure kind here, + // process any deferred resolutions. + if infer_kind { + let closure_def_id = self.tcx.hir.local_def_id(id); let deferred_call_resolutions = - self.fcx.remove_deferred_call_resolutions(closure_def_id); + self.remove_deferred_call_resolutions(closure_def_id); for deferred_call_resolution in deferred_call_resolutions { - deferred_call_resolution.resolve(self.fcx); + deferred_call_resolution.resolve(self); } } } // Returns a list of `ClosureUpvar`s for each upvar. - fn final_upvar_tys(&mut self, closure_id: ast::NodeId) -> Vec> { + fn final_upvar_tys(&self, closure_id: ast::NodeId) -> Vec> { // Presently an unboxed closure type cannot "escape" out of a // function, so we will only encounter ones that originated in the // local crate or were inlined into it along with some function. // This may change if abstract return types of some sort are // implemented. - let tcx = self.fcx.tcx; + let tcx = self.tcx; tcx.with_freevars(closure_id, |freevars| { freevars.iter().map(|freevar| { let def_id = freevar.def.def_id(); let var_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let freevar_ty = self.fcx.node_ty(var_id); + let freevar_ty = self.node_ty(var_id); let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: closure_id }; - let capture = self.fcx.upvar_capture(upvar_id).unwrap(); + let capture = self.tables.borrow().upvar_capture(upvar_id); debug!("var_id={:?} freevar_ty={:?} capture={:?}", var_id, freevar_ty, capture); @@ -260,7 +234,15 @@ fn final_upvar_tys(&mut self, closure_id: ast::NodeId) -> Vec> { }).collect() }) } +} +struct InferBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, + adjust_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, + adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>, +} + +impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) @@ -297,9 +279,7 @@ fn adjust_upvar_borrow_kind_for_consume(&mut self, guarantor.span, tcx.hir.name(upvar_id.var_id)); - let upvar_capture_map = - &mut self.fcx.tables.borrow_mut().upvar_capture_map; - upvar_capture_map.insert(upvar_id, ty::UpvarCapture::ByValue); + self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue); } mc::NoteClosureEnv(upvar_id) => { // we get just a closureenv ref if this is a @@ -410,11 +390,7 @@ fn try_adjust_upvar_deref(&mut self, // upvar, then we need to modify the // borrow_kind of the upvar to make sure it // is inferred to mutable if necessary - { - let upvar_capture_map = &mut self.fcx.tables.borrow_mut().upvar_capture_map; - let ub = upvar_capture_map.get_mut(&upvar_id).unwrap(); - self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind); - } + self.adjust_upvar_borrow_kind(upvar_id, borrow_kind); // also need to be in an FnMut closure since this is not an ImmBorrow self.adjust_closure_kind(upvar_id.closure_expr_id, @@ -448,22 +424,25 @@ fn try_adjust_upvar_deref(&mut self, /// some particular use. fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, - upvar_capture: &mut ty::UpvarCapture, kind: ty::BorrowKind) { + let upvar_capture = self.adjust_upvar_captures.get(&upvar_id).cloned() + .unwrap_or_else(|| self.fcx.tables.borrow().upvar_capture(upvar_id)); debug!("adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})", upvar_id, upvar_capture, kind); - match *upvar_capture { + match upvar_capture { ty::UpvarCapture::ByValue => { // Upvar is already by-value, the strongest criteria. } - ty::UpvarCapture::ByRef(ref mut upvar_borrow) => { + ty::UpvarCapture::ByRef(mut upvar_borrow) => { match (upvar_borrow.kind, kind) { // Take RHS: (ty::ImmBorrow, ty::UniqueImmBorrow) | (ty::ImmBorrow, ty::MutBorrow) | (ty::UniqueImmBorrow, ty::MutBorrow) => { upvar_borrow.kind = kind; + self.adjust_upvar_captures.insert(upvar_id, + ty::UpvarCapture::ByRef(upvar_borrow)); } // Take LHS: (ty::ImmBorrow, ty::ImmBorrow) | @@ -484,7 +463,9 @@ fn adjust_closure_kind(&mut self, 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) { + let closure_kind = self.adjust_closure_kinds.get(&closure_id).cloned() + .or_else(|| self.fcx.tables.borrow().closure_kinds.get(&closure_id).cloned()); + if let Some((existing_kind, _)) = closure_kind { debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", closure_id, existing_kind, new_kind); @@ -500,7 +481,7 @@ fn adjust_closure_kind(&mut self, (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( + self.adjust_closure_kinds.insert( closure_id, (new_kind, Some((upvar_span, var_name))) ); @@ -510,27 +491,7 @@ fn adjust_closure_kind(&mut self, } } -impl<'a, 'gcx, 'tcx> Visitor<'gcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::None - } - - fn visit_fn(&mut self, - fn_kind: intravisit::FnKind<'gcx>, - decl: &'gcx hir::FnDecl, - body: hir::BodyId, - span: Span, - id: ast::NodeId) - { - intravisit::walk_fn(self, fn_kind, decl, body, span, id); - - let body = self.fcx.tcx.hir.body(body); - self.visit_body(body); - self.analyze_closure(id, span, body); - } -} - -impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { fn consume(&mut self, _consume_id: ast::NodeId, _consume_span: Span,