Skip to content

Commit a277f9d

Browse files
authored
Auto merge of #37675 - arielb1:trans-closure, r=eddyb
Translate closures through the collector Now that old trans is gone, there is no need for the hack of translating closures when they are instantiated. We can translate them like regular items. r? @eddyb
2 parents fd983d0 + d394e75 commit a277f9d

39 files changed

+455
-505
lines changed

src/librustc/infer/mod.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1150,10 +1150,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11501150
self.tcx.mk_var(self.next_ty_var_id(true))
11511151
}
11521152

1153-
pub fn next_ty_vars(&self, n: usize) -> Vec<Ty<'tcx>> {
1154-
(0..n).map(|_i| self.next_ty_var()).collect()
1155-
}
1156-
11571153
pub fn next_int_var_id(&self) -> IntVid {
11581154
self.int_unification_table
11591155
.borrow_mut()
@@ -1657,7 +1653,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
16571653
{
16581654
if let InferTables::Local(tables) = self.tables {
16591655
if let Some(ty) = tables.borrow().closure_tys.get(&def_id) {
1660-
return ty.subst(self.tcx, substs.func_substs);
1656+
return ty.subst(self.tcx, substs.substs);
16611657
}
16621658
}
16631659

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

+29
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,22 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
183183
tcx.intern_substs(&substs)
184184
}
185185

186+
pub fn extend_to<FR, FT>(&self,
187+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
188+
def_id: DefId,
189+
mut mk_region: FR,
190+
mut mk_type: FT)
191+
-> &'tcx Substs<'tcx>
192+
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
193+
FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx>
194+
{
195+
let defs = tcx.item_generics(def_id);
196+
let mut result = Vec::with_capacity(defs.count());
197+
result.extend(self[..].iter().cloned());
198+
Substs::fill_single(&mut result, defs, &mut mk_region, &mut mk_type);
199+
tcx.intern_substs(&result)
200+
}
201+
186202
fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
187203
tcx: TyCtxt<'a, 'gcx, 'tcx>,
188204
defs: &ty::Generics<'tcx>,
@@ -195,7 +211,15 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
195211
let parent_defs = tcx.item_generics(def_id);
196212
Substs::fill_item(substs, tcx, parent_defs, mk_region, mk_type);
197213
}
214+
Substs::fill_single(substs, defs, mk_region, mk_type)
215+
}
198216

217+
fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
218+
defs: &ty::Generics<'tcx>,
219+
mk_region: &mut FR,
220+
mk_type: &mut FT)
221+
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
222+
FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> {
199223
// Handle Self first, before all regions.
200224
let mut types = defs.types.iter();
201225
if defs.parent.is_none() && defs.has_self {
@@ -274,6 +298,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
274298
let defs = tcx.item_generics(source_ancestor);
275299
tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned())
276300
}
301+
302+
pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics<'tcx>)
303+
-> &'tcx Substs<'tcx> {
304+
tcx.mk_substs(self.iter().take(generics.count()).cloned())
305+
}
277306
}
278307

279308
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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1056,10 +1056,10 @@ 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(),
1062-
generics: None,
1062+
generics: Some(self.encode_generics(def_id)),
10631063
predicates: None,
10641064

10651065
ast: None,

0 commit comments

Comments
 (0)