Skip to content

Commit

Permalink
rustc_typeck: register item types for closures
Browse files Browse the repository at this point in the history
This makes them closer to actual items and allows for more
transparent treatment.
  • Loading branch information
arielb1 committed Nov 12, 2016
1 parent ca9b566 commit b6828fd
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/librustc_metadata/encoder.rs
Expand Up @@ -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)),
Expand Down
77 changes: 48 additions & 29 deletions src/librustc_typeck/check/closure.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -43,20 +45,62 @@ 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>,
decl: &'gcx hir::FnDecl,
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,
Expand All @@ -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={:?}",
Expand Down

0 comments on commit b6828fd

Please sign in to comment.