about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2016-11-09 20:41:03 +0200
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2016-11-12 19:57:23 +0200
commitb6828fd1acf11272b05c32010f9071d3e8862e76 (patch)
tree3eb8bf995a454ccc896e7624b643c66850f2cf28
parentca9b5664c3c4a052a044d63725239ff2e56136f4 (diff)
downloadrust-b6828fd1acf11272b05c32010f9071d3e8862e76.tar.gz
rust-b6828fd1acf11272b05c32010f9071d3e8862e76.zip
rustc_typeck: register item types for closures
This makes them closer to actual items and allows for more
transparent treatment.
-rw-r--r--src/librustc_metadata/encoder.rs2
-rw-r--r--src/librustc_typeck/check/closure.rs77
2 files changed, 49 insertions, 30 deletions
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 4d7aa43ce42..778a9d185e1 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1056,7 +1056,7 @@ impl<'a, 'tcx> EncodeContext<'a, '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)),
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index d48a129dfe1..3efbd6b30c2 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                      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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // 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={:?}",