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.
This commit is contained in:
parent
f3af8c8505
commit
ca9b5664c3
32 changed files with 179 additions and 92 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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))]
|
||||
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1574,4 +1572,3 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
|
|||
Ok(f(&iter.collect::<Result<AccumulateVec<[_; 8]>, _>>()?))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
@ -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)]
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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 = ", ";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
// duplicate declarations
|
||||
let tcx = ccx.tcx();
|
||||
let substs = tcx.erase_regions(&substs);
|
||||
let instance = Instance::new(closure_id, substs.func_substs);
|
||||
let instance = Instance::new(closure_id, substs.substs);
|
||||
|
||||
if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
|
||||
debug!("get_or_create_closure_declaration(): found closure {:?}: {:?}",
|
||||
|
|
@ -99,8 +99,7 @@ pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
let tcx = ccx.tcx();
|
||||
let _icx = push_ctxt("closure::trans_closure_expr");
|
||||
|
||||
let param_substs = closure_substs.func_substs;
|
||||
let instance = Instance::new(closure_def_id, param_substs);
|
||||
let instance = Instance::new(closure_def_id, closure_substs.substs);
|
||||
|
||||
// If we have not done so yet, translate this closure's body
|
||||
if !ccx.instances().borrow().contains_key(&instance) {
|
||||
|
|
@ -138,7 +137,7 @@ pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
|
||||
trans_closure(ccx,
|
||||
llfn,
|
||||
Instance::new(closure_def_id, param_substs),
|
||||
instance,
|
||||
&sig,
|
||||
Abi::RustCall);
|
||||
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
|||
|
||||
let concrete_substs = monomorphize::apply_param_substs(self.scx,
|
||||
self.param_substs,
|
||||
&substs.func_substs);
|
||||
&substs.substs);
|
||||
let concrete_substs = self.scx.tcx().erase_regions(&concrete_substs);
|
||||
|
||||
let visitor = MirNeighborCollector {
|
||||
|
|
@ -797,8 +797,8 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
|||
}
|
||||
}
|
||||
}
|
||||
ty::TyClosure(_, substs) => {
|
||||
for upvar_ty in substs.upvar_tys {
|
||||
ty::TyClosure(def_id, substs) => {
|
||||
for upvar_ty in substs.upvar_tys(def_id, scx.tcx()) {
|
||||
let upvar_ty = glue::get_drop_glue_type(scx.tcx(), upvar_ty);
|
||||
if glue::type_needs_drop(scx.tcx(), upvar_ty) {
|
||||
output.push(TransItem::DropGlue(DropGlueKind::Ty(upvar_ty)));
|
||||
|
|
|
|||
|
|
@ -109,7 +109,16 @@ pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
|
|||
Some([monomorphize::field_ty(ccx.tcx(), substs, &fields[0]),
|
||||
monomorphize::field_ty(ccx.tcx(), substs, &fields[1])])
|
||||
}
|
||||
ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) |
|
||||
ty::TyClosure(def_id, substs) => {
|
||||
let mut tys = substs.upvar_tys(def_id, ccx.tcx());
|
||||
tys.next().and_then(|first_ty| tys.next().and_then(|second_ty| {
|
||||
if tys.next().is_some() {
|
||||
None
|
||||
} else {
|
||||
Some([first_ty, second_ty])
|
||||
}
|
||||
}))
|
||||
}
|
||||
ty::TyTuple(tys) => {
|
||||
if tys.len() != 2 {
|
||||
return None;
|
||||
|
|
|
|||
|
|
@ -574,10 +574,11 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
|
||||
|
||||
}
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
ty::TyClosure(def_id, substs) => {
|
||||
let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx()).collect();
|
||||
prepare_tuple_metadata(cx,
|
||||
t,
|
||||
&substs.upvar_tys,
|
||||
&upvar_tys,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ use llvm::{ModuleRef, ContextRef, ValueRef};
|
|||
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray,
|
||||
FlagPrototyped};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::map::DefPathData;
|
||||
use rustc::ty::subst::Substs;
|
||||
|
||||
use abi::Abi;
|
||||
|
|
@ -248,21 +247,19 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
};
|
||||
|
||||
// Find the enclosing function, in case this is a closure.
|
||||
let mut fn_def_id = instance.def;
|
||||
let mut def_key = cx.tcx().def_key(fn_def_id);
|
||||
let def_key = cx.tcx().def_key(instance.def);
|
||||
let mut name = def_key.disambiguated_data.data.to_string();
|
||||
let name_len = name.len();
|
||||
while def_key.disambiguated_data.data == DefPathData::ClosureExpr {
|
||||
fn_def_id.index = def_key.parent.expect("closure without a parent?");
|
||||
def_key = cx.tcx().def_key(fn_def_id);
|
||||
}
|
||||
|
||||
let fn_def_id = cx.tcx().closure_base_def_id(instance.def);
|
||||
|
||||
// Get_template_parameters() will append a `<...>` clause to the function
|
||||
// name if necessary.
|
||||
let generics = cx.tcx().item_generics(fn_def_id);
|
||||
let substs = instance.substs.truncate_to(cx.tcx(), generics);
|
||||
let template_parameters = get_template_parameters(cx,
|
||||
&generics,
|
||||
instance.substs,
|
||||
substs,
|
||||
file_metadata,
|
||||
&mut name);
|
||||
|
||||
|
|
|
|||
|
|
@ -531,8 +531,8 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
|||
|
||||
let mut cx = cx;
|
||||
match t.sty {
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
for (i, upvar_ty) in substs.upvar_tys.iter().enumerate() {
|
||||
ty::TyClosure(def_id, substs) => {
|
||||
for (i, upvar_ty) in substs.upvar_tys(def_id, cx.tcx()).enumerate() {
|
||||
let llupvar = adt::trans_field_ptr(cx, t, value, Disr(0), i);
|
||||
cx = drop_ty(cx, llupvar, upvar_ty, DebugLoc::None);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,8 +470,8 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
|
|||
} else {
|
||||
(arg_ty, false)
|
||||
};
|
||||
let upvar_tys = if let ty::TyClosure(_, ref substs) = closure_ty.sty {
|
||||
&substs.upvar_tys[..]
|
||||
let upvar_tys = if let ty::TyClosure(def_id, substs) = closure_ty.sty {
|
||||
substs.upvar_tys(def_id, tcx)
|
||||
} else {
|
||||
bug!("upvar_decls with non-closure arg0 type `{}`", closure_ty);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -477,12 +477,14 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
push_unique_type_name(tcx, sig.output, output);
|
||||
}
|
||||
},
|
||||
ty::TyClosure(def_id, ref closure_substs) => {
|
||||
ty::TyClosure(def_id, closure_substs) => {
|
||||
push_item_name(tcx, def_id, output);
|
||||
output.push_str("{");
|
||||
output.push_str(&format!("{}:{}", def_id.krate, def_id.index.as_usize()));
|
||||
output.push_str("}");
|
||||
push_type_params(tcx, closure_substs.func_substs, &[], output);
|
||||
let generics = tcx.item_generics(tcx.closure_base_def_id(def_id));
|
||||
let substs = closure_substs.substs.truncate_to(tcx, generics);
|
||||
push_type_params(tcx, substs, &[], output);
|
||||
}
|
||||
ty::TyError |
|
||||
ty::TyInfer(_) |
|
||||
|
|
|
|||
|
|
@ -14,10 +14,13 @@ use super::{check_fn, Expectation, FnCtxt};
|
|||
|
||||
use astconv::AstConv;
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty};
|
||||
use rustc::util::common::MemoizationMap;
|
||||
use std::cmp;
|
||||
use syntax::abi::Abi;
|
||||
use rustc::hir;
|
||||
|
||||
use syntax::parse::token;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn check_expr_closure(&self,
|
||||
expr: &hir::Expr,
|
||||
|
|
@ -48,6 +51,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
expected_sig: Option<ty::FnSig<'tcx>>)
|
||||
-> Ty<'tcx> {
|
||||
let expr_def_id = self.tcx.map.local_def_id(expr.id);
|
||||
let base_def_id = self.tcx.closure_base_def_id(expr_def_id);
|
||||
|
||||
debug!("check_closure opt_kind={:?} expected_sig={:?}",
|
||||
opt_kind,
|
||||
|
|
@ -62,16 +66,42 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Create type variables (for now) to represent the transformed
|
||||
// types of upvars. These will be unified during the upvar
|
||||
// inference phase (`upvar.rs`).
|
||||
let num_upvars = self.tcx.with_freevars(expr.id, |fv| fv.len());
|
||||
let base_generics = self.tcx.item_generics(base_def_id);
|
||||
// provide junk type parameter defs - the only place that
|
||||
// cares about anything but the length is instantiation,
|
||||
// and we don't do that for closures.
|
||||
let upvar_decls : Vec<_> = self.tcx.with_freevars(expr.id, |fv| {
|
||||
fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef {
|
||||
index: (base_generics.count() as u32) + (i as u32),
|
||||
name: token::intern("<upvar>"),
|
||||
def_id: expr_def_id,
|
||||
default_def_id: base_def_id,
|
||||
default: None,
|
||||
object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
|
||||
pure_wrt_drop: false,
|
||||
}).collect()
|
||||
});
|
||||
let num_upvars = upvar_decls.len();
|
||||
|
||||
self.tcx.generics.memoize(expr_def_id, || self.tcx.alloc_generics(ty::Generics {
|
||||
parent: Some(base_def_id),
|
||||
parent_regions: base_generics.parent_regions + (base_generics.regions.len() as u32),
|
||||
parent_types: base_generics.parent_types + (base_generics.types.len() as u32),
|
||||
regions: vec![],
|
||||
types: upvar_decls,
|
||||
has_self: false,
|
||||
}));
|
||||
|
||||
let upvar_tys = self.next_ty_vars(num_upvars);
|
||||
|
||||
debug!("check_closure: expr.id={:?} upvar_tys={:?}",
|
||||
expr.id,
|
||||
upvar_tys);
|
||||
|
||||
let closure_type = self.tcx.mk_closure(expr_def_id,
|
||||
self.parameter_environment.free_substs,
|
||||
&upvar_tys);
|
||||
let closure_type = self.tcx.mk_closure(
|
||||
expr_def_id,
|
||||
self.parameter_environment.free_substs.extend_with_types(self.tcx, &upvar_tys)
|
||||
);
|
||||
|
||||
let fn_sig = self.tcx
|
||||
.liberate_late_bound_regions(self.tcx.region_maps.call_site_extent(expr.id, body.id),
|
||||
|
|
|
|||
|
|
@ -482,8 +482,14 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
ty::TyTuple(tys) |
|
||||
ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) => {
|
||||
ty::TyClosure(def_id, substs) => {
|
||||
for ty in substs.upvar_tys(def_id, tcx) {
|
||||
iterate_over_potentially_unsafe_regions_in_type(cx, context, ty, depth+1)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
ty::TyTuple(tys) => {
|
||||
for ty in tys {
|
||||
iterate_over_potentially_unsafe_regions_in_type(cx, context, ty, depth+1)?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,8 +183,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||
// inference algorithm will reject it).
|
||||
|
||||
// Extract the type variables UV0...UVn.
|
||||
let closure_substs = match self.fcx.node_ty(id).sty {
|
||||
ty::TyClosure(_, ref substs) => substs,
|
||||
let (def_id, closure_substs) = match self.fcx.node_ty(id).sty {
|
||||
ty::TyClosure(def_id, substs) => (def_id, substs),
|
||||
ref t => {
|
||||
span_bug!(
|
||||
span,
|
||||
|
|
@ -197,7 +197,9 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||
let final_upvar_tys = self.final_upvar_tys(id);
|
||||
debug!("analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}",
|
||||
id, closure_substs, final_upvar_tys);
|
||||
for (&upvar_ty, final_upvar_ty) in closure_substs.upvar_tys.iter().zip(final_upvar_tys) {
|
||||
for (upvar_ty, final_upvar_ty) in
|
||||
closure_substs.upvar_tys(def_id, self.fcx.tcx).zip(final_upvar_tys)
|
||||
{
|
||||
self.fcx.demand_eqtype(span, final_upvar_ty, upvar_ty);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue