From 15d8e8fb2b5ae3c1493b82077a2c5d3252926227 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Sat, 22 Dec 2018 15:06:14 -0800 Subject: [PATCH] [Cleanup] This is the first in the series of removals of with_freevars usage. Currently, there are many places in rustc, where we use with_freevars to iterate over freevars of a closure. The problem with this is the argument to with_freevars is a NodeId and this will get in the way of our eventual goal of solving for issue (#53488), sub-issue (#56905) --- src/librustc/ty/context.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc_mir/build/mod.rs | 77 +++++++++++++------------- src/librustc_typeck/check/upvar.rs | 10 ++-- src/librustc_typeck/check/writeback.rs | 29 +++++++++- 5 files changed, 74 insertions(+), 46 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index aebf71791bc..8d4b8aae8b1 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -422,7 +422,7 @@ pub struct TypeckTables<'tcx> { /// The upvarID contains the HIR node ID and it also contains the full path /// leading to the member of the struct or tuple that is used instead of the /// entire variable. - pub upvar_list: ty::UpvarListMap<'tcx>, + pub upvar_list: ty::UpvarListMap, } impl<'tcx> TypeckTables<'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8afe0241ac8..cfd99948e43 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -808,7 +808,7 @@ pub struct UpvarBorrow<'tcx> { pub region: ty::Region<'tcx>, } -pub type UpvarListMap<'tcx> = FxHashMap>; +pub type UpvarListMap = FxHashMap>; pub type UpvarCaptureMap<'tcx> = FxHashMap>; #[derive(Copy, Clone)] diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4b0907f8083..b1a377591e3 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -4,7 +4,7 @@ use hair::{LintLevel, BindingMode, PatternKind}; use rustc::hir; use rustc::hir::Node; -use rustc::hir::def_id::{DefId, LocalDefId}; +use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::mir::*; use rustc::mir::visit::{MutVisitor, TyContext}; @@ -640,47 +640,49 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let arguments: Vec<_> = arguments.collect(); let tcx = hir.tcx(); - let span = tcx.hir().span(fn_id); + let tcx_hir = tcx.hir(); + let span = tcx_hir.span(fn_id); - // hir.tables().upvar_list[fn_id]. - // Gather the upvars of a closure, if any. - let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { - freevars.iter().map(|fv| { - let var_id = fv.var_id(); - let var_hir_id = tcx.hir().node_to_hir_id(var_id); - let closure_expr_id = tcx.hir().local_def_id(fn_id); - let capture = hir.tables().upvar_capture(ty::UpvarId { - var_path: ty::UpvarPath {hir_id: var_hir_id}, - closure_expr_id: LocalDefId::from_def_id(closure_expr_id), - }); - let by_ref = match capture { - ty::UpvarCapture::ByValue => false, - ty::UpvarCapture::ByRef(..) => true - }; - let mut decl = UpvarDecl { - debug_name: keywords::Invalid.name(), - var_hir_id: ClearCrossCrate::Set(var_hir_id), - by_ref, - mutability: Mutability::Not, - }; - if let Some(Node::Binding(pat)) = tcx.hir().find(var_id) { - if let hir::PatKind::Binding(_, _, ident, _) = pat.node { - decl.debug_name = ident.name; + let hir_tables = hir.tables(); + let fn_def_id = tcx_hir.local_def_id(fn_id); - if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) { - if bm == ty::BindByValue(hir::MutMutable) { - decl.mutability = Mutability::Mut; + // Gather the upvars of a closure, if any. + let upvar_decls: Vec<_> = match hir_tables.upvar_list.get(&fn_def_id) { + Some(upvars) => upvars + .iter() + .map(|upvar_id| { + let var_hir_id = upvar_id.var_path.hir_id; + let var_node_id = tcx_hir.hir_to_node_id(var_hir_id); + let capture = hir_tables.upvar_capture(*upvar_id); + let by_ref = match capture { + ty::UpvarCapture::ByValue => false, + ty::UpvarCapture::ByRef(..) => true, + }; + let mut decl = UpvarDecl { + debug_name: keywords::Invalid.name(), + var_hir_id: ClearCrossCrate::Set(var_hir_id), + by_ref, + mutability: Mutability::Not, + }; + if let Some(Node::Binding(pat)) = tcx_hir.find(var_node_id) { + if let hir::PatKind::Binding(_, _, ident, _) = pat.node { + decl.debug_name = ident.name; + if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) { + if bm == ty::BindByValue(hir::MutMutable) { + decl.mutability = Mutability::Mut; + } else { + decl.mutability = Mutability::Not; + } } else { - decl.mutability = Mutability::Not; + tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } - } else { - tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } } - } - decl - }).collect() - }); + decl + }) + .collect(), + _ => vec![], + }; let mut builder = Builder::new(hir, span, @@ -690,7 +692,6 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, return_ty_span, upvar_decls); - let fn_def_id = tcx.hir().local_def_id(fn_id); let call_site_scope = region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite @@ -733,7 +734,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, // RustCall pseudo-ABI untuples the last argument. spread_arg = Some(Local::new(arguments.len())); } - let closure_expr_id = tcx.hir().local_def_id(fn_id); + let closure_expr_id = tcx_hir.local_def_id(fn_id); info!("fn_id {:?} has attrs {:?}", closure_expr_id, tcx.get_attrs(closure_expr_id)); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 24d13d9c2ac..ffd7c2114e5 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -156,10 +156,12 @@ fn analyze_closure( // Add the vector of freevars to the map keyed with the closure id. // This gives us an easier access to them without having to call // with_freevars again.. - self.tables - .borrow_mut() - .upvar_list - .insert(closure_node_id, freevar_list); + if !freevar_list.is_empty() { + self.tables + .borrow_mut() + .upvar_list + .insert(closure_def_id, freevar_list); + } }); let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 38de936a027..8499a492bcc 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -20,6 +20,15 @@ /////////////////////////////////////////////////////////////////////////// // Entry point +/// During type inference, partially inferred types are +/// represented using Type variables (ty::Infer). These don't appear in +/// the final TypeckTables since all of the types should have been +/// inferred once typeck_tables_of is done. +/// When type inference is running however, having to update the typeck +/// tables every time a new type is inferred would be unreasonably slow, +/// so instead all of the replacement happens at the end in +/// resolve_type_vars_in_body, which creates a new TypeTables which +/// doesn't contain any inference types. impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> { @@ -35,7 +44,8 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type wbcx.visit_node_id(arg.pat.span, arg.hir_id); } wbcx.visit_body(body); - wbcx.visit_upvar_borrow_map(); + wbcx.visit_upvar_capture_map(); + wbcx.visit_upvar_list_map(); wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); wbcx.visit_fru_field_types(); @@ -291,7 +301,7 @@ fn visit_ty(&mut self, hir_ty: &'gcx hir::Ty) { } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { - fn visit_upvar_borrow_map(&mut self) { + fn visit_upvar_capture_map(&mut self) { for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() { let new_upvar_capture = match *upvar_capture { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, @@ -314,6 +324,21 @@ fn visit_upvar_borrow_map(&mut self) { } } + /// Runs through the function context's upvar list map and adds the same to + /// the TypeckTables. upvarlist is a hashmap of the list of upvars referred + /// to in a closure.. + fn visit_upvar_list_map(&mut self) { + for (closure_def_id, upvar_list) in self.fcx.tables.borrow().upvar_list.iter() { + debug!( + "UpvarIDs captured by closure {:?} are: {:?}", + closure_def_id, upvar_list + ); + self.tables + .upvar_list + .insert(*closure_def_id, upvar_list.to_vec()); + } + } + fn visit_closures(&mut self) { let fcx_tables = self.fcx.tables.borrow(); debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); -- 2.44.0