diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index ee9e199a6c5..72e1525b506 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -564,8 +564,13 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w assert_eq!(next(st), '['); let did = parse_def_(st, ClosureSource, conv); let substs = parse_substs_(st, conv); + let mut tys = vec![]; + while peek(st) != '.' { + tys.push(parse_ty_(st, conv)); + } + assert_eq!(next(st), '.'); assert_eq!(next(st), ']'); - return st.tcx.mk_closure(did, st.tcx.mk_substs(substs)); + return st.tcx.mk_closure(did, st.tcx.mk_substs(substs), tys); } 'P' => { assert_eq!(next(st), '['); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index e29c0f2b837..77b5306c36e 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -143,9 +143,13 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { enc_substs(w, cx, substs); mywrite!(w, "]"); } - ty::TyClosure(def, substs) => { + ty::TyClosure(def, substs, ref tys) => { mywrite!(w, "k[{}|", (cx.ds)(def)); enc_substs(w, cx, substs); + for ty in tys { + enc_ty(w, cx, ty); + } + mywrite!(w, "."); mywrite!(w, "]"); } ty::TyProjection(ref data) => { diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs index de7582a1371..4635e406c41 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -76,7 +76,7 @@ pub fn simplify_type(tcx: &ty::ctxt, Err(msg) => tcx.sess.fatal(&msg), } } - ty::TyClosure(def_id, _) => { + ty::TyClosure(def_id, _, _) => { Some(ClosureSimplifiedType(def_id)) } ty::TyTuple(ref tys) => { diff --git a/src/librustc/middle/implicator.rs b/src/librustc/middle/implicator.rs index 18059848481..b6a8037fe03 100644 --- a/src/librustc/middle/implicator.rs +++ b/src/librustc/middle/implicator.rs @@ -96,7 +96,8 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> { // No borrowed content reachable here. } - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { + // TODO remove RegionSubClosure let &(r_a, opt_ty) = self.stack.last().unwrap(); self.out.push(Implication::RegionSubClosure(opt_ty, r_a, def_id, substs)); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 4345649de0c..fbb80fef9e6 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1493,7 +1493,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn fn_ret(&self, id: NodeId) -> ty::PolyFnOutput<'tcx> { let fn_ty = self.ir.tcx.node_id_to_type(id); match fn_ty.sty { - ty::TyClosure(closure_def_id, substs) => + ty::TyClosure(closure_def_id, substs, _) => self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), _ => fn_ty.fn_ret() } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index bf47396bb9f..4ba154b1046 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -584,7 +584,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { def::DefUpvar(var_id, fn_node_id) => { let ty = try!(self.node_ty(fn_node_id)); match ty.sty { - ty::TyClosure(closure_id, _) => { + ty::TyClosure(closure_id, _, _) => { match self.typer.closure_kind(closure_id) { Some(kind) => { self.cat_upvar(id, span, var_id, fn_node_id, kind) diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 148b27adf64..ea2dee76159 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -271,6 +271,7 @@ pub struct VtableImplData<'tcx, N> { pub struct VtableClosureData<'tcx, N> { pub closure_def_id: ast::DefId, pub substs: subst::Substs<'tcx>, + pub upvar_tys: Vec>, /// Nested obligations. This can be non-empty if the closure /// signature contains associated types. pub nested: Vec @@ -548,7 +549,8 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableClosure(c) => VtableClosure(VtableClosureData { closure_def_id: c.closure_def_id, substs: c.substs, - nested: c.nested.into_iter().map(f).collect() + nested: c.nested.into_iter().map(f).collect(), + upvar_tys: c.upvar_tys, }) } } diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index cd38e9d0d31..b678aa405a8 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -154,7 +154,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext debug!("consider_unification_despite_ambiguity: self_ty.sty={:?}", self_ty.sty); match self_ty.sty { - ty::TyClosure(closure_def_id, substs) => { + ty::TyClosure(closure_def_id, substs, _) => { let closure_typer = selcx.closure_typer(); let closure_type = closure_typer.closure_type(closure_def_id, substs); let ty::Binder((_, ret_type)) = diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 81e59f57ae7..af41e205aec 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -201,7 +201,7 @@ enum SelectionCandidate<'tcx> { /// Implementation of a `Fn`-family trait by one of the /// anonymous types generated for a `||` expression. - ClosureCandidate(/* closure */ ast::DefId, Substs<'tcx>), + ClosureCandidate(/* closure */ ast::DefId, &'tcx Substs<'tcx>, &'tcx Vec>), /// Implementation of a `Fn`-family trait by one of the anonymous /// types generated for a fn pointer type (e.g., `fn(int)->int`) @@ -348,7 +348,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // lifetimes can appear inside the self-type. let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let (closure_def_id, substs) = match self_ty.sty { - ty::TyClosure(id, ref substs) => (id, substs.clone()), + ty::TyClosure(id, ref substs, _) => (id, substs.clone()), _ => { return; } }; assert!(!substs.has_escaping_regions()); @@ -1142,8 +1142,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); - let (closure_def_id, substs) = match self_ty.sty { - ty::TyClosure(id, substs) => (id, substs), + let (closure_def_id, substs, upvar_tys) = match self_ty.sty { + ty::TyClosure(id, substs, ref upvar_tys) => (id, substs, upvar_tys), ty::TyInfer(ty::TyVar(_)) => { debug!("assemble_unboxed_closure_candidates: ambiguous self-type"); candidates.ambiguous = true; @@ -1161,8 +1161,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Some(closure_kind) => { debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind); if closure_kind.extends(kind) { - candidates.vec.push(ClosureCandidate(closure_def_id, - substs.clone())); + candidates.vec.push(ClosureCandidate(closure_def_id, substs, upvar_tys)); } } None => { @@ -1704,7 +1703,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet ty::TyTuple(ref tys) => ok_if(tys.clone()), - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { // FIXME -- This case is tricky. In the case of by-ref // closures particularly, we need the results of // inference to decide how to reflect the type of each @@ -1730,6 +1729,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return ok_if(Vec::new()); } + // TODO match self.infcx.closure_upvars(def_id, substs) { Some(upvars) => ok_if(upvars.iter().map(|c| c.ty).collect()), None => { @@ -1865,9 +1865,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Some(tys.clone()) } - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { assert_eq!(def_id.krate, ast::LOCAL_CRATE); + // TODO match self.infcx.closure_upvars(def_id, substs) { Some(upvars) => { Some(upvars.iter().map(|c| c.ty).collect()) @@ -2014,9 +2015,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(VtableImpl(vtable_impl)) } - ClosureCandidate(closure_def_id, substs) => { + ClosureCandidate(closure_def_id, substs, upvar_tys) => { let vtable_closure = - try!(self.confirm_closure_candidate(obligation, closure_def_id, &substs)); + try!(self.confirm_closure_candidate(obligation, closure_def_id, + &substs, upvar_tys)); Ok(VtableClosure(vtable_closure)) } @@ -2365,7 +2367,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_closure_candidate(&mut self, obligation: &TraitObligation<'tcx>, closure_def_id: ast::DefId, - substs: &Substs<'tcx>) + substs: &Substs<'tcx>, + upvar_tys: &'tcx Vec>) -> Result>, SelectionError<'tcx>> { @@ -2391,6 +2394,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(VtableClosureData { closure_def_id: closure_def_id, substs: substs.clone(), + upvar_tys: upvar_tys.clone(), nested: obligations }) } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 64e707f6264..17d55737114 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1767,7 +1767,7 @@ pub enum TypeVariants<'tcx> { /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. - TyClosure(DefId, &'tcx Substs<'tcx>), + TyClosure(DefId, &'tcx Substs<'tcx>, Vec>), /// A tuple type. For example, `(i32, bool)`. TyTuple(Vec>), @@ -3214,10 +3214,11 @@ impl FlagComputation { } } - &TyClosure(_, substs) => { + &TyClosure(_, substs, ref tys) => { self.add_flags(TypeFlags::HAS_TY_CLOSURE); self.add_flags(TypeFlags::HAS_LOCAL_NAMES); self.add_substs(substs); + self.add_tys(tys); } &TyInfer(_) => { @@ -3659,9 +3660,12 @@ impl<'tcx> ctxt<'tcx> { self.mk_ty(TyStruct(struct_id, substs)) } - pub fn mk_closure(&self, closure_id: ast::DefId, substs: &'tcx Substs<'tcx>) + pub fn mk_closure(&self, + closure_id: ast::DefId, + substs: &'tcx Substs<'tcx>, + tys: Vec>) -> Ty<'tcx> { - self.mk_ty(TyClosure(closure_id, substs)) + self.mk_ty(TyClosure(closure_id, substs, tys)) } pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> { @@ -3928,7 +3932,7 @@ impl<'tcx> TyS<'tcx> { TyTrait(ref tt) => Some(tt.principal_def_id()), TyStruct(id, _) | TyEnum(id, _) | - TyClosure(id, _) => Some(id), + TyClosure(id, _, _) => Some(id), _ => None } } @@ -4146,7 +4150,7 @@ impl<'tcx> TyS<'tcx> { apply_lang_items(cx, did, res) } - TyClosure(did, substs) => { + TyClosure(did, substs, _) => { let param_env = cx.empty_parameter_environment(); let infcx = infer::new_infer_ctxt(cx, &cx.tables, Some(param_env), false); let upvars = infcx.closure_upvars(did, substs).unwrap(); @@ -6378,7 +6382,7 @@ impl<'tcx> ctxt<'tcx> { } TyInfer(_) => unreachable!(), TyError => byte!(21), - TyClosure(d, _) => { + TyClosure(d, _, _) => { byte!(22); did(state, d); } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index eae2bb49664..87b5fcbd28e 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -450,6 +450,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureDa closure_def_id: self.closure_def_id, substs: self.substs.fold_with(folder), nested: self.nested.fold_with(folder), + upvar_tys: self.upvar_tys.fold_with(folder), } } } @@ -602,9 +603,10 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, let substs = substs.fold_with(this); ty::TyStruct(did, this.tcx().mk_substs(substs)) } - ty::TyClosure(did, ref substs) => { + ty::TyClosure(did, ref substs, ref tys) => { let s = substs.fold_with(this); - ty::TyClosure(did, this.tcx().mk_substs(s)) + let tys = tys.fold_with(this); + ty::TyClosure(did, this.tcx().mk_substs(s), tys) } ty::TyProjection(ref data) => { ty::TyProjection(data.fold_with(this)) diff --git a/src/librustc/middle/ty_relate/mod.rs b/src/librustc/middle/ty_relate/mod.rs index 0159801d5be..33cddc978d9 100644 --- a/src/librustc/middle/ty_relate/mod.rs +++ b/src/librustc/middle/ty_relate/mod.rs @@ -48,6 +48,12 @@ pub trait TypeRelation<'a,'tcx> : Sized { Relate::relate(self, a, b) } + /// Relete elements of two slices pairwise. + fn relate_zip>(&mut self, a: &[T], b: &[T]) -> RelateResult<'tcx, Vec> { + assert_eq!(a.len(), b.len()); + a.iter().zip(b).map(|(a, b)| self.relate(a, b)).collect() + } + /// Switch variance for the purpose of relating `a` and `b`. fn relate_with_variance>(&mut self, variance: ty::Variance, @@ -500,15 +506,16 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, Ok(tcx.mk_struct(a_id, tcx.mk_substs(substs))) } - (&ty::TyClosure(a_id, a_substs), - &ty::TyClosure(b_id, b_substs)) + (&ty::TyClosure(a_id, a_substs, ref a_tys), + &ty::TyClosure(b_id, b_substs, ref b_tys)) if a_id == b_id => { // All TyClosure types with the same id represent // the (anonymous) type of the same closure expression. So // all of their regions should be equated. let substs = try!(relate_substs(relation, None, a_substs, b_substs)); - Ok(tcx.mk_closure(a_id, tcx.mk_substs(substs))) + let tys = try!(relation.relate_zip(a_tys, b_tys)); + Ok(tcx.mk_closure(a_id, tcx.mk_substs(substs), tys)) } (&ty::TyBox(a_inner), &ty::TyBox(b_inner)) => diff --git a/src/librustc/middle/ty_walk.rs b/src/librustc/middle/ty_walk.rs index 3e9a402f949..97f3bd12971 100644 --- a/src/librustc/middle/ty_walk.rs +++ b/src/librustc/middle/ty_walk.rs @@ -88,10 +88,13 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { }).collect::>()); } ty::TyEnum(_, ref substs) | - ty::TyStruct(_, ref substs) | - ty::TyClosure(_, ref substs) => { + ty::TyStruct(_, ref substs) => { push_reversed(stack, substs.types.as_slice()); } + ty::TyClosure(_, ref substs, ref tys) => { + push_reversed(stack, substs.types.as_slice()); + push_reversed(stack, tys); + } ty::TyTuple(ref ts) => { push_reversed(stack, ts); } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index b0510a76385..d6696e392bc 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -662,7 +662,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { TyTrait(ref data) => write!(f, "{}", data), ty::TyProjection(ref data) => write!(f, "{}", data), TyStr => write!(f, "str"), - TyClosure(ref did, substs) => ty::tls::with(|tcx| { + TyClosure(ref did, substs, _) => ty::tls::with(|tcx| { try!(write!(f, "[closure")); let closure_tys = &tcx.tables.borrow().closure_tys; try!(closure_tys.get(did).map(|cty| &cty.sig).and_then(|sig| { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 6289d505881..331bcaa8da8 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -2529,7 +2529,7 @@ impl LintPass for DropWithReprExtern { match dtor_self_type.sty { ty::TyEnum(self_type_did, _) | ty::TyStruct(self_type_did, _) | - ty::TyClosure(self_type_did, _) => { + ty::TyClosure(self_type_did, _, _) => { let hints = ctx.tcx.lookup_repr_hints(self_type_did); if hints.iter().any(|attr| *attr == attr::ReprExtern) && ctx.tcx.ty_dtor(self_type_did).has_drop_flag() { diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 7b2bdee50fe..985ef2d7b14 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -221,9 +221,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor)) } - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables); - let upvars = infcx.closure_upvars(def_id, substs).unwrap(); + let upvars = infcx.closure_upvars(def_id, substs).unwrap(); // TODO let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); Univariant(mk_struct(cx, &upvar_types[..], false, t), 0) } @@ -441,9 +441,9 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>, // Perhaps one of the upvars of this struct is non-zero // Let's recurse and find out! - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables); - let upvars = infcx.closure_upvars(def_id, substs).unwrap(); + let upvars = infcx.closure_upvars(def_id, substs).unwrap(); // TODO let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); for (j, &ty) in upvar_types.iter().enumerate() { diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs index f8daefa87a5..03e7d9e3aa2 100644 --- a/src/librustc_trans/trans/attributes.rs +++ b/src/librustc_trans/trans/attributes.rs @@ -145,7 +145,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx let function_type; let (fn_sig, abi, env_ty) = match fn_type.sty { ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None), - ty::TyClosure(closure_did, substs) => { + ty::TyClosure(closure_did, substs, _) => { let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables); function_type = infcx.closure_type(closure_did, substs); let self_type = base::self_type_for_closure(ccx, closure_did, fn_type); diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 258051357b1..678b5063816 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -470,7 +470,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, } }) } - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { // TODO let repr = adt::represent_type(cx.ccx(), t); let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables); let upvars = infcx.closure_upvars(def_id, substs).unwrap(); diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index f00029ec2ff..defa0a1d898 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -12,6 +12,7 @@ use arena::TypedArena; use back::link::{self, mangle_internal_name_by_path_and_seq}; use llvm::{ValueRef, get_params}; use middle::infer; +use middle::ty::Ty; use trans::adt; use trans::attributes; use trans::base::*; @@ -142,7 +143,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc // duplicate declarations let function_type = erase_regions(ccx.tcx(), &function_type); let params = match function_type.sty { - ty::TyClosure(_, substs) => &substs.types, + ty::TyClosure(_, substs, _) => &substs.types, _ => unreachable!() }; let mono_id = MonoId { @@ -269,6 +270,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, closure_def_id: ast::DefId, substs: Substs<'tcx>, + upvar_tys: Vec>, node: ExprOrMethodCall, param_substs: &'tcx Substs<'tcx>, trait_closure_kind: ty::ClosureKind) @@ -288,6 +290,7 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, trans_closure_adapter_shim(ccx, closure_def_id, substs, + upvar_tys, closure_kind, trait_closure_kind, llfn) @@ -297,6 +300,7 @@ fn trans_closure_adapter_shim<'a, 'tcx>( ccx: &'a CrateContext<'a, 'tcx>, closure_def_id: ast::DefId, substs: Substs<'tcx>, + upvar_tys: Vec>, llfn_closure_kind: ty::ClosureKind, trait_closure_kind: ty::ClosureKind, llfn: ValueRef) @@ -335,7 +339,7 @@ fn trans_closure_adapter_shim<'a, 'tcx>( // fn call_once(mut self, ...) { call_mut(&mut self, ...) } // // These are both the same at trans time. - trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn) + trans_fn_once_adapter_shim(ccx, closure_def_id, substs, upvar_tys, llfn) } _ => { tcx.sess.bug(&format!("trans_closure_adapter_shim: cannot convert {:?} to {:?}", @@ -349,6 +353,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( ccx: &'a CrateContext<'a, 'tcx>, closure_def_id: ast::DefId, substs: Substs<'tcx>, + upvar_tys: Vec>, llreffn: ValueRef) -> ValueRef { @@ -363,7 +368,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( // Find a version of the closure type. Substitute static for the // region since it doesn't really matter. let substs = tcx.mk_substs(substs); - let closure_ty = tcx.mk_closure(closure_def_id, substs); + let closure_ty = tcx.mk_closure(closure_def_id, substs, upvar_tys); let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), closure_ty); // Make a version with the type of by-ref closure. diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs index 5f17197a4b9..d0c6c0ab308 100644 --- a/src/librustc_trans/trans/debuginfo/metadata.rs +++ b/src/librustc_trans/trans/debuginfo/metadata.rs @@ -287,7 +287,7 @@ impl<'tcx> TypeMap<'tcx> { } } }, - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables); let closure_ty = infcx.closure_type(def_id, substs); self.get_unique_type_id_of_closure_type(cx, @@ -811,7 +811,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false) } - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables); let upvars = infcx.closure_upvars(def_id, substs).unwrap(); let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs index c802de91e38..a641302e53f 100644 --- a/src/librustc_trans/trans/declare.rs +++ b/src/librustc_trans/trans/declare.rs @@ -116,7 +116,7 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, ty::TyBareFn(_, ref f) => { (&f.sig, f.abi, None) } - ty::TyClosure(closure_did, substs) => { + ty::TyClosure(closure_did, substs, _) => { let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables); function_type = infcx.closure_type(closure_did, substs); let self_type = base::self_type_for_closure(ccx, closure_did, fn_type); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 8901361b279..cf2a226db41 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -341,6 +341,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llfn = closure::trans_closure_method(bcx.ccx(), vtable_closure.closure_def_id, vtable_closure.substs, + vtable_closure.upvar_tys, MethodCallKey(method_call), bcx.fcx.param_substs, trait_closure_kind); @@ -641,11 +642,13 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, traits::VtableClosureData { closure_def_id, substs, + upvar_tys, nested: _ }) => { let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap(); let llfn = closure::trans_closure_method(ccx, closure_def_id, substs, + upvar_tys, ExprId(0), param_substs, trait_closure_kind); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index f32a4fe43d6..955a3013405 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -131,7 +131,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, return Some(CallStep::Builtin); } - ty::TyClosure(def_id, substs) => { + ty::TyClosure(def_id, substs, _) => { assert_eq!(def_id.krate, ast::LOCAL_CRATE); // Check whether this is a call to a closure where we diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 6d1e9dfacf2..71e51292a78 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -60,8 +60,18 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, abi::RustCall, expected_sig); - let closure_type = fcx.ccx.tcx.mk_closure(expr_def_id, - fcx.ccx.tcx.mk_substs(fcx.inh.infcx.parameter_environment.free_substs.clone())); + let freevar_tys = + fcx.tcx().with_freevars(expr.id, |fv| { + fv.iter() + .map(|_| fcx.tcx().types.bool) // TODO + .collect() + }); + + let closure_type = + fcx.ccx.tcx.mk_closure( + expr_def_id, + fcx.ccx.tcx.mk_substs(fcx.inh.infcx.parameter_environment.free_substs.clone()), + freevar_tys); fcx.write_ty(expr.id, closure_type); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 7d911cf8b03..f37177684d5 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -42,7 +42,7 @@ pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(), match dtor_self_type.sty { ty::TyEnum(self_type_did, self_to_impl_substs) | ty::TyStruct(self_type_did, self_to_impl_substs) | - ty::TyClosure(self_type_did, self_to_impl_substs) => { + ty::TyClosure(self_type_did, self_to_impl_substs, _) => { try!(ensure_drop_params_and_item_params_correspond(tcx, drop_impl_did, dtor_generics, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index a960123efc6..8b9871428c4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -288,7 +288,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } ty::TyEnum(did, _) | ty::TyStruct(did, _) | - ty::TyClosure(did, _) => { + ty::TyClosure(did, _, _) => { self.assemble_inherent_impl_candidates_for_type(did); } ty::TyBox(_) => { @@ -711,7 +711,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { let steps = self.steps.clone(); for step in steps.iter() { let closure_def_id = match step.self_ty.sty { - ty::TyClosure(a, _) => a, + ty::TyClosure(a, _, _) => a, _ => continue, }; diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 2b800bd9a44..0878ca1c295 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -312,7 +312,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { match self_type.ty.sty { ty::TyEnum(type_def_id, _) | ty::TyStruct(type_def_id, _) | - ty::TyClosure(type_def_id, _) => { + ty::TyClosure(type_def_id, _, _) => { tcx.destructor_for_type .borrow_mut() .insert(type_def_id, method_def_id.def_id());