about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-01-01 17:58:57 -0500
committerNiko Matsakis <niko@alum.mit.edu>2015-01-01 18:48:26 -0500
commit1e3214ba330c81f93b69ac5f4e3cfee73271e4c4 (patch)
treef24112d4d10e311e036ced1c453bdc5697061877 /src
parent78f848cde5fd8741faf6306801766ae2a937db35 (diff)
downloadrust-1e3214ba330c81f93b69ac5f4e3cfee73271e4c4.tar.gz
rust-1e3214ba330c81f93b69ac5f4e3cfee73271e4c4.zip
Normalize the associated types in closure and closure upvar types.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/traits/select.rs5
-rw-r--r--src/librustc/middle/ty.rs40
-rw-r--r--src/librustc/middle/ty_fold.rs10
-rw-r--r--src/librustc_trans/trans/base.rs34
-rw-r--r--src/librustc_trans/trans/closure.rs21
-rw-r--r--src/librustc_trans/trans/common.rs60
-rw-r--r--src/librustc_trans/trans/debuginfo.rs16
-rw-r--r--src/librustc_trans/trans/monomorphize.rs3
8 files changed, 145 insertions, 44 deletions
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index c5ad8c3b230..f9dced088f8 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -1781,6 +1781,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                substs.repr(self.tcx()));
 
         let closure_type = self.closure_typer.unboxed_closure_type(closure_def_id, substs);
+
+        debug!("confirm_unboxed_closure_candidate: closure_def_id={} closure_type={}",
+               closure_def_id.repr(self.tcx()),
+               closure_type.repr(self.tcx()));
+
         let closure_sig = &closure_type.sig;
         let arguments_tuple = closure_sig.0.inputs[0];
         let trait_substs =
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index cea98ff20cd..a83f03c2c16 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -5665,7 +5665,7 @@ pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
     }).collect()
 }
 
-#[deriving(Copy)]
+#[deriving(Copy, Clone)]
 pub struct UnboxedClosureUpvar<'tcx> {
     pub def: def::Def,
     pub span: Span,
@@ -7099,12 +7099,30 @@ pub trait HasProjectionTypes {
     fn has_projection_types(&self) -> bool;
 }
 
+impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for Vec<T> {
+    fn has_projection_types(&self) -> bool {
+        self.iter().any(|p| p.has_projection_types())
+    }
+}
+
 impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for VecPerParamSpace<T> {
     fn has_projection_types(&self) -> bool {
         self.iter().any(|p| p.has_projection_types())
     }
 }
 
+impl<'tcx> HasProjectionTypes for ClosureTy<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.sig.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for UnboxedClosureUpvar<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.ty.has_projection_types()
+    }
+}
+
 impl<'tcx> HasProjectionTypes for ty::GenericBounds<'tcx> {
     fn has_projection_types(&self) -> bool {
         self.predicates.has_projection_types()
@@ -7304,3 +7322,23 @@ impl ReferencesError for Region
         false
     }
 }
+
+impl<'tcx> Repr<'tcx> for ClosureTy<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("ClosureTy({},{},{},{},{},{})",
+                self.unsafety,
+                self.onceness,
+                self.store,
+                self.bounds.repr(tcx),
+                self.sig.repr(tcx),
+                self.abi)
+    }
+}
+
+impl<'tcx> Repr<'tcx> for UnboxedClosureUpvar<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("UnboxedClosureUpvar({},{})",
+                self.def.repr(tcx),
+                self.ty.repr(tcx))
+    }
+}
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 1e7605c0f17..83d2f6fb0e6 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -532,6 +532,16 @@ impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnboxedClosureUpvar<'tcx> {
+        ty::UnboxedClosureUpvar {
+            def: self.def,
+            span: self.span,
+            ty: self.ty.fold_with(folder),
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // "super" routines: these are the default implementations for TypeFolder.
 //
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index b4dac456536..18155d75680 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -43,7 +43,7 @@ use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::subst;
 use middle::weak_lang_items;
 use middle::subst::{Subst, Substs};
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, Ty, UnboxedClosureTyper};
 use session::config::{mod, NoDebugInfo, FullDebugInfo};
 use session::Session;
 use trans::_match;
@@ -257,12 +257,12 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>,
 }
 
 pub fn self_type_for_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                     closure_id: ast::DefId,
-                                     fn_ty: Ty<'tcx>)
-                                     -> Ty<'tcx> {
-    let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
-    let unboxed_closure = &(*unboxed_closures)[closure_id];
-    match unboxed_closure.kind {
+                                               closure_id: ast::DefId,
+                                               fn_ty: Ty<'tcx>)
+                                               -> Ty<'tcx>
+{
+    let unboxed_closure_kind = ccx.tcx().unboxed_closure_kind(closure_id);
+    match unboxed_closure_kind {
         ty::FnUnboxedClosureKind => {
             ty::mk_imm_rptr(ccx.tcx(), ccx.tcx().mk_region(ty::ReStatic), fn_ty)
         }
@@ -291,13 +291,15 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             (f.sig.0.inputs.clone(), f.sig.0.output, f.abi, Some(Type::i8p(ccx)))
         }
         ty::ty_unboxed_closure(closure_did, _, substs) => {
-            let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
-            let unboxed_closure = &(*unboxed_closures)[closure_did];
-            let function_type = unboxed_closure.closure_type.clone();
+            let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx());
+            let function_type = typer.unboxed_closure_type(closure_did, substs);
             let self_type = self_type_for_unboxed_closure(ccx, closure_did, fn_ty);
             let llenvironment_type = type_of_explicit_arg(ccx, self_type);
-            (function_type.sig.0.inputs.iter().map(|t| t.subst(ccx.tcx(), substs)).collect(),
-             function_type.sig.0.output.subst(ccx.tcx(), substs),
+            debug!("decl_rust_fn: function_type={} self_type={}",
+                   function_type.repr(ccx.tcx()),
+                   self_type.repr(ccx.tcx()));
+            (function_type.sig.0.inputs,
+             function_type.sig.0.output,
              RustCall,
              Some(llenvironment_type))
         }
@@ -2436,11 +2438,9 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
         ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true),
         ty::ty_bare_fn(_, ref f) => (f.sig.clone(), f.abi, false),
         ty::ty_unboxed_closure(closure_did, _, substs) => {
-            let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
-            let ref function_type = (*unboxed_closures)[closure_did]
-                                                    .closure_type;
-
-            (function_type.sig.subst(ccx.tcx(), substs), RustCall, true)
+            let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx());
+            let function_type = typer.unboxed_closure_type(closure_did, substs);
+            (function_type.sig, RustCall, true)
         }
         _ => ccx.sess().bug("expected closure or function.")
     };
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index 3723ad07a36..93a5b54fde3 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -22,11 +22,11 @@ use trans::common::*;
 use trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
 use trans::debuginfo;
 use trans::expr;
-use trans::monomorphize::MonoId;
+use trans::monomorphize::{mod, MonoId};
 use trans::type_of::*;
 use trans::type_::Type;
-use middle::ty::{mod, Ty};
-use middle::subst::{Subst, Substs};
+use middle::ty::{mod, Ty, UnboxedClosureTyper};
+use middle::subst::{Substs};
 use session::config::FullDebugInfo;
 use util::ppaux::Repr;
 use util::ppaux::ty_to_string;
@@ -464,7 +464,7 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
     }
 
     let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node);
-    let function_type = function_type.subst(bcx.tcx(), substs);
+    let function_type = monomorphize::apply_param_substs(bcx.tcx(), substs, &function_type);
 
     // Normalize type so differences in regions and typedefs don't cause
     // duplicate declarations
@@ -511,7 +511,8 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
                              body: &ast::Block,
                              id: ast::NodeId,
                              dest: expr::Dest)
-                             -> Block<'blk, 'tcx> {
+                             -> Block<'blk, 'tcx>
+{
     let _icx = push_ctxt("closure::trans_unboxed_closure");
 
     debug!("trans_unboxed_closure()");
@@ -522,9 +523,13 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
         closure_id,
         bcx.fcx.param_substs).unwrap();
 
-    let function_type = (*bcx.tcx().unboxed_closures.borrow())[closure_id]
-                                                              .closure_type
-                                                              .clone();
+    // Get the type of this closure. Use the current `param_substs` as
+    // the closure substitutions. This makes sense because the closure
+    // takes the same set of type arguments as the enclosing fn, and
+    // this function (`trans_unboxed_closure`) is invoked at the point
+    // of the closure expression.
+    let typer = NormalizingUnboxedClosureTyper::new(bcx.tcx());
+    let function_type = typer.unboxed_closure_type(closure_id, bcx.fcx.param_substs);
     let function_type = ty::mk_closure(bcx.tcx(), function_type);
 
     let freevars: Vec<ty::Freevar> =
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 8d1322da635..aa882240880 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -632,7 +632,8 @@ impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
                             def_id: ast::DefId)
                             -> ty::UnboxedClosureKind
     {
-        self.tcx().unboxed_closure_kind(def_id)
+        let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+        typer.unboxed_closure_kind(def_id)
     }
 
     fn unboxed_closure_type(&self,
@@ -640,9 +641,8 @@ impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
                             substs: &subst::Substs<'tcx>)
                             -> ty::ClosureTy<'tcx>
     {
-        // the substitutions in `substs` are already monomorphized, so we can
-        // ignore `param_substs`
-        self.tcx().unboxed_closure_type(def_id, substs)
+        let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+        typer.unboxed_closure_type(def_id, substs)
     }
 
     fn unboxed_closure_upvars(&self,
@@ -650,9 +650,8 @@ impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
                               substs: &Substs<'tcx>)
                               -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
     {
-        // the substitutions in `substs` are already monomorphized, so we can
-        // ignore `param_substs`
-        ty::unboxed_closure_upvars(self.tcx(), def_id, substs)
+        let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+        typer.unboxed_closure_upvars(def_id, substs)
     }
 }
 
@@ -948,7 +947,8 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    let mut selcx = traits::SelectionContext::new(&infcx, &param_env, tcx);
+    let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
+    let mut selcx = traits::SelectionContext::new(&infcx, &param_env, &typer);
     let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
                                              trait_ref.to_poly_trait_predicate());
     let selection = match selcx.select(&obligation) {
@@ -992,6 +992,47 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     vtable
 }
 
+pub struct NormalizingUnboxedClosureTyper<'a,'tcx:'a> {
+    tcx: &'a ty::ctxt<'tcx>
+}
+
+impl<'a,'tcx> NormalizingUnboxedClosureTyper<'a,'tcx> {
+    pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingUnboxedClosureTyper<'a,'tcx> {
+        NormalizingUnboxedClosureTyper { tcx: tcx }
+    }
+}
+
+impl<'a,'tcx> ty::UnboxedClosureTyper<'tcx> for NormalizingUnboxedClosureTyper<'a,'tcx> {
+    fn unboxed_closure_kind(&self,
+                            def_id: ast::DefId)
+                            -> ty::UnboxedClosureKind
+    {
+        self.tcx.unboxed_closure_kind(def_id)
+    }
+
+    fn unboxed_closure_type(&self,
+                            def_id: ast::DefId,
+                            substs: &subst::Substs<'tcx>)
+                            -> ty::ClosureTy<'tcx>
+    {
+        // the substitutions in `substs` are already monomorphized,
+        // but we still must normalize associated types
+        let closure_ty = self.tcx.unboxed_closure_type(def_id, substs);
+        monomorphize::normalize_associated_type(self.tcx, &closure_ty)
+    }
+
+    fn unboxed_closure_upvars(&self,
+                              def_id: ast::DefId,
+                              substs: &Substs<'tcx>)
+                              -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
+    {
+        // the substitutions in `substs` are already monomorphized,
+        // but we still must normalize associated types
+        let result = ty::unboxed_closure_upvars(self.tcx, def_id, substs);
+        monomorphize::normalize_associated_type(self.tcx, &result)
+    }
+}
+
 pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
                                        infcx: &infer::InferCtxt<'a,'tcx>,
                                        param_env: &ty::ParameterEnvironment<'tcx>,
@@ -1006,7 +1047,8 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
     // In principle, we only need to do this so long as `result`
     // contains unbound type parameters. It could be a slight
     // optimization to stop iterating early.
-    match fulfill_cx.select_all_or_error(infcx, param_env, infcx.tcx) {
+    let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
+    match fulfill_cx.select_all_or_error(infcx, param_env, &typer) {
         Ok(()) => { }
         Err(errors) => {
             if errors.iter().all(|e| e.is_overflow()) {
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index bce446b7412..c651255226b 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -194,13 +194,13 @@ use llvm;
 use llvm::{ModuleRef, ContextRef, ValueRef};
 use llvm::debuginfo::*;
 use metadata::csearch;
-use middle::subst::{mod, Subst, Substs};
+use middle::subst::{mod, Substs};
 use trans::{mod, adt, machine, type_of};
 use trans::common::*;
 use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
 use trans::monomorphize;
 use trans::type_::Type;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, Ty, UnboxedClosureTyper};
 use middle::pat_util;
 use session::config::{mod, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
@@ -470,9 +470,9 @@ impl<'tcx> TypeMap<'tcx> {
                                                         closure_ty.clone(),
                                                         &mut unique_type_id);
             },
-            ty::ty_unboxed_closure(ref def_id, _, substs) => {
-                let closure_ty = cx.tcx().unboxed_closures.borrow()
-                                   .get(def_id).unwrap().closure_type.subst(cx.tcx(), substs);
+            ty::ty_unboxed_closure(def_id, _, substs) => {
+                let typer = NormalizingUnboxedClosureTyper::new(cx.tcx());
+                let closure_ty = typer.unboxed_closure_type(def_id, substs);
                 self.get_unique_type_id_of_closure_type(cx,
                                                         closure_ty,
                                                         &mut unique_type_id);
@@ -3020,9 +3020,9 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::ty_closure(ref closurety) => {
             subroutine_type_metadata(cx, unique_type_id, &closurety.sig, usage_site_span)
         }
-        ty::ty_unboxed_closure(ref def_id, _, substs) => {
-            let sig = cx.tcx().unboxed_closures.borrow()
-                        .get(def_id).unwrap().closure_type.sig.subst(cx.tcx(), substs);
+        ty::ty_unboxed_closure(def_id, _, substs) => {
+            let typer = NormalizingUnboxedClosureTyper::new(cx.tcx());
+            let sig = typer.unboxed_closure_type(def_id, substs).sig;
             subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
         }
         ty::ty_struct(def_id, substs) => {
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index 7646aa086eb..7c8ba08d987 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -323,7 +323,8 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
 
     let infcx = infer::new_infer_ctxt(tcx);
     let param_env = ty::empty_parameter_environment();
-    let mut selcx = traits::SelectionContext::new(&infcx, &param_env, tcx);
+    let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
+    let mut selcx = traits::SelectionContext::new(&infcx, &param_env, &typer);
     let cause = traits::ObligationCause::dummy();
     let traits::Normalized { value: result, obligations } =
         traits::normalize(&mut selcx, cause, value);