Skip to content

Commit ca9b566

Browse files
committed
rustc: move closure upvar types to the closure substs
This moves closures to the (DefId, Substs) scheme like all other items, and saves a word from the size of TyS now that Substs is 2 words.
1 parent f3af8c8 commit ca9b566

File tree

32 files changed

+179
-92
lines changed

32 files changed

+179
-92
lines changed

src/librustc/infer/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1657,7 +1657,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
16571657
{
16581658
if let InferTables::Local(tables) = self.tables {
16591659
if let Some(ty) = tables.borrow().closure_tys.get(&def_id) {
1660-
return ty.subst(self.tcx, substs.func_substs);
1660+
return ty.subst(self.tcx, substs.substs);
16611661
}
16621662
}
16631663

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#![feature(rustc_private)]
4141
#![feature(slice_patterns)]
4242
#![feature(staged_api)]
43+
#![feature(unboxed_closures)]
4344
#![cfg_attr(stage0, feature(question_mark))]
4445
#![cfg_attr(test, feature(test))]
4546

src/librustc/traits/select.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1912,16 +1912,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
19121912
tys.to_vec()
19131913
}
19141914

1915-
ty::TyClosure(_, ref substs) => {
1915+
ty::TyClosure(def_id, ref substs) => {
19161916
// FIXME(#27086). We are invariant w/r/t our
1917-
// substs.func_substs, but we don't see them as
1917+
// func_substs, but we don't see them as
19181918
// constituent types; this seems RIGHT but also like
19191919
// something that a normal type couldn't simulate. Is
19201920
// this just a gap with the way that PhantomData and
19211921
// OIBIT interact? That is, there is no way to say
19221922
// "make me invariant with respect to this TYPE, but
19231923
// do not act as though I can reach it"
1924-
substs.upvar_tys.to_vec()
1924+
substs.upvar_tys(def_id, self.tcx()).collect()
19251925
}
19261926

19271927
// for `PhantomData<T>`, we pass `T`

src/librustc/ty/contents.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,11 @@ impl TypeContents {
9898
TC::OwnsOwned | (*self & TC::OwnsAll)
9999
}
100100

101-
pub fn union<T, F>(v: &[T], mut f: F) -> TypeContents where
102-
F: FnMut(&T) -> TypeContents,
101+
pub fn union<I, T, F>(v: I, mut f: F) -> TypeContents where
102+
I: IntoIterator<Item=T>,
103+
F: FnMut(T) -> TypeContents,
103104
{
104-
v.iter().fold(TC::None, |tc, ty| tc | f(ty))
105+
v.into_iter().fold(TC::None, |tc, ty| tc | f(ty))
105106
}
106107

107108
pub fn has_dtor(&self) -> bool {
@@ -215,8 +216,10 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
215216
}
216217
ty::TyStr => TC::None,
217218

218-
ty::TyClosure(_, ref substs) => {
219-
TypeContents::union(&substs.upvar_tys, |ty| tc_ty(tcx, &ty, cache))
219+
ty::TyClosure(def_id, ref substs) => {
220+
TypeContents::union(
221+
substs.upvar_tys(def_id, tcx),
222+
|ty| tc_ty(tcx, &ty, cache))
220223
}
221224

222225
ty::TyTuple(ref tys) => {

src/librustc/ty/context.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1446,12 +1446,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
14461446

14471447
pub fn mk_closure(self,
14481448
closure_id: DefId,
1449-
substs: &'tcx Substs<'tcx>,
1450-
tys: &[Ty<'tcx>])
1449+
substs: &'tcx Substs<'tcx>)
14511450
-> Ty<'tcx> {
14521451
self.mk_closure_from_closure_substs(closure_id, ClosureSubsts {
1453-
func_substs: substs,
1454-
upvar_tys: self.intern_type_list(tys)
1452+
substs: substs
14551453
})
14561454
}
14571455

@@ -1574,4 +1572,3 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
15741572
Ok(f(&iter.collect::<Result<AccumulateVec<[_; 8]>, _>>()?))
15751573
}
15761574
}
1577-

src/librustc/ty/flags.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ impl FlagComputation {
8888
&ty::TyClosure(_, ref substs) => {
8989
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
9090
self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
91-
self.add_substs(&substs.func_substs);
92-
self.add_tys(&substs.upvar_tys);
91+
self.add_substs(&substs.substs);
9392
}
9493

9594
&ty::TyInfer(infer) => {

src/librustc/ty/layout.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,9 @@ impl<'a, 'gcx, 'tcx> Struct {
631631

632632
// Perhaps one of the upvars of this closure is non-zero
633633
// Let's recurse and find out!
634-
(_, &ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. })) |
634+
(_, &ty::TyClosure(def_id, ref substs)) => {
635+
Struct::non_zero_field_path(infcx, substs.upvar_tys(def_id, tcx))
636+
}
635637
// Can we use one of the fields in this tuple?
636638
(_, &ty::TyTuple(tys)) => {
637639
Struct::non_zero_field_path(infcx, tys.iter().cloned())
@@ -961,7 +963,13 @@ impl<'a, 'gcx, 'tcx> Layout {
961963
}
962964

963965
// Tuples and closures.
964-
ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) |
966+
ty::TyClosure(def_id, ref substs) => {
967+
let mut st = Struct::new(dl, false);
968+
let tys = substs.upvar_tys(def_id, tcx);
969+
st.extend(dl, tys.map(|ty| ty.layout(infcx)), ty)?;
970+
Univariant { variant: st, non_zero: false }
971+
}
972+
965973
ty::TyTuple(tys) => {
966974
let mut st = Struct::new(dl, false);
967975
st.extend(dl, tys.iter().map(|ty| ty.layout(infcx)), ty)?;

src/librustc/ty/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2544,12 +2544,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
25442544
// tables by typeck; else, it will be retreived from
25452545
// the external crate metadata.
25462546
if let Some(ty) = self.tables.borrow().closure_tys.get(&def_id) {
2547-
return ty.subst(self, substs.func_substs);
2547+
return ty.subst(self, substs.substs);
25482548
}
25492549

25502550
let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id);
25512551
self.tables.borrow_mut().closure_tys.insert(def_id, ty.clone());
2552-
ty.subst(self, substs.func_substs)
2552+
ty.subst(self, substs.substs)
25532553
}
25542554

25552555
/// Given the def_id of an impl, return the def_id of the trait it implements.

src/librustc/ty/outlives.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
7272
// in the `subtys` iterator (e.g., when encountering a
7373
// projection).
7474
match ty.sty {
75-
ty::TyClosure(_, ref substs) => {
75+
ty::TyClosure(def_id, ref substs) => {
7676
// FIXME(#27086). We do not accumulate from substs, since they
7777
// don't represent reachable data. This means that, in
7878
// practice, some of the lifetime parameters might not
@@ -110,7 +110,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
110110
// what func/type parameters are used and unused,
111111
// taking into consideration UFCS and so forth.
112112

113-
for &upvar_ty in substs.upvar_tys {
113+
for upvar_ty in substs.upvar_tys(def_id, *self) {
114114
self.compute_components(upvar_ty, out);
115115
}
116116
}

src/librustc/ty/relate.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -534,13 +534,8 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
534534
-> RelateResult<'tcx, ty::ClosureSubsts<'tcx>>
535535
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
536536
{
537-
let substs = relate_substs(relation, None, a.func_substs, b.func_substs)?;
538-
assert_eq!(a.upvar_tys.len(), b.upvar_tys.len());
539-
Ok(ty::ClosureSubsts {
540-
func_substs: substs,
541-
upvar_tys: relation.tcx().mk_type_list(
542-
a.upvar_tys.iter().zip(b.upvar_tys).map(|(a, b)| relation.relate(a, b)))?
543-
})
537+
let substs = relate_substs(relation, None, a.substs, b.substs)?;
538+
Ok(ty::ClosureSubsts { substs: substs })
544539
}
545540
}
546541

src/librustc/ty/structural_impls.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,8 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> {
198198
impl<'a, 'tcx> Lift<'tcx> for ty::ClosureSubsts<'a> {
199199
type Lifted = ty::ClosureSubsts<'tcx>;
200200
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
201-
tcx.lift(&(self.func_substs, self.upvar_tys)).map(|(substs, upvar_tys)| {
202-
ty::ClosureSubsts {
203-
func_substs: substs,
204-
upvar_tys: upvar_tys
205-
}
201+
tcx.lift(&self.substs).map(|substs| {
202+
ty::ClosureSubsts { substs: substs }
206203
})
207204
}
208205
}
@@ -654,13 +651,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Region {
654651
impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
655652
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
656653
ty::ClosureSubsts {
657-
func_substs: self.func_substs.fold_with(folder),
658-
upvar_tys: self.upvar_tys.fold_with(folder),
654+
substs: self.substs.fold_with(folder),
659655
}
660656
}
661657

662658
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
663-
self.func_substs.visit_with(visitor) || self.upvar_tys.visit_with(visitor)
659+
self.substs.visit_with(visitor)
664660
}
665661
}
666662

src/librustc/ty/sty.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! This module contains TypeVariants and its major components
1212
1313
use hir::def_id::DefId;
14+
1415
use middle::region;
1516
use ty::subst::Substs;
1617
use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TypeFoldable};
@@ -254,15 +255,23 @@ pub enum TypeVariants<'tcx> {
254255
/// handle). Plus it fixes an ICE. :P
255256
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
256257
pub struct ClosureSubsts<'tcx> {
257-
/// Lifetime and type parameters from the enclosing function.
258+
/// Lifetime and type parameters from the enclosing function,
259+
/// concatenated with the types of the upvars.
260+
///
258261
/// These are separated out because trans wants to pass them around
259262
/// when monomorphizing.
260-
pub func_substs: &'tcx Substs<'tcx>,
263+
pub substs: &'tcx Substs<'tcx>,
264+
}
261265

262-
/// The types of the upvars. The list parallels the freevars and
263-
/// `upvar_borrows` lists. These are kept distinct so that we can
264-
/// easily index into them.
265-
pub upvar_tys: &'tcx Slice<Ty<'tcx>>
266+
impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> {
267+
#[inline]
268+
pub fn upvar_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'acx>) ->
269+
impl Iterator<Item=Ty<'tcx>> + 'tcx
270+
{
271+
let generics = tcx.item_generics(def_id);
272+
self.substs[self.substs.len()-generics.own_count()..].iter().map(
273+
|t| t.as_type().expect("unexpected region in upvars"))
274+
}
266275
}
267276

268277
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
@@ -1234,7 +1243,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
12341243
substs.regions().collect()
12351244
}
12361245
TyClosure(_, ref substs) => {
1237-
substs.func_substs.regions().collect()
1246+
substs.substs.regions().collect()
12381247
}
12391248
TyProjection(ref data) => {
12401249
data.trait_ref.substs.regions().collect()

src/librustc/ty/subst.rs

+14
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,20 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
274274
let defs = tcx.item_generics(source_ancestor);
275275
tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned())
276276
}
277+
278+
pub fn extend_with_types(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
279+
types: &[Ty<'tcx>])
280+
-> &'tcx Substs<'tcx> {
281+
tcx.mk_substs(
282+
self[..].iter().cloned().chain(
283+
types.iter().map(|a| Kind::from(*a)))
284+
)
285+
}
286+
287+
pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics<'tcx>)
288+
-> &'tcx Substs<'tcx> {
289+
tcx.mk_substs(self.iter().take(generics.count()).cloned())
290+
}
277291
}
278292

279293
impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> {

src/librustc/ty/util.rs

+11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! misc. type-system utilities too small to deserve their own file
1212
1313
use hir::def_id::DefId;
14+
use hir::map::DefPathData;
1415
use infer::InferCtxt;
1516
use hir::map as ast_map;
1617
use hir::pat_util;
@@ -390,6 +391,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
390391
// (e.g. calling `foo.0.clone()` of `Foo<T:Clone>`).
391392
return !self.has_attr(dtor_method, "unsafe_destructor_blind_to_params");
392393
}
394+
395+
pub fn closure_base_def_id(&self, def_id: DefId) -> DefId {
396+
let mut def_id = def_id;
397+
while self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr {
398+
def_id = self.parent_def_id(def_id).unwrap_or_else(|| {
399+
bug!("closure {:?} has no parent", def_id);
400+
});
401+
}
402+
def_id
403+
}
393404
}
394405

395406
/// When hashing a type this ends up affecting properties like symbol names. We

src/librustc/ty/walk.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
9797
stack.extend(substs.types().rev());
9898
}
9999
ty::TyClosure(_, ref substs) => {
100-
stack.extend(substs.func_substs.types().rev());
101-
stack.extend(substs.upvar_tys.iter().cloned().rev());
100+
stack.extend(substs.substs.types().rev());
102101
}
103102
ty::TyTuple(ts) => {
104103
stack.extend(ts.iter().cloned().rev());

src/librustc/util/ppaux.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -907,13 +907,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
907907
}
908908
TyStr => write!(f, "str"),
909909
TyClosure(did, substs) => ty::tls::with(|tcx| {
910+
let upvar_tys = substs.upvar_tys(did, tcx);
910911
write!(f, "[closure")?;
911912

912913
if let Some(node_id) = tcx.map.as_local_node_id(did) {
913914
write!(f, "@{:?}", tcx.map.span(node_id))?;
914915
let mut sep = " ";
915916
tcx.with_freevars(node_id, |freevars| {
916-
for (freevar, upvar_ty) in freevars.iter().zip(substs.upvar_tys) {
917+
for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
917918
let def_id = freevar.def.def_id();
918919
let node_id = tcx.map.as_local_node_id(def_id).unwrap();
919920
write!(f,
@@ -930,7 +931,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
930931
// visible in trans bug reports, I imagine.
931932
write!(f, "@{:?}", did)?;
932933
let mut sep = " ";
933-
for (index, upvar_ty) in substs.upvar_tys.iter().enumerate() {
934+
for (index, upvar_ty) in upvar_tys.enumerate() {
934935
write!(f, "{}{}:{}", sep, index, upvar_ty)?;
935936
sep = ", ";
936937
}

src/librustc_borrowck/borrowck/mir/elaborate_drops.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -709,9 +709,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
709709
ty::TyAdt(def, substs) => {
710710
self.open_drop_for_adt(c, def, substs)
711711
}
712-
ty::TyTuple(tys) | ty::TyClosure(_, ty::ClosureSubsts {
713-
upvar_tys: tys, ..
714-
}) => {
712+
ty::TyClosure(def_id, substs) => {
713+
let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx).collect();
714+
self.open_drop_for_tuple(c, &tys)
715+
}
716+
ty::TyTuple(tys) => {
715717
self.open_drop_for_tuple(c, tys)
716718
}
717719
ty::TyBox(ty) => {

src/librustc_metadata/encoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
10591059
ty: None,
10601060
inherent_impls: LazySeq::empty(),
10611061
variances: LazySeq::empty(),
1062-
generics: None,
1062+
generics: Some(self.encode_generics(def_id)),
10631063
predicates: None,
10641064

10651065
ast: None,

src/librustc_mir/hair/cx/expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
521521
};
522522
let upvars = cx.tcx.with_freevars(expr.id, |freevars| {
523523
freevars.iter()
524-
.enumerate()
525-
.map(|(i, fv)| capture_freevar(cx, expr, fv, substs.upvar_tys[i]))
524+
.zip(substs.upvar_tys(def_id, cx.tcx))
525+
.map(|(fv, ty)| capture_freevar(cx, expr, fv, ty))
526526
.collect()
527527
});
528528
ExprKind::Closure {

src/librustc_mir/transform/type_check.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,15 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
274274
ty::TyAdt(adt_def, substs) if adt_def.is_univariant() => {
275275
(&adt_def.variants[0], substs)
276276
}
277-
ty::TyTuple(tys) | ty::TyClosure(_, ty::ClosureSubsts {
278-
upvar_tys: tys, ..
279-
}) => {
277+
ty::TyClosure(def_id, substs) => {
278+
return match substs.upvar_tys(def_id, tcx).nth(field.index()) {
279+
Some(ty) => Ok(ty),
280+
None => Err(FieldAccessError::OutOfRange {
281+
field_count: substs.upvar_tys(def_id, tcx).count()
282+
})
283+
}
284+
}
285+
ty::TyTuple(tys) => {
280286
return match tys.get(field.index()) {
281287
Some(&ty) => Ok(ty),
282288
None => Err(FieldAccessError::OutOfRange {

src/librustc_trans/adt.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>,
108108
}).collect::<Vec<_>>()
109109
},
110110
ty::TyTuple(fields) => fields.to_vec(),
111-
ty::TyClosure(_, substs) => {
111+
ty::TyClosure(def_id, substs) => {
112112
if variant_index > 0 { bug!("{} is a closure, which only has one variant", t);}
113-
substs.upvar_tys.to_vec()
113+
substs.upvar_tys(def_id, cx.tcx()).collect()
114114
},
115115
_ => bug!("{} is not a type that can have fields.", t)
116116
}

0 commit comments

Comments
 (0)