Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
arielb1 committed Nov 12, 2016
1 parent f3af8c8 commit ca9b566
Show file tree
Hide file tree
Showing 32 changed files with 179 additions and 92 deletions.
2 changes: 1 addition & 1 deletion src/librustc/infer/mod.rs
Expand Up @@ -1657,7 +1657,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
{
if let InferTables::Local(tables) = self.tables {
if let Some(ty) = tables.borrow().closure_tys.get(&def_id) {
return ty.subst(self.tcx, substs.func_substs);
return ty.subst(self.tcx, substs.substs);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Expand Up @@ -40,6 +40,7 @@
#![feature(rustc_private)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![cfg_attr(stage0, feature(question_mark))]
#![cfg_attr(test, feature(test))]

Expand Down
6 changes: 3 additions & 3 deletions src/librustc/traits/select.rs
Expand Up @@ -1912,16 +1912,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
tys.to_vec()
}

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

// for `PhantomData<T>`, we pass `T`
Expand Down
13 changes: 8 additions & 5 deletions src/librustc/ty/contents.rs
Expand Up @@ -98,10 +98,11 @@ impl TypeContents {
TC::OwnsOwned | (*self & TC::OwnsAll)
}

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

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

ty::TyClosure(_, ref substs) => {
TypeContents::union(&substs.upvar_tys, |ty| tc_ty(tcx, &ty, cache))
ty::TyClosure(def_id, ref substs) => {
TypeContents::union(
substs.upvar_tys(def_id, tcx),
|ty| tc_ty(tcx, &ty, cache))
}

ty::TyTuple(ref tys) => {
Expand Down
7 changes: 2 additions & 5 deletions src/librustc/ty/context.rs
Expand Up @@ -1446,12 +1446,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

pub fn mk_closure(self,
closure_id: DefId,
substs: &'tcx Substs<'tcx>,
tys: &[Ty<'tcx>])
substs: &'tcx Substs<'tcx>)
-> Ty<'tcx> {
self.mk_closure_from_closure_substs(closure_id, ClosureSubsts {
func_substs: substs,
upvar_tys: self.intern_type_list(tys)
substs: substs
})
}

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

3 changes: 1 addition & 2 deletions src/librustc/ty/flags.rs
Expand Up @@ -88,8 +88,7 @@ impl FlagComputation {
&ty::TyClosure(_, ref substs) => {
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
self.add_substs(&substs.func_substs);
self.add_tys(&substs.upvar_tys);
self.add_substs(&substs.substs);
}

&ty::TyInfer(infer) => {
Expand Down
12 changes: 10 additions & 2 deletions src/librustc/ty/layout.rs
Expand Up @@ -631,7 +631,9 @@ impl<'a, 'gcx, 'tcx> Struct {

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

// Tuples and closures.
ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) |
ty::TyClosure(def_id, ref substs) => {
let mut st = Struct::new(dl, false);
let tys = substs.upvar_tys(def_id, tcx);
st.extend(dl, tys.map(|ty| ty.layout(infcx)), ty)?;
Univariant { variant: st, non_zero: false }
}

ty::TyTuple(tys) => {
let mut st = Struct::new(dl, false);
st.extend(dl, tys.iter().map(|ty| ty.layout(infcx)), ty)?;
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/mod.rs
Expand Up @@ -2544,12 +2544,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// tables by typeck; else, it will be retreived from
// the external crate metadata.
if let Some(ty) = self.tables.borrow().closure_tys.get(&def_id) {
return ty.subst(self, substs.func_substs);
return ty.subst(self, substs.substs);
}

let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id);
self.tables.borrow_mut().closure_tys.insert(def_id, ty.clone());
ty.subst(self, substs.func_substs)
ty.subst(self, substs.substs)
}

/// Given the def_id of an impl, return the def_id of the trait it implements.
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/outlives.rs
Expand Up @@ -72,7 +72,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// in the `subtys` iterator (e.g., when encountering a
// projection).
match ty.sty {
ty::TyClosure(_, ref substs) => {
ty::TyClosure(def_id, ref substs) => {
// FIXME(#27086). We do not accumulate from substs, since they
// don't represent reachable data. This means that, in
// practice, some of the lifetime parameters might not
Expand Down Expand Up @@ -110,7 +110,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// what func/type parameters are used and unused,
// taking into consideration UFCS and so forth.

for &upvar_ty in substs.upvar_tys {
for upvar_ty in substs.upvar_tys(def_id, *self) {
self.compute_components(upvar_ty, out);
}
}
Expand Down
9 changes: 2 additions & 7 deletions src/librustc/ty/relate.rs
Expand Up @@ -534,13 +534,8 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
-> RelateResult<'tcx, ty::ClosureSubsts<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
let substs = relate_substs(relation, None, a.func_substs, b.func_substs)?;
assert_eq!(a.upvar_tys.len(), b.upvar_tys.len());
Ok(ty::ClosureSubsts {
func_substs: substs,
upvar_tys: relation.tcx().mk_type_list(
a.upvar_tys.iter().zip(b.upvar_tys).map(|(a, b)| relation.relate(a, b)))?
})
let substs = relate_substs(relation, None, a.substs, b.substs)?;
Ok(ty::ClosureSubsts { substs: substs })
}
}

Expand Down
12 changes: 4 additions & 8 deletions src/librustc/ty/structural_impls.rs
Expand Up @@ -198,11 +198,8 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> {
impl<'a, 'tcx> Lift<'tcx> for ty::ClosureSubsts<'a> {
type Lifted = ty::ClosureSubsts<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
tcx.lift(&(self.func_substs, self.upvar_tys)).map(|(substs, upvar_tys)| {
ty::ClosureSubsts {
func_substs: substs,
upvar_tys: upvar_tys
}
tcx.lift(&self.substs).map(|substs| {
ty::ClosureSubsts { substs: substs }
})
}
}
Expand Down Expand Up @@ -654,13 +651,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Region {
impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ClosureSubsts {
func_substs: self.func_substs.fold_with(folder),
upvar_tys: self.upvar_tys.fold_with(folder),
substs: self.substs.fold_with(folder),
}
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.func_substs.visit_with(visitor) || self.upvar_tys.visit_with(visitor)
self.substs.visit_with(visitor)
}
}

Expand Down
23 changes: 16 additions & 7 deletions src/librustc/ty/sty.rs
Expand Up @@ -11,6 +11,7 @@
//! This module contains TypeVariants and its major components

use hir::def_id::DefId;

use middle::region;
use ty::subst::Substs;
use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TypeFoldable};
Expand Down Expand Up @@ -254,15 +255,23 @@ pub enum TypeVariants<'tcx> {
/// handle). Plus it fixes an ICE. :P
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct ClosureSubsts<'tcx> {
/// Lifetime and type parameters from the enclosing function.
/// Lifetime and type parameters from the enclosing function,
/// concatenated with the types of the upvars.
///
/// These are separated out because trans wants to pass them around
/// when monomorphizing.
pub func_substs: &'tcx Substs<'tcx>,
pub substs: &'tcx Substs<'tcx>,
}

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

#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
Expand Down Expand Up @@ -1234,7 +1243,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
substs.regions().collect()
}
TyClosure(_, ref substs) => {
substs.func_substs.regions().collect()
substs.substs.regions().collect()
}
TyProjection(ref data) => {
data.trait_ref.substs.regions().collect()
Expand Down
14 changes: 14 additions & 0 deletions src/librustc/ty/subst.rs
Expand Up @@ -274,6 +274,20 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
let defs = tcx.item_generics(source_ancestor);
tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned())
}

pub fn extend_with_types(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
types: &[Ty<'tcx>])
-> &'tcx Substs<'tcx> {
tcx.mk_substs(
self[..].iter().cloned().chain(
types.iter().map(|a| Kind::from(*a)))
)
}

pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics<'tcx>)
-> &'tcx Substs<'tcx> {
tcx.mk_substs(self.iter().take(generics.count()).cloned())
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> {
Expand Down
11 changes: 11 additions & 0 deletions src/librustc/ty/util.rs
Expand Up @@ -11,6 +11,7 @@
//! misc. type-system utilities too small to deserve their own file

use hir::def_id::DefId;
use hir::map::DefPathData;
use infer::InferCtxt;
use hir::map as ast_map;
use hir::pat_util;
Expand Down Expand Up @@ -390,6 +391,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// (e.g. calling `foo.0.clone()` of `Foo<T:Clone>`).
return !self.has_attr(dtor_method, "unsafe_destructor_blind_to_params");
}

pub fn closure_base_def_id(&self, def_id: DefId) -> DefId {
let mut def_id = def_id;
while self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr {
def_id = self.parent_def_id(def_id).unwrap_or_else(|| {
bug!("closure {:?} has no parent", def_id);
});
}
def_id
}
}

/// When hashing a type this ends up affecting properties like symbol names. We
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/ty/walk.rs
Expand Up @@ -97,8 +97,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
stack.extend(substs.types().rev());
}
ty::TyClosure(_, ref substs) => {
stack.extend(substs.func_substs.types().rev());
stack.extend(substs.upvar_tys.iter().cloned().rev());
stack.extend(substs.substs.types().rev());
}
ty::TyTuple(ts) => {
stack.extend(ts.iter().cloned().rev());
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/util/ppaux.rs
Expand Up @@ -907,13 +907,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
}
TyStr => write!(f, "str"),
TyClosure(did, substs) => ty::tls::with(|tcx| {
let upvar_tys = substs.upvar_tys(did, tcx);
write!(f, "[closure")?;

if let Some(node_id) = tcx.map.as_local_node_id(did) {
write!(f, "@{:?}", tcx.map.span(node_id))?;
let mut sep = " ";
tcx.with_freevars(node_id, |freevars| {
for (freevar, upvar_ty) in freevars.iter().zip(substs.upvar_tys) {
for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
let def_id = freevar.def.def_id();
let node_id = tcx.map.as_local_node_id(def_id).unwrap();
write!(f,
Expand All @@ -930,7 +931,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
// visible in trans bug reports, I imagine.
write!(f, "@{:?}", did)?;
let mut sep = " ";
for (index, upvar_ty) in substs.upvar_tys.iter().enumerate() {
for (index, upvar_ty) in upvar_tys.enumerate() {
write!(f, "{}{}:{}", sep, index, upvar_ty)?;
sep = ", ";
}
Expand Down
8 changes: 5 additions & 3 deletions src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
Expand Up @@ -709,9 +709,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
ty::TyAdt(def, substs) => {
self.open_drop_for_adt(c, def, substs)
}
ty::TyTuple(tys) | ty::TyClosure(_, ty::ClosureSubsts {
upvar_tys: tys, ..
}) => {
ty::TyClosure(def_id, substs) => {
let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx).collect();
self.open_drop_for_tuple(c, &tys)
}
ty::TyTuple(tys) => {
self.open_drop_for_tuple(c, tys)
}
ty::TyBox(ty) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_metadata/encoder.rs
Expand Up @@ -1059,7 +1059,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
ty: None,
inherent_impls: LazySeq::empty(),
variances: LazySeq::empty(),
generics: None,
generics: Some(self.encode_generics(def_id)),
predicates: None,

ast: None,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/hair/cx/expr.rs
Expand Up @@ -521,8 +521,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
};
let upvars = cx.tcx.with_freevars(expr.id, |freevars| {
freevars.iter()
.enumerate()
.map(|(i, fv)| capture_freevar(cx, expr, fv, substs.upvar_tys[i]))
.zip(substs.upvar_tys(def_id, cx.tcx))
.map(|(fv, ty)| capture_freevar(cx, expr, fv, ty))
.collect()
});
ExprKind::Closure {
Expand Down
12 changes: 9 additions & 3 deletions src/librustc_mir/transform/type_check.rs
Expand Up @@ -274,9 +274,15 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
ty::TyAdt(adt_def, substs) if adt_def.is_univariant() => {
(&adt_def.variants[0], substs)
}
ty::TyTuple(tys) | ty::TyClosure(_, ty::ClosureSubsts {
upvar_tys: tys, ..
}) => {
ty::TyClosure(def_id, substs) => {
return match substs.upvar_tys(def_id, tcx).nth(field.index()) {
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
field_count: substs.upvar_tys(def_id, tcx).count()
})
}
}
ty::TyTuple(tys) => {
return match tys.get(field.index()) {
Some(&ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_trans/adt.rs
Expand Up @@ -108,9 +108,9 @@ fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>,
}).collect::<Vec<_>>()
},
ty::TyTuple(fields) => fields.to_vec(),
ty::TyClosure(_, substs) => {
ty::TyClosure(def_id, substs) => {
if variant_index > 0 { bug!("{} is a closure, which only has one variant", t);}
substs.upvar_tys.to_vec()
substs.upvar_tys(def_id, cx.tcx()).collect()
},
_ => bug!("{} is not a type that can have fields.", t)
}
Expand Down

0 comments on commit ca9b566

Please sign in to comment.