Skip to content

Commit

Permalink
rustc: move closure upvar types to the closure substs
Browse files Browse the repository at this point in the history
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.