]> git.lizzy.rs Git - rust.git/commitdiff
Introduce ClosureSubsts rather than just having random fields in the
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 16 Jul 2015 13:46:35 +0000 (09:46 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Fri, 24 Jul 2015 08:53:17 +0000 (04:53 -0400)
TyClosure variant; thread this through wherever closure substitutions
are expected, which leads to a net simplification. Simplify trans
treatment of closures in particular.

30 files changed:
src/librustc/metadata/tyencode.rs
src/librustc/middle/fast_reject.rs
src/librustc/middle/implicator.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/project.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/middle/ty_relate/mod.rs
src/librustc/middle/ty_walk.rs
src/librustc/util/ppaux.rs
src/librustc_lint/builtin.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/attributes.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/closure.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/debuginfo/metadata.rs
src/librustc_trans/trans/declare.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/meth.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/coherence/mod.rs

index 77b5306c36e43262416c14ad94c2badfb6527e59..c77e96f1648882da676ae3c8b966b9ed1d856be2 100644 (file)
@@ -143,10 +143,10 @@ 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, ref tys) => {
+        ty::TyClosure(def, ref substs) => {
             mywrite!(w, "k[{}|", (cx.ds)(def));
-            enc_substs(w, cx, substs);
-            for ty in tys {
+            enc_substs(w, cx, &substs.func_substs);
+            for ty in &substs.upvar_tys {
                 enc_ty(w, cx, ty);
             }
             mywrite!(w, ".");
index 4635e406c4122320e9c5b65556d56a8659e36d46..de7582a13716620ec4e9bd6baf141d1a473d1fdf 100644 (file)
@@ -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) => {
index b6a8037fe033ec45044757bef7a84fa00cf17c58..8fba98bead479bfb59d9e18976a103f0115e8102 100644 (file)
@@ -28,7 +28,7 @@
 pub enum Implication<'tcx> {
     RegionSubRegion(Option<Ty<'tcx>>, ty::Region, ty::Region),
     RegionSubGeneric(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
-    RegionSubClosure(Option<Ty<'tcx>>, ty::Region, ast::DefId, &'tcx Substs<'tcx>),
+    RegionSubClosure(Option<Ty<'tcx>>, ty::Region, ast::DefId, &'tcx ty::ClosureSubsts<'tcx>),
     Predicate(ast::DefId, ty::Predicate<'tcx>),
 }
 
@@ -96,7 +96,7 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
                 // No borrowed content reachable here.
             }
 
-            ty::TyClosure(def_id, substs, _) => {
+            ty::TyClosure(def_id, ref 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));
index a293170966aacaac21dfd01dc636d2f671a76663..e6cea4d1b6ac088ff1919125aebfa5e4701009c3 100644 (file)
@@ -1374,17 +1374,16 @@ pub fn closure_kind(&self,
     }
 
     pub fn closure_type(&self,
-                    def_id: ast::DefId,
-                    substs: &subst::Substs<'tcx>)
-                    -> ty::ClosureTy<'tcx>
+                        def_id: ast::DefId,
+                        substs: &ty::ClosureSubsts<'tcx>)
+                        -> ty::ClosureTy<'tcx>
     {
-
         let closure_ty = self.tables
                              .borrow()
                              .closure_tys
                              .get(&def_id)
                              .unwrap()
-                             .subst(self.tcx, substs);
+                             .subst(self.tcx, &substs.func_substs);
 
         if self.normalize {
             normalize_associated_type(&self.tcx, &closure_ty)
@@ -1395,7 +1394,7 @@ pub fn closure_type(&self,
 
     pub fn closure_upvars(&self,
                           def_id: ast::DefId,
-                          substs: &Substs<'tcx>)
+                          substs: &ty::ClosureSubsts<'tcx>)
                           -> Option<Vec<ty::ClosureUpvar<'tcx>>>
     {
         let result = ty::ctxt::closure_upvars(self, def_id, substs);
index fbb80fef9e6df2977c0aebec3eb082c105607005..7db740798bd406f989be18c519cbfca939a638f3 100644 (file)
@@ -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, ref substs) =>
                 self.ir.tcx.closure_type(closure_def_id, substs).sig.output(),
             _ => fn_ty.fn_ret()
         }
index 4ba154b1046f30797f307056f2490f8b0976e36f..bf47396bb9f656afdba931e1e18e178c52099744 100644 (file)
@@ -584,7 +584,7 @@ pub fn cat_def(&self,
           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)
index ea2dee761593555d131b07d59faa0c76b108cfa1..376430e87c6f005b10ee6615a33df7ef044c7a08 100644 (file)
@@ -270,8 +270,7 @@ pub struct VtableImplData<'tcx, N> {
 #[derive(Clone, PartialEq, Eq)]
 pub struct VtableClosureData<'tcx, N> {
     pub closure_def_id: ast::DefId,
-    pub substs: subst::Substs<'tcx>,
-    pub upvar_tys: Vec<Ty<'tcx>>,
+    pub substs: ty::ClosureSubsts<'tcx>,
     /// Nested obligations. This can be non-empty if the closure
     /// signature contains associated types.
     pub nested: Vec<N>
@@ -550,7 +549,6 @@ pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M {
                 closure_def_id: c.closure_def_id,
                 substs: c.substs,
                 nested: c.nested.into_iter().map(f).collect(),
-                upvar_tys: c.upvar_tys,
             })
         }
     }
index b678aa405a89cfdc01947b01a3a9b4d01f479a95..ef3a217ecdbf28d494d691def3fe700300a7ab9a 100644 (file)
@@ -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, ref substs) => {
             let closure_typer = selcx.closure_typer();
             let closure_type = closure_typer.closure_type(closure_def_id, substs);
             let ty::Binder((_, ret_type)) =
index af41e205aec6672d9a0ff2f6732d69f8e820c42a..c2c2ceb0b033de851134e455e6c56d7c4826897e 100644 (file)
@@ -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, &'tcx Substs<'tcx>, &'tcx Vec<Ty<'tcx>>),
+    ClosureCandidate(/* closure */ ast::DefId, &'tcx ty::ClosureSubsts<'tcx>),
 
     /// 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 @@ fn consider_unification_despite_ambiguity(&mut self, obligation: &TraitObligatio
         // 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),
             _ => { return; }
         };
         assert!(!substs.has_escaping_regions());
@@ -1142,8 +1142,8 @@ fn assemble_closure_candidates(&mut self,
         // 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, upvar_tys) = match self_ty.sty {
-            ty::TyClosure(id, substs, ref upvar_tys) => (id, substs, upvar_tys),
+        let (closure_def_id, substs) = match self_ty.sty {
+            ty::TyClosure(id, ref substs) => (id, substs),
             ty::TyInfer(ty::TyVar(_)) => {
                 debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
                 candidates.ambiguous = true;
@@ -1161,7 +1161,7 @@ fn assemble_closure_candidates(&mut self,
             Some(closure_kind) => {
                 debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
                 if closure_kind.extends(kind) {
-                    candidates.vec.push(ClosureCandidate(closure_def_id, substs, upvar_tys));
+                    candidates.vec.push(ClosureCandidate(closure_def_id, substs));
                 }
             }
             None => {
@@ -1703,7 +1703,7 @@ fn builtin_bound(&mut self,
             // (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, ref 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
@@ -1865,7 +1865,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
                 Some(tys.clone())
             }
 
-            ty::TyClosure(def_id, substs, _) => {
+            ty::TyClosure(def_id, ref substs) => {
                 assert_eq!(def_id.krate, ast::LOCAL_CRATE);
 
                 // TODO
@@ -2015,10 +2015,9 @@ fn confirm_candidate(&mut self,
                 Ok(VtableImpl(vtable_impl))
             }
 
-            ClosureCandidate(closure_def_id, substs, upvar_tys) => {
+            ClosureCandidate(closure_def_id, substs) => {
                 let vtable_closure =
-                    try!(self.confirm_closure_candidate(obligation, closure_def_id,
-                                                        &substs, upvar_tys));
+                    try!(self.confirm_closure_candidate(obligation, closure_def_id, substs));
                 Ok(VtableClosure(vtable_closure))
             }
 
@@ -2367,8 +2366,7 @@ fn confirm_fn_pointer_candidate(&mut self,
     fn confirm_closure_candidate(&mut self,
                                  obligation: &TraitObligation<'tcx>,
                                  closure_def_id: ast::DefId,
-                                 substs: &Substs<'tcx>,
-                                 upvar_tys: &'tcx Vec<Ty<'tcx>>)
+                                 substs: &ty::ClosureSubsts<'tcx>)
                                  -> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
                                            SelectionError<'tcx>>
     {
@@ -2394,7 +2392,6 @@ fn confirm_closure_candidate(&mut self,
         Ok(VtableClosureData {
             closure_def_id: closure_def_id,
             substs: substs.clone(),
-            upvar_tys: upvar_tys.clone(),
             nested: obligations
         })
     }
@@ -2856,7 +2853,7 @@ fn push_stack<'o,'s:'o>(&mut self,
     fn closure_trait_ref_unnormalized(&mut self,
                                       obligation: &TraitObligation<'tcx>,
                                       closure_def_id: ast::DefId,
-                                      substs: &Substs<'tcx>)
+                                      substs: &ty::ClosureSubsts<'tcx>)
                                       -> ty::PolyTraitRef<'tcx>
     {
         let closure_type = self.infcx.closure_type(closure_def_id, substs);
@@ -2878,7 +2875,7 @@ fn closure_trait_ref_unnormalized(&mut self,
     fn closure_trait_ref(&mut self,
                          obligation: &TraitObligation<'tcx>,
                          closure_def_id: ast::DefId,
-                         substs: &Substs<'tcx>)
+                         substs: &ty::ClosureSubsts<'tcx>)
                          -> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
     {
         let trait_ref = self.closure_trait_ref_unnormalized(
index 17d55737114fb73787862044e81dd477c853e2c4..5528472d793134498c837ff53a96c8b246f50b41 100644 (file)
@@ -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>, Vec<Ty<'tcx>>),
+    TyClosure(DefId, Box<ClosureSubsts<'tcx>>),
 
     /// A tuple type.  For example, `(i32, bool)`.
     TyTuple(Vec<Ty<'tcx>>),
@@ -1787,6 +1787,93 @@ pub enum TypeVariants<'tcx> {
     TyError,
 }
 
+/// A closure can be modeled as a struct that looks like:
+///
+///     struct Closure<'l0...'li, T0...Tj, U0...Uk> {
+///         upvar0: U0,
+///         ...
+///         upvark: Uk
+///     }
+///
+/// where 'l0...'li and T0...Tj are the lifetime and type parameters
+/// in scope on the function that defined the closure, and U0...Uk are
+/// type parameters representing the types of its upvars (borrowed, if
+/// appropriate).
+///
+/// So, for example, given this function:
+///
+///     fn foo<'a, T>(data: &'a mut T) {
+///          do(|| data.count += 1)
+///     }
+///
+/// the type of the closure would be something like:
+///
+///     struct Closure<'a, T, U0> {
+///         data: U0
+///     }
+///
+/// Note that the type of the upvar is not specified in the struct.
+/// You may wonder how the impl would then be able to use the upvar,
+/// if it doesn't know it's type? The answer is that the impl is
+/// (conceptually) not fully generic over Closure but rather tied to
+/// instances with the expected upvar types:
+///
+///     impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> {
+///         ...
+///     }
+///
+/// You can see that the *impl* fully specified the type of the upvar
+/// and thus knows full well that `data` has type `&'b mut &'a mut T`.
+/// (Here, I am assuming that `data` is mut-borrowed.)
+///
+/// Now, the last question you may ask is: Why include the upvar types
+/// as extra type parameters? The reason for this design is that the
+/// upvar types can reference lifetimes that are internal to the
+/// creating function. In my example above, for example, the lifetime
+/// `'b` represents the extent of the closure itself; this is some
+/// subset of `foo`, probably just the extent of the call to the to
+/// `do()`. If we just had the lifetime/type parameters from the
+/// enclosing function, we couldn't name this lifetime `'b`. Note that
+/// there can also be lifetimes in the types of the upvars themselves,
+/// if one of them happens to be a reference to something that the
+/// creating fn owns.
+///
+/// OK, you say, so why not create a more minimal set of parameters
+/// that just includes the extra lifetime parameters? The answer is
+/// primarily that it would be hard --- we don't know at the time when
+/// we create the closure type what the full types of the upvars are,
+/// nor do we know which are borrowed and which are not. In this
+/// design, we can just supply a fresh type parameter and figure that
+/// out later.
+///
+/// All right, you say, but why include the type parameters from the
+/// original function then? The answer is that trans may need them
+/// when monomorphizing, and they may not appear in the upvars.  A
+/// closure could capture no variables but still make use of some
+/// in-scope type parameter with a bound (e.g., if our example above
+/// had an extra `U: Default`, and the closure called `U::default()`).
+///
+/// There is another reason. This design (implicitly) prohibits
+/// closures from capturing themselves (except via a trait
+/// object). This simplifies closure inference considerably, since it
+/// means that when we infer the kind of a closure or its upvars, we
+/// don't have to handles cycles where the decisions we make wind up
+/// for closure C wind up influencing the decisions we ought to make
+/// for closure C (which would then require fixed point iteration to
+/// handle). Plus it fixes an ICE. :P
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct ClosureSubsts<'tcx> {
+    /// Lifetime and type parameters from the enclosing function.
+    /// These are separated out because trans wants to pass them around
+    /// when monomorphizing.
+    pub func_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: Vec<Ty<'tcx>>
+}
+
 #[derive(Clone, PartialEq, Eq, Hash)]
 pub struct TraitTy<'tcx> {
     pub principal: ty::PolyTraitRef<'tcx>,
@@ -3214,11 +3301,11 @@ fn add_sty(&mut self, st: &TypeVariants) {
                 }
             }
 
-            &TyClosure(_, substs, ref tys) => {
+            &TyClosure(_, ref substs) => {
                 self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                 self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
-                self.add_substs(substs);
-                self.add_tys(tys);
+                self.add_substs(&substs.func_substs);
+                self.add_tys(&substs.upvar_tys);
             }
 
             &TyInfer(_) => {
@@ -3462,10 +3549,10 @@ pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind {
 
     pub fn closure_type(&self,
                         def_id: ast::DefId,
-                        substs: &subst::Substs<'tcx>)
+                        substs: &ClosureSubsts<'tcx>)
                         -> ty::ClosureTy<'tcx>
     {
-        self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, substs)
+        self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs)
     }
 
     pub fn type_parameter_def(&self,
@@ -3665,7 +3752,17 @@ pub fn mk_closure(&self,
                       substs: &'tcx Substs<'tcx>,
                       tys: Vec<Ty<'tcx>>)
                       -> Ty<'tcx> {
-        self.mk_ty(TyClosure(closure_id, substs, tys))
+        self.mk_closure_from_closure_substs(closure_id, Box::new(ClosureSubsts {
+            func_substs: substs,
+            upvar_tys: tys
+        }))
+    }
+
+    pub fn mk_closure_from_closure_substs(&self,
+                                          closure_id: ast::DefId,
+                                          closure_substs: Box<ClosureSubsts<'tcx>>)
+                                          -> Ty<'tcx> {
+        self.mk_ty(TyClosure(closure_id, closure_substs))
     }
 
     pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
@@ -3932,7 +4029,7 @@ pub fn ty_to_def_id(&self) -> Option<ast::DefId> {
             TyTrait(ref tt) => Some(tt.principal_def_id()),
             TyStruct(id, _) |
             TyEnum(id, _) |
-            TyClosure(id, _, _) => Some(id),
+            TyClosure(id, _) => Some(id),
             _ => None
         }
     }
@@ -4150,7 +4247,8 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
                     apply_lang_items(cx, did, res)
                 }
 
-                TyClosure(did, substs, _) => {
+                TyClosure(did, ref substs) => {
+                    // TODO
                     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();
@@ -5911,9 +6009,9 @@ pub fn struct_lockstep_tails(&self,
 
     // Returns a list of `ClosureUpvar`s for each upvar.
     pub fn closure_upvars<'a>(typer: &infer::InferCtxt<'a, 'tcx>,
-                          closure_id: ast::DefId,
-                          substs: &Substs<'tcx>)
-                          -> Option<Vec<ClosureUpvar<'tcx>>>
+                              closure_id: ast::DefId,
+                              substs: &ClosureSubsts<'tcx>)
+                              -> Option<Vec<ClosureUpvar<'tcx>>>
     {
         // Presently an unboxed closure type cannot "escape" out of a
         // function, so we will only encounter ones that originated in the
@@ -5932,7 +6030,7 @@ pub fn closure_upvars<'a>(typer: &infer::InferCtxt<'a, 'tcx>,
                                 Ok(t) => { t }
                                 Err(()) => { return None; }
                             };
-                            let freevar_ty = freevar_ty.subst(tcx, substs);
+                            let freevar_ty = freevar_ty.subst(tcx, &substs.func_substs);
 
                             let upvar_id = ty::UpvarId {
                                 var_id: freevar_def_id.node,
@@ -6382,7 +6480,7 @@ macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
                     }
                     TyInfer(_) => unreachable!(),
                     TyError => byte!(21),
-                    TyClosure(d, _, _) => {
+                    TyClosure(d, _) => {
                         byte!(22);
                         did(state, d);
                     }
@@ -6763,6 +6861,13 @@ fn has_regions_escaping_depth(&self, depth: u32) -> bool {
     }
 }
 
+impl<'tcx> RegionEscape for ClosureSubsts<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.func_substs.has_regions_escaping_depth(depth) ||
+            self.upvar_tys.iter().any(|t| t.has_regions_escaping_depth(depth))
+    }
+}
+
 impl<T:RegionEscape> RegionEscape for Vec<T> {
     fn has_regions_escaping_depth(&self, depth: u32) -> bool {
         self.iter().any(|t| t.has_regions_escaping_depth(depth))
@@ -7106,6 +7211,15 @@ fn has_type_flags(&self, flags: TypeFlags) -> bool {
     }
 }
 
+impl<'tcx> HasTypeFlags for ClosureSubsts<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.func_substs.has_type_flags(flags) ||
+            self.upvar_tys.iter().any(|t| t.has_type_flags(flags))
+    }
+}
+
+
+
 impl<'tcx> fmt::Debug for ClosureTy<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "ClosureTy({},{:?},{})",
index 87b5fcbd28e90e3fb6bf67480fe0748c8dc6a434..b6bb82ad7b15b2f5bd16ddea6e4ab490ca04efe0 100644 (file)
@@ -296,6 +296,16 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> subst::Substs<'tcx>
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureSubsts<'tcx> {
+        let func_substs = self.func_substs.fold_with(folder);
+        ty::ClosureSubsts {
+            func_substs: folder.tcx().mk_substs(func_substs),
+            upvar_tys: self.upvar_tys.fold_with(folder),
+        }
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ItemSubsts<'tcx> {
         ty::ItemSubsts {
@@ -450,7 +460,6 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableClosure
             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),
         }
     }
 }
@@ -603,10 +612,9 @@ 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, ref tys) => {
+        ty::TyClosure(did, ref substs) => {
             let s = substs.fold_with(this);
-            let tys = tys.fold_with(this);
-            ty::TyClosure(did, this.tcx().mk_substs(s), tys)
+            ty::TyClosure(did, s)
         }
         ty::TyProjection(ref data) => {
             ty::TyProjection(data.fold_with(this))
index 33cddc978d9bb46d5905100630d8f7b2e842e5eb..f8678b4d8e3bd1b47cd6481758474bc37400eb87 100644 (file)
@@ -506,16 +506,15 @@ 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, ref a_tys),
-         &ty::TyClosure(b_id, b_substs, ref b_tys))
+        (&ty::TyClosure(a_id, ref a_substs),
+         &ty::TyClosure(b_id, ref b_substs))
             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));
-            let tys = try!(relation.relate_zip(a_tys, b_tys));
-            Ok(tcx.mk_closure(a_id, tcx.mk_substs(substs), tys))
+            let substs = try!(relation.relate(a_substs, b_substs));
+            Ok(tcx.mk_closure_from_closure_substs(a_id, substs))
         }
 
         (&ty::TyBox(a_inner), &ty::TyBox(b_inner)) =>
@@ -588,6 +587,20 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
     }
 }
 
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ClosureSubsts<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::ClosureSubsts<'tcx>,
+                 b: &ty::ClosureSubsts<'tcx>)
+                 -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        let func_substs = try!(relate_substs(relation, None, a.func_substs, b.func_substs));
+        let upvar_tys = try!(relation.relate_zip(&a.upvar_tys, &b.upvar_tys));
+        Ok(ty::ClosureSubsts { func_substs: relation.tcx().mk_substs(func_substs),
+                               upvar_tys: upvar_tys })
+    }
+}
+
 impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::Region {
     fn relate<R>(relation: &mut R,
                  a: &ty::Region,
index 97f3bd1297197e4a67d3264b1fb650fe2c3fc710..81cad4486904b7e6e7ee946bbd2a2ebc53ca540a 100644 (file)
@@ -91,9 +91,9 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
         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::TyClosure(_, ref substs) => {
+            push_reversed(stack, substs.func_substs.types.as_slice());
+            push_reversed(stack, &substs.upvar_tys);
         }
         ty::TyTuple(ref ts) => {
             push_reversed(stack, ts);
index d6696e392bcff4c726188b27e7c988a44195e29d..d24fa5cef0349bae1d035e6d3e37311912372f29 100644 (file)
@@ -662,11 +662,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             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, ref substs) => ty::tls::with(|tcx| {
                 try!(write!(f, "[closure"));
+
+                // TODO consider changing this to print out the upvar types instead
+
                 let closure_tys = &tcx.tables.borrow().closure_tys;
                 try!(closure_tys.get(did).map(|cty| &cty.sig).and_then(|sig| {
-                    tcx.lift(&substs).map(|substs| sig.subst(tcx, substs))
+                    tcx.lift(&substs.func_substs).map(|substs| sig.subst(tcx, substs))
                 }).map(|sig| {
                     fn_sig(f, &sig.0.inputs, false, sig.0.output)
                 }).unwrap_or_else(|| {
index 331bcaa8da89b8dab27b10fa7d7a0bf2bb5b6592..6289d50588104bbffa0baf63dd9379b38862e535 100644 (file)
@@ -2529,7 +2529,7 @@ fn check_crate(&mut self, ctx: &Context, _: &ast::Crate) {
             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() {
index 985ef2d7b14fcf979562039578fd4478661ec58a..b51a3d4b2a081c52a927346a61157e8ce12dc725 100644 (file)
@@ -221,7 +221,7 @@ 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, ref substs) => {
             let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
             let upvars = infcx.closure_upvars(def_id, substs).unwrap(); // TODO
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
@@ -441,7 +441,7 @@ 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, ref substs) => {
             let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
             let upvars = infcx.closure_upvars(def_id, substs).unwrap(); // TODO
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
index 03e7d9e3aa28596dc06e89a9ec2a5683cfc6b727..62b03c9fb0f1fcaa858b6ed464efe9628220e4df 100644 (file)
@@ -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, ref 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);
index 678b5063816c70531148e13a9c71610e4503bef2..e18fc6c5da2beec5e218f769ef9b62e895ee49e3 100644 (file)
@@ -470,7 +470,7 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
               }
           })
       }
-      ty::TyClosure(def_id, substs, _) => { // TODO
+      ty::TyClosure(def_id, ref 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();
index 7900000d3a9df1d33478acb7ad2b119721182047..0f75c1f8ab65a6d0befe9ec2f3b25a57db63db43 100644 (file)
@@ -32,7 +32,6 @@
 use trans::callee;
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
-use trans::closure;
 use trans::common::{self, Block, Result, NodeIdAndSpan, ExprId, CrateContext,
                     ExprOrMethodCall, FunctionContext, MethodCallKey};
 use trans::consts;
@@ -446,12 +445,6 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
         }
     };
 
-    // If this is a closure, redirect to it.
-    match closure::get_or_create_declaration_if_closure(ccx, def_id, substs) {
-        None => {}
-        Some(llfn) => return llfn,
-    }
-
     // Check whether this fn has an inlined copy and, if so, redirect
     // def_id to the local id of the inlined copy.
     let def_id = inline::maybe_instantiate_inline(ccx, def_id);
index defa0a1d898bf60e5c52d3d0aade1233e9f9fab2..b05bc7e5855e8009f9d8a05c7d8d6cb8d54dfbe5 100644 (file)
@@ -12,7 +12,6 @@
 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::*;
 use trans::debuginfo::{self, DebugLoc};
 use trans::declare;
 use trans::expr;
-use trans::monomorphize::{self, MonoId};
+use trans::monomorphize::{MonoId};
 use trans::type_of::*;
 use middle::ty;
-use middle::subst::Substs;
 use session::config::FullDebugInfo;
 
 use syntax::abi::RustCall;
@@ -127,47 +125,32 @@ pub fn load<'blk,'tcx>(self, bcx: Block<'blk, 'tcx>, arg_scope: ScopeId)
 
 /// Returns the LLVM function declaration for a closure, creating it if
 /// necessary. If the ID does not correspond to a closure ID, returns None.
-pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                                      closure_id: ast::DefId,
-                                                      substs: &Substs<'tcx>)
-                                                      -> Option<Datum<'tcx, Rvalue>> {
-    if !ccx.tcx().tables.borrow().closure_kinds.contains_key(&closure_id) {
-        // Not a closure.
-        return None
-    }
-
-    let function_type = ccx.tcx().node_id_to_type(closure_id.node);
-    let function_type = monomorphize::apply_param_substs(ccx.tcx(), substs, &function_type);
-
+pub fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                                   closure_id: ast::DefId,
+                                                   substs: &ty::ClosureSubsts<'tcx>)
+                                                   -> ValueRef {
     // Normalize type so differences in regions and typedefs don't cause
     // duplicate declarations
-    let function_type = erase_regions(ccx.tcx(), &function_type);
-    let params = match function_type.sty {
-        ty::TyClosure(_, substs, _) => &substs.types,
-        _ => unreachable!()
-    };
+    let substs = erase_regions(ccx.tcx(), substs);
     let mono_id = MonoId {
         def: closure_id,
-        params: params
+        params: &substs.func_substs.types
     };
 
-    match ccx.closure_vals().borrow().get(&mono_id) {
-        Some(&llfn) => {
-            debug!("get_or_create_declaration_if_closure(): found closure {:?}: {:?}",
-                   mono_id, ccx.tn().val_to_string(llfn));
-            return Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
-        }
-        None => {}
+    if let Some(&llfn) = ccx.closure_vals().borrow().get(&mono_id) {
+        debug!("get_or_create_declaration_if_closure(): found closure {:?}: {:?}",
+               mono_id, ccx.tn().val_to_string(llfn));
+        return llfn;
     }
 
     let symbol = ccx.tcx().map.with_path(closure_id.node, |path| {
         mangle_internal_name_by_path_and_seq(path, "closure")
     });
 
-    // Currently there’s only a single user of
-    // get_or_create_declaration_if_closure and it unconditionally defines the
-    // function, therefore we use define_* here.
-    let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type);
+    let function_type = ccx.tcx().mk_closure_from_closure_substs(closure_id, Box::new(substs));
+    let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type).unwrap_or_else(||{
+        ccx.sess().bug(&format!("symbol `{}` already defined", symbol));
+    });
 
     // set an inline hint for all closures
     attributes::inline(llfn, attributes::InlineAttr::Hint);
@@ -179,7 +162,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
            ccx.tn().val_to_string(llfn));
     ccx.closure_vals().borrow_mut().insert(mono_id, llfn);
 
-    Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
+    llfn
 }
 
 pub enum Dest<'a, 'tcx: 'a> {
@@ -191,9 +174,11 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
                                     decl: &ast::FnDecl,
                                     body: &ast::Block,
                                     id: ast::NodeId,
-                                    param_substs: &'tcx Substs<'tcx>)
+                                    closure_substs: &'tcx ty::ClosureSubsts<'tcx>)
                                     -> Option<Block<'a, 'tcx>>
 {
+    let param_substs = closure_substs.func_substs;
+
     let ccx = match dest {
         Dest::SaveIn(bcx, _) => bcx.ccx(),
         Dest::Ignore(ccx) => ccx
@@ -204,10 +189,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     debug!("trans_closure_expr()");
 
     let closure_id = ast_util::local_def(id);
-    let llfn = get_or_create_declaration_if_closure(
-        ccx,
-        closure_id,
-        param_substs).unwrap();
+    let llfn = get_or_create_closure_declaration(ccx, closure_id, closure_substs);
 
     // Get the type of this closure. Use the current `param_substs` as
     // the closure substitutions. This makes sense because the closure
@@ -216,7 +198,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     // of the closure expression.
 
     let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
-    let function_type = infcx.closure_type(closure_id, param_substs);
+    let function_type = infcx.closure_type(closure_id, closure_substs);
 
     let freevars: Vec<ty::Freevar> =
         tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
@@ -226,7 +208,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     trans_closure(ccx,
                   decl,
                   body,
-                  llfn.val,
+                  llfn,
                   param_substs,
                   id,
                   &[],
@@ -269,20 +251,12 @@ 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<Ty<'tcx>>,
-                                      node: ExprOrMethodCall,
-                                      param_substs: &'tcx Substs<'tcx>,
+                                      substs: ty::ClosureSubsts<'tcx>,
                                       trait_closure_kind: ty::ClosureKind)
                                       -> ValueRef
 {
-    // The substitutions should have no type parameters remaining
-    // after passing through fulfill_obligation
-    let llfn = callee::trans_fn_ref_with_substs(ccx,
-                                                closure_def_id,
-                                                node,
-                                                param_substs,
-                                                substs.clone()).val;
+    // If this is a closure, redirect to it.
+    let llfn = get_or_create_closure_declaration(ccx, closure_def_id, &substs);
 
     // If the closure is a Fn closure, but a FnOnce is needed (etc),
     // then adapt the self type
@@ -290,7 +264,6 @@ 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)
@@ -299,8 +272,7 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
 fn trans_closure_adapter_shim<'a, 'tcx>(
     ccx: &'a CrateContext<'a, 'tcx>,
     closure_def_id: ast::DefId,
-    substs: Substs<'tcx>,
-    upvar_tys: Vec<Ty<'tcx>>,
+    substs: ty::ClosureSubsts<'tcx>,
     llfn_closure_kind: ty::ClosureKind,
     trait_closure_kind: ty::ClosureKind,
     llfn: ValueRef)
@@ -339,7 +311,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, upvar_tys, llfn)
+            trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn)
         }
         _ => {
             tcx.sess.bug(&format!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
@@ -352,8 +324,7 @@ fn trans_closure_adapter_shim<'a, 'tcx>(
 fn trans_fn_once_adapter_shim<'a, 'tcx>(
     ccx: &'a CrateContext<'a, 'tcx>,
     closure_def_id: ast::DefId,
-    substs: Substs<'tcx>,
-    upvar_tys: Vec<Ty<'tcx>>,
+    substs: ty::ClosureSubsts<'tcx>,
     llreffn: ValueRef)
     -> ValueRef
 {
@@ -367,12 +338,11 @@ 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, upvar_tys);
+    let closure_ty = tcx.mk_closure_from_closure_substs(closure_def_id, Box::new(substs.clone()));
     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.
-    let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, substs);
+    let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, &substs);
     sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
     let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
                                                                abi: abi,
@@ -402,7 +372,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
                       ast::DUMMY_NODE_ID,
                       false,
                       sig.output,
-                      substs,
+                      substs.func_substs,
                       None,
                       &block_arena);
     let mut bcx = init_function(&fcx, false, sig.output);
index 302ef68bddc7d9943fa756d24bcbbd3e76404d71..deab11332c809cb09e97d4973ba6c0f332ec1484 100644 (file)
@@ -882,11 +882,16 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
         },
         ast::ExprClosure(_, ref decl, ref body) => {
-            closure::trans_closure_expr(closure::Dest::Ignore(cx),
-                                        decl,
-                                        body,
-                                        e.id,
-                                        param_substs);
+            match ety.sty {
+                ty::TyClosure(_, ref substs) => {
+                    closure::trans_closure_expr(closure::Dest::Ignore(cx), decl,
+                                                body, e.id, substs);
+                }
+                _ =>
+                    cx.sess().span_bug(
+                        e.span,
+                        &format!("bad type for closure expr: {:?}", ety))
+            }
             C_null(type_of::type_of(cx, ety))
         },
         _ => cx.sess().span_bug(e.span,
index d0c6c0ab308c4bec0b52411366d6ffb721f6e4b0..66772e67755db5239b18c0df597acdc14416882f 100644 (file)
@@ -287,7 +287,7 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
                     }
                 }
             },
-            ty::TyClosure(def_id, substs, _) => {
+            ty::TyClosure(def_id, ref 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, ref 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::<Vec<_>>();
index a641302e53fab835c6dc31d44dbf19c069d6c594..0c77e74be38aa1f831bc8a0525ff17a2582694e0 100644 (file)
@@ -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, ref 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);
index f7ace78512013789af3369cb6748cf010e5f26c1..962803932b88b03361d671be9dfd79b6dadc6c40 100644 (file)
@@ -1146,8 +1146,14 @@ fn make_field(field_name: &str, expr: P<ast::Expr>) -> ast::Field {
                 SaveIn(lldest) => closure::Dest::SaveIn(bcx, lldest),
                 Ignore => closure::Dest::Ignore(bcx.ccx())
             };
-            closure::trans_closure_expr(dest, decl, body, expr.id, bcx.fcx.param_substs)
-                .unwrap_or(bcx)
+            let substs = match expr_ty(bcx, expr).sty {
+                ty::TyClosure(_, ref substs) => substs,
+                ref t =>
+                    bcx.tcx().sess.span_bug(
+                        expr.span,
+                        &format!("closure expr without closure type: {:?}", t)),
+            };
+            closure::trans_closure_expr(dest, decl, body, expr.id, substs).unwrap_or(bcx)
         }
         ast::ExprCall(ref f, ref args) => {
             if bcx.tcx().is_method_call(expr.id) {
index cf2a226db41eb45426a4d910683b07e108b3f7ec..4a549d9c24cdab5e0a31250e5430d2198eeae11e 100644 (file)
@@ -341,9 +341,6 @@ 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);
             Callee {
                 bcx: bcx,
@@ -642,15 +639,11 @@ 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);
                 vec![llfn].into_iter()
             }
index 955a301340519b84c4600732b49a42a5a990f731..4cca3b7582bfb0897a3d0ee13b380ec841bf424c 100644 (file)
@@ -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, ref substs) => {
             assert_eq!(def_id.krate, ast::LOCAL_CRATE);
 
             // Check whether this is a call to a closure where we
index f37177684d55219b35424c919cc93844d75c6291..38207354792ae783c4cb703b74e3cf0686c81798 100644 (file)
@@ -41,8 +41,7 @@ pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(),
     let dtor_predicates = tcx.lookup_predicates(drop_impl_did);
     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::TyStruct(self_type_did, self_to_impl_substs) => {
             try!(ensure_drop_params_and_item_params_correspond(tcx,
                                                                drop_impl_did,
                                                                dtor_generics,
index 8b9871428c4d12d78f06aa917d7da38bf5d1d174..a960123efc6b8172045ea9fefa1c0fe7a4ed8e3e 100644 (file)
@@ -288,7 +288,7 @@ fn assemble_probe(&mut self, self_ty: Ty<'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 @@ fn assemble_closure_candidates(&mut self,
         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,
             };
 
index 1c21813fc63bda63920dfb881851332d8324abef..ba89908bbe7e1689e9185159e0b3a4d9eb90f35e 100644 (file)
@@ -89,7 +89,6 @@
 use middle::implicator;
 use middle::mem_categorization as mc;
 use middle::region::CodeExtent;
-use middle::subst::Substs;
 use middle::traits;
 use middle::ty::{self, ReScope, Ty, MethodCall, HasTypeFlags};
 use middle::infer::{self, GenericKind};
@@ -1444,7 +1443,7 @@ fn closure_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                   origin: infer::SubregionOrigin<'tcx>,
                                   region: ty::Region,
                                   def_id: ast::DefId,
-                                  substs: &'tcx Substs<'tcx>) {
+                                  substs: &'tcx ty::ClosureSubsts<'tcx>) {
     debug!("closure_must_outlive(region={:?}, def_id={:?}, substs={:?})",
            region, def_id, substs);
 
index 0878ca1c29562c66ed9342d3c6fa820776543deb..2b800bd9a441f738c3ecdbaf93a5d059b4eede9e 100644 (file)
@@ -312,7 +312,7 @@ fn populate_destructor_table(&self) {
             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());