]> git.lizzy.rs Git - rust.git/commitdiff
[Cleanup] This is the first in the series of removals of with_freevars usage.
authorBlitzerr <rusty.blitzerr@gmail.com>
Sat, 22 Dec 2018 23:06:14 +0000 (15:06 -0800)
committerBlitzerr <rusty.blitzerr@gmail.com>
Wed, 9 Jan 2019 01:57:22 +0000 (17:57 -0800)
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
src/librustc/ty/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/writeback.rs

index aebf71791bc6061ba935f4adb754101f9878f6f0..8d4b8aae8b1767641a3705010f4fdd0e4a7f668c 100644 (file)
@@ -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> {
index 8afe0241ac8638db66b3d2e182107398c0b42ecd..cfd99948e4370424f991da6d61dc16a159006182 100644 (file)
@@ -808,7 +808,7 @@ pub struct UpvarBorrow<'tcx> {
     pub region: ty::Region<'tcx>,
 }
 
-pub type UpvarListMap<'tcx> = FxHashMap<ast::NodeId, Vec<UpvarId>>;
+pub type UpvarListMap = FxHashMap<DefId, Vec<UpvarId>>;
 pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
 
 #[derive(Copy, Clone)]
index 4b0907f808364c749e32146d53da832eb7e77507..b1a377591e31025c1243bd1fa10080cada89a9b2 100644 (file)
@@ -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));
 
index 24d13d9c2acfa3d38b064776aea00f9a27602f9e..ffd7c2114e5ab34294c4f03584d02d669ce4cf42 100644 (file)
@@ -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());
index 38de936a027ff6e2dd4e28ddb2d70812ea138744..8499a492bccec7bc7523ff943258fea194b88c84 100644 (file)
 
 ///////////////////////////////////////////////////////////////////////////
 // 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);