]> git.lizzy.rs Git - rust.git/commitdiff
rustc_typeck: register item types for closures
authorAriel Ben-Yehuda <ariel.byd@gmail.com>
Wed, 9 Nov 2016 18:41:03 +0000 (20:41 +0200)
committerAriel Ben-Yehuda <ariel.byd@gmail.com>
Sat, 12 Nov 2016 17:57:23 +0000 (19:57 +0200)
This makes them closer to actual items and allows for more
transparent treatment.

src/librustc_metadata/encoder.rs
src/librustc_typeck/check/closure.rs

index 4d7aa43ce42dbe8ec0a49bd30b53ab82ef483895..778a9d185e145ef797e857617f4ac71da4e0a5f3 100644 (file)
@@ -1056,7 +1056,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
             stability: None,
             deprecation: None,
 
-            ty: None,
+            ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
             variances: LazySeq::empty(),
             generics: Some(self.encode_generics(def_id)),
index d48a129dfe1cd9432065b0086bd40cf3d35c268e..3efbd6b30c2201d9179bd644c0f9c9d38e620ea5 100644 (file)
@@ -13,7 +13,9 @@
 use super::{check_fn, Expectation, FnCtxt};
 
 use astconv::AstConv;
+use rustc::hir::def_id::DefId;
 use rustc::ty::{self, ToPolyTraitRef, Ty};
+use rustc::ty::subst::Substs;
 use rustc::util::common::MemoizationMap;
 use std::cmp;
 use syntax::abi::Abi;
@@ -43,6 +45,48 @@ pub fn check_expr_closure(&self,
         self.check_closure(expr, expected_kind, decl, body, expected_sig)
     }
 
+    fn declare_closure(&self, def_id: DefId) {
+        let tcx = self.tcx.global_tcx();
+
+        tcx.generics.memoize(def_id, || {
+            let node_id = tcx.map.as_local_node_id(def_id).unwrap();
+            let base_def_id = self.tcx.closure_base_def_id(def_id);
+            let base_generics = tcx.item_generics(base_def_id);
+
+            // provide junk type parameter defs - the only place that
+            // cares about anything but the length is instantiation,
+            // and we don't do that for closures.
+            let upvar_decls : Vec<_> = tcx.with_freevars(node_id, |fv| {
+                fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef {
+                    index: (base_generics.count() as u32) + (i as u32),
+                    name: token::intern("<upvar>"),
+                    def_id: def_id,
+                    default_def_id: base_def_id,
+                    default: None,
+                    object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
+                    pure_wrt_drop: false,
+                }).collect()
+            });
+
+            tcx.alloc_generics(ty::Generics {
+                parent: Some(base_def_id),
+                parent_regions: base_generics.parent_regions +
+                    (base_generics.regions.len() as u32),
+                parent_types: base_generics.parent_types +
+                    (base_generics.types.len() as u32),
+                regions: vec![],
+                types: upvar_decls,
+                has_self: false,
+            })
+        });
+
+        tcx.item_types.memoize(def_id, || tcx.mk_closure(def_id, Substs::for_item(
+            tcx, def_id,
+            |def, _| tcx.mk_region(def.to_early_bound_region()),
+            |def, _| tcx.mk_param_from_def(def)
+        )));
+    }
+
     fn check_closure(&self,
                      expr: &hir::Expr,
                      opt_kind: Option<ty::ClosureKind>,
@@ -50,13 +94,13 @@ fn check_closure(&self,
                      body: &'gcx hir::Expr,
                      expected_sig: Option<ty::FnSig<'tcx>>)
                      -> Ty<'tcx> {
-        let expr_def_id = self.tcx.map.local_def_id(expr.id);
-        let base_def_id = self.tcx.closure_base_def_id(expr_def_id);
-
         debug!("check_closure opt_kind={:?} expected_sig={:?}",
                opt_kind,
                expected_sig);
 
+        let expr_def_id = self.tcx.map.local_def_id(expr.id);
+        self.declare_closure(expr_def_id);
+
         let mut fn_ty = AstConv::ty_of_closure(self,
                                                hir::Unsafety::Normal,
                                                decl,
@@ -66,32 +110,7 @@ fn check_closure(&self,
         // Create type variables (for now) to represent the transformed
         // types of upvars. These will be unified during the upvar
         // inference phase (`upvar.rs`).
-        let base_generics = self.tcx.item_generics(base_def_id);
-        // provide junk type parameter defs - the only place that
-        // cares about anything but the length is instantiation,
-        // and we don't do that for closures.
-        let upvar_decls : Vec<_> = self.tcx.with_freevars(expr.id, |fv| {
-            fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef {
-                index: (base_generics.count() as u32) + (i as u32),
-                name: token::intern("<upvar>"),
-                def_id: expr_def_id,
-                default_def_id: base_def_id,
-                default: None,
-                object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
-                pure_wrt_drop: false,
-            }).collect()
-        });
-        let num_upvars = upvar_decls.len();
-
-        self.tcx.generics.memoize(expr_def_id, || self.tcx.alloc_generics(ty::Generics {
-            parent: Some(base_def_id),
-            parent_regions: base_generics.parent_regions + (base_generics.regions.len() as u32),
-            parent_types: base_generics.parent_types + (base_generics.types.len() as u32),
-            regions: vec![],
-            types: upvar_decls,
-            has_self: false,
-        }));
-
+        let num_upvars = self.tcx.with_freevars(expr.id, |fv| fv.len());
         let upvar_tys = self.next_ty_vars(num_upvars);
 
         debug!("check_closure: expr.id={:?} upvar_tys={:?}",