rustc_typeck: register item types for closures
This makes them closer to actual items and allows for more transparent treatment.
This commit is contained in:
parent
ca9b5664c3
commit
b6828fd1ac
2 changed files with 49 additions and 30 deletions
|
@ -1056,7 +1056,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
stability: None,
|
stability: None,
|
||||||
deprecation: None,
|
deprecation: None,
|
||||||
|
|
||||||
ty: None,
|
ty: Some(self.encode_item_type(def_id)),
|
||||||
inherent_impls: LazySeq::empty(),
|
inherent_impls: LazySeq::empty(),
|
||||||
variances: LazySeq::empty(),
|
variances: LazySeq::empty(),
|
||||||
generics: Some(self.encode_generics(def_id)),
|
generics: Some(self.encode_generics(def_id)),
|
||||||
|
|
|
@ -13,7 +13,9 @@
|
||||||
use super::{check_fn, Expectation, FnCtxt};
|
use super::{check_fn, Expectation, FnCtxt};
|
||||||
|
|
||||||
use astconv::AstConv;
|
use astconv::AstConv;
|
||||||
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::ty::{self, ToPolyTraitRef, Ty};
|
use rustc::ty::{self, ToPolyTraitRef, Ty};
|
||||||
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::util::common::MemoizationMap;
|
use rustc::util::common::MemoizationMap;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use syntax::abi::Abi;
|
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)
|
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,
|
fn check_closure(&self,
|
||||||
expr: &hir::Expr,
|
expr: &hir::Expr,
|
||||||
opt_kind: Option<ty::ClosureKind>,
|
opt_kind: Option<ty::ClosureKind>,
|
||||||
|
@ -50,13 +94,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
body: &'gcx hir::Expr,
|
body: &'gcx hir::Expr,
|
||||||
expected_sig: Option<ty::FnSig<'tcx>>)
|
expected_sig: Option<ty::FnSig<'tcx>>)
|
||||||
-> Ty<'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={:?}",
|
debug!("check_closure opt_kind={:?} expected_sig={:?}",
|
||||||
opt_kind,
|
opt_kind,
|
||||||
expected_sig);
|
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,
|
let mut fn_ty = AstConv::ty_of_closure(self,
|
||||||
hir::Unsafety::Normal,
|
hir::Unsafety::Normal,
|
||||||
decl,
|
decl,
|
||||||
|
@ -66,32 +110,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// Create type variables (for now) to represent the transformed
|
// Create type variables (for now) to represent the transformed
|
||||||
// types of upvars. These will be unified during the upvar
|
// types of upvars. These will be unified during the upvar
|
||||||
// inference phase (`upvar.rs`).
|
// inference phase (`upvar.rs`).
|
||||||
let base_generics = self.tcx.item_generics(base_def_id);
|
let num_upvars = self.tcx.with_freevars(expr.id, |fv| fv.len());
|
||||||
// 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 upvar_tys = self.next_ty_vars(num_upvars);
|
let upvar_tys = self.next_ty_vars(num_upvars);
|
||||||
|
|
||||||
debug!("check_closure: expr.id={:?} upvar_tys={:?}",
|
debug!("check_closure: expr.id={:?} upvar_tys={:?}",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue