Skip to content

Commit b6828fd

Browse files
committed
rustc_typeck: register item types for closures
This makes them closer to actual items and allows for more transparent treatment.
1 parent ca9b566 commit b6828fd

File tree

2 files changed

+49
-30
lines changed

2 files changed

+49
-30
lines changed

src/librustc_metadata/encoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
10561056
stability: None,
10571057
deprecation: None,
10581058

1059-
ty: None,
1059+
ty: Some(self.encode_item_type(def_id)),
10601060
inherent_impls: LazySeq::empty(),
10611061
variances: LazySeq::empty(),
10621062
generics: Some(self.encode_generics(def_id)),

src/librustc_typeck/check/closure.rs

+48-29
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
use super::{check_fn, Expectation, FnCtxt};
1414

1515
use astconv::AstConv;
16+
use rustc::hir::def_id::DefId;
1617
use rustc::ty::{self, ToPolyTraitRef, Ty};
18+
use rustc::ty::subst::Substs;
1719
use rustc::util::common::MemoizationMap;
1820
use std::cmp;
1921
use syntax::abi::Abi;
@@ -43,20 +45,62 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4345
self.check_closure(expr, expected_kind, decl, body, expected_sig)
4446
}
4547

48+
fn declare_closure(&self, def_id: DefId) {
49+
let tcx = self.tcx.global_tcx();
50+
51+
tcx.generics.memoize(def_id, || {
52+
let node_id = tcx.map.as_local_node_id(def_id).unwrap();
53+
let base_def_id = self.tcx.closure_base_def_id(def_id);
54+
let base_generics = tcx.item_generics(base_def_id);
55+
56+
// provide junk type parameter defs - the only place that
57+
// cares about anything but the length is instantiation,
58+
// and we don't do that for closures.
59+
let upvar_decls : Vec<_> = tcx.with_freevars(node_id, |fv| {
60+
fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef {
61+
index: (base_generics.count() as u32) + (i as u32),
62+
name: token::intern("<upvar>"),
63+
def_id: def_id,
64+
default_def_id: base_def_id,
65+
default: None,
66+
object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
67+
pure_wrt_drop: false,
68+
}).collect()
69+
});
70+
71+
tcx.alloc_generics(ty::Generics {
72+
parent: Some(base_def_id),
73+
parent_regions: base_generics.parent_regions +
74+
(base_generics.regions.len() as u32),
75+
parent_types: base_generics.parent_types +
76+
(base_generics.types.len() as u32),
77+
regions: vec![],
78+
types: upvar_decls,
79+
has_self: false,
80+
})
81+
});
82+
83+
tcx.item_types.memoize(def_id, || tcx.mk_closure(def_id, Substs::for_item(
84+
tcx, def_id,
85+
|def, _| tcx.mk_region(def.to_early_bound_region()),
86+
|def, _| tcx.mk_param_from_def(def)
87+
)));
88+
}
89+
4690
fn check_closure(&self,
4791
expr: &hir::Expr,
4892
opt_kind: Option<ty::ClosureKind>,
4993
decl: &'gcx hir::FnDecl,
5094
body: &'gcx hir::Expr,
5195
expected_sig: Option<ty::FnSig<'tcx>>)
5296
-> Ty<'tcx> {
53-
let expr_def_id = self.tcx.map.local_def_id(expr.id);
54-
let base_def_id = self.tcx.closure_base_def_id(expr_def_id);
55-
5697
debug!("check_closure opt_kind={:?} expected_sig={:?}",
5798
opt_kind,
5899
expected_sig);
59100

101+
let expr_def_id = self.tcx.map.local_def_id(expr.id);
102+
self.declare_closure(expr_def_id);
103+
60104
let mut fn_ty = AstConv::ty_of_closure(self,
61105
hir::Unsafety::Normal,
62106
decl,
@@ -66,32 +110,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
66110
// Create type variables (for now) to represent the transformed
67111
// types of upvars. These will be unified during the upvar
68112
// inference phase (`upvar.rs`).
69-
let base_generics = self.tcx.item_generics(base_def_id);
70-
// provide junk type parameter defs - the only place that
71-
// cares about anything but the length is instantiation,
72-
// and we don't do that for closures.
73-
let upvar_decls : Vec<_> = self.tcx.with_freevars(expr.id, |fv| {
74-
fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef {
75-
index: (base_generics.count() as u32) + (i as u32),
76-
name: token::intern("<upvar>"),
77-
def_id: expr_def_id,
78-
default_def_id: base_def_id,
79-
default: None,
80-
object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
81-
pure_wrt_drop: false,
82-
}).collect()
83-
});
84-
let num_upvars = upvar_decls.len();
85-
86-
self.tcx.generics.memoize(expr_def_id, || self.tcx.alloc_generics(ty::Generics {
87-
parent: Some(base_def_id),
88-
parent_regions: base_generics.parent_regions + (base_generics.regions.len() as u32),
89-
parent_types: base_generics.parent_types + (base_generics.types.len() as u32),
90-
regions: vec![],
91-
types: upvar_decls,
92-
has_self: false,
93-
}));
94-
113+
let num_upvars = self.tcx.with_freevars(expr.id, |fv| fv.len());
95114
let upvar_tys = self.next_ty_vars(num_upvars);
96115

97116
debug!("check_closure: expr.id={:?} upvar_tys={:?}",

0 commit comments

Comments
 (0)