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(""), + 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, @@ -50,13 +94,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { body: &'gcx hir::Expr, expected_sig: Option>) -> 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(""), - 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={:?}",