about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJared Roesch <roeschinc@gmail.com>2015-06-27 22:04:15 -0700
committerJared Roesch <roeschinc@gmail.com>2015-06-30 02:40:17 -0700
commitfb295a60b37fc2bc60fab29fad1863a174fa587c (patch)
tree980d570d48b321d96e3d940919813c4f9c5bcf4f
parent0f13a3f361384c278041c95e9a2ba9975e6cde71 (diff)
downloadrust-fb295a60b37fc2bc60fab29fad1863a174fa587c.tar.gz
rust-fb295a60b37fc2bc60fab29fad1863a174fa587c.zip
Remove NormalizingClosureTyper
-rw-r--r--src/librustc/middle/infer/mod.rs164
-rw-r--r--src/librustc_trans/trans/adt.rs9
-rw-r--r--src/librustc_trans/trans/attributes.rs5
-rw-r--r--src/librustc_trans/trans/base.rs5
-rw-r--r--src/librustc_trans/trans/closure.rs10
-rw-r--r--src/librustc_trans/trans/common.rs81
-rw-r--r--src/librustc_trans/trans/debuginfo/metadata.rs11
-rw-r--r--src/librustc_trans/trans/declare.rs6
-rw-r--r--src/librustc_trans/trans/monomorphize.rs7
9 files changed, 204 insertions, 94 deletions
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index 04c29aaeb5a..91fee77f0a7 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -19,6 +19,7 @@ pub use self::TypeOrigin::*;
 pub use self::ValuePairs::*;
 pub use self::fixup_err::*;
 pub use middle::ty::IntVarValue;
+use middle::ty::ClosureTyper;
 pub use self::freshen::TypeFreshener;
 pub use self::region_inference::GenericKind;
 
@@ -29,7 +30,8 @@ use middle::region::CodeExtent;
 use middle::subst;
 use middle::subst::Substs;
 use middle::subst::Subst;
-use middle::traits;
+use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation,
+                     SelectionContext, ObligationCause};
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
 use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
@@ -39,7 +41,7 @@ use std::cell::{RefCell, Ref};
 use std::fmt;
 use syntax::ast;
 use syntax::codemap;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
 use util::nodemap::{FnvHashMap, NodeMap};
 
 use self::combine::CombineFields;
@@ -354,6 +356,14 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
     }
 }
 
+pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
+                                        tables: &'a RefCell<ty::Tables<'tcx>>)
+                                        -> InferCtxt<'a, 'tcx> {
+    let mut infcx = new_infer_ctxt(tcx, tables, None, false);
+    infcx.normalize = true;
+    infcx
+}
+
 /// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and
 /// returns ty::err.
 pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
@@ -557,7 +567,8 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
             // the substitutions in `substs` are already monomorphized,
             // but we still must normalize associated types
             // normalize_associated_type(self.param_env.tcx, &closure_ty)
-            panic!("see issue 26597: fufillment context refactor must occur")
+            normalize_associated_type(&self.tcx, &closure_ty)
+            // panic!("see issue 26597: fufillment context refactor must occur")
         } else {
             closure_ty
         }
@@ -579,13 +590,158 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
             // the substitutions in `substs` are already monomorphized,
             // but we still must normalize associated types
             // monomorphize::normalize_associated_type(self.param_env.tcx, &result)
-            panic!("see issue 26597: fufillment context refactor must occur")
+            // panic!("see issue 26597: fufillment context refactor must occur")
+            normalize_associated_type(&self.tcx, &result)
         } else {
             result
         }
     }
 }
 
+pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
+    where T : TypeFoldable<'tcx> + HasTypeFlags
+{
+    debug!("normalize_associated_type(t={:?})", value);
+
+    let value = erase_regions(tcx, value);
+
+    if !value.has_projection_types() {
+        return value;
+    }
+
+    let infcx = new_infer_ctxt(tcx, &tcx.tables, None, true);
+    let mut selcx = traits::SelectionContext::new(&infcx, &infcx);
+    let cause = traits::ObligationCause::dummy();
+    let traits::Normalized { value: result, obligations } =
+        traits::normalize(&mut selcx, cause, &value);
+
+    debug!("normalize_associated_type: result={:?} obligations={:?}",
+           result,
+           obligations);
+
+    let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
+
+    for obligation in obligations {
+        fulfill_cx.register_predicate_obligation(&infcx, obligation);
+    }
+
+    let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result);
+
+    result
+}
+
+pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
+                                                infcx: &InferCtxt<'a,'tcx>,
+                                                fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+                                                result: &T)
+                                                -> T
+    where T : TypeFoldable<'tcx>
+{
+    match drain_fulfillment_cx(infcx, fulfill_cx, result) {
+        Ok(v) => v,
+        Err(errors) => {
+            infcx.tcx.sess.span_bug(
+                span,
+                &format!("Encountered errors `{:?}` fulfilling during trans",
+                         errors));
+        }
+    }
+}
+
+/// Finishes processes any obligations that remain in the fulfillment
+/// context, and then "freshens" and returns `result`. This is
+/// primarily used during normalization and other cases where
+/// processing the obligations in `fulfill_cx` may cause type
+/// inference variables that appear in `result` to be unified, and
+/// hence we need to process those obligations to get the complete
+/// picture of the type.
+pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
+                                       fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+                                       result: &T)
+                                       -> Result<T,Vec<traits::FulfillmentError<'tcx>>>
+    where T : TypeFoldable<'tcx>
+{
+    debug!("drain_fulfillment_cx(result={:?})",
+           result);
+    // this is stupid but temporary
+    let typer: &ClosureTyper<'tcx> = infcx;
+    // 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, typer) {
+        Ok(()) => { }
+        Err(errors) => {
+            return Err(errors);
+        }
+    }
+
+    // Use freshen to simultaneously replace all type variables with
+    // their bindings and replace all regions with 'static.  This is
+    // sort of overkill because we do not expect there to be any
+    // unbound type variables, hence no `TyFresh` types should ever be
+    // inserted.
+    Ok(result.fold_with(&mut infcx.freshener()))
+}
+
+/// Returns an equivalent value with all free regions removed (note
+/// that late-bound regions remain, because they are important for
+/// subtyping, but they are anonymized and normalized as well). This
+/// is a stronger, caching version of `ty_fold::erase_regions`.
+pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
+    where T : TypeFoldable<'tcx>
+{
+    let value1 = value.fold_with(&mut RegionEraser(cx));
+    debug!("erase_regions({:?}) = {:?}",
+           value, value1);
+    return value1;
+
+    struct RegionEraser<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>);
+
+    impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
+        fn tcx(&self) -> &ty::ctxt<'tcx> { self.0 }
+
+        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+            match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
+                None => {}
+                Some(u) => return u
+            }
+
+            let t_norm = ty_fold::super_fold_ty(self, ty);
+            self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
+            return t_norm;
+        }
+
+        fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+            where T : TypeFoldable<'tcx>
+        {
+            let u = self.tcx().anonymize_late_bound_regions(t);
+            ty_fold::super_fold_binder(self, &u)
+        }
+
+        fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+            // because late-bound regions affect subtyping, we can't
+            // erase the bound/free distinction, but we can replace
+            // all free regions with 'static.
+            //
+            // Note that we *CAN* replace early-bound regions -- the
+            // type system never "sees" those, they get substituted
+            // away. In trans, they will always be erased to 'static
+            // whenever a substitution occurs.
+            match r {
+                ty::ReLateBound(..) => r,
+                _ => ty::ReStatic
+            }
+        }
+
+        fn fold_substs(&mut self,
+                       substs: &subst::Substs<'tcx>)
+                       -> subst::Substs<'tcx> {
+            subst::Substs { regions: subst::ErasedRegions,
+                            types: substs.types.fold_with(self) }
+        }
+    }
+}
+
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
         t.fold_with(&mut self.freshener())
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index 3ce76167e85..b96dcf940a8 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -50,6 +50,7 @@ use std::rc::Rc;
 use llvm::{ValueRef, True, IntEQ, IntNE};
 use back::abi::FAT_PTR_ADDR;
 use middle::subst;
+use middle::infer;
 use middle::ty::{self, Ty, ClosureTyper};
 use middle::ty::Disr;
 use syntax::ast;
@@ -223,8 +224,8 @@ 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) => {
-            let typer = NormalizingClosureTyper::new(cx.tcx());
-            let upvars = typer.closure_upvars(def_id, substs).unwrap();
+            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<_>>();
             Univariant(mk_struct(cx, &upvar_types[..], false, t), 0)
         }
@@ -443,8 +444,8 @@ 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) => {
-            let typer = NormalizingClosureTyper::new(tcx);
-            let upvars = typer.closure_upvars(def_id, substs).unwrap();
+            let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+            let upvars = infcx.closure_upvars(def_id, substs).unwrap();
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
 
             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 b432560bc4b..fd704ed2d37 100644
--- a/src/librustc_trans/trans/attributes.rs
+++ b/src/librustc_trans/trans/attributes.rs
@@ -12,6 +12,7 @@
 use libc::{c_uint, c_ulonglong};
 use llvm::{self, ValueRef, AttrHelper};
 use middle::ty::{self, ClosureTyper};
+use middle::infer;
 use session::config::NoDebugInfo;
 use syntax::abi;
 use syntax::ast;
@@ -145,8 +146,8 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
     let (fn_sig, abi, env_ty) = match fn_type.sty {
         ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None),
         ty::TyClosure(closure_did, substs) => {
-            let typer = common::NormalizingClosureTyper::new(ccx.tcx());
-            function_type = typer.closure_type(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);
             (&function_type.sig, abi::RustCall, Some(self_type))
         }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 0cd6bbad03a..088df7288be 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -37,6 +37,7 @@ use llvm;
 use metadata::{csearch, encoder, loader};
 use middle::astencode;
 use middle::cfg;
+use middle::infer;
 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::weak_lang_items;
 use middle::subst::Substs;
@@ -434,8 +435,8 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
       }
       ty::TyClosure(def_id, substs) => {
           let repr = adt::represent_type(cx.ccx(), t);
-          let typer = common::NormalizingClosureTyper::new(cx.tcx());
-          let upvars = typer.closure_upvars(def_id, substs).unwrap();
+          let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+          let upvars = infcx.closure_upvars(def_id, substs).unwrap();
           for (i, upvar) in upvars.iter().enumerate() {
               let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
               cx = f(cx, llupvar, upvar.ty);
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index b6378062855..c9bab6861ca 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::mem_categorization::Typer;
+use middle::infer;
 use trans::adt;
 use trans::attributes;
 use trans::base::*;
@@ -214,8 +215,9 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     // takes the same set of type arguments as the enclosing fn, and
     // this function (`trans_closure`) is invoked at the point
     // of the closure expression.
-    let typer = NormalizingClosureTyper::new(tcx);
-    let function_type = typer.closure_type(closure_id, param_substs);
+
+    let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
+    let function_type = infcx.closure_type(closure_id, param_substs);
 
     let freevars: Vec<ty::Freevar> =
         tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
@@ -358,7 +360,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
            ccx.tn().val_to_string(llreffn));
 
     let tcx = ccx.tcx();
-    let typer = NormalizingClosureTyper::new(tcx);
+    let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
 
     // Find a version of the closure type. Substitute static for the
     // region since it doesn't really matter.
@@ -367,7 +369,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     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 } = typer.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,
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 92aeb9f7b72..1fc68790db0 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -24,6 +24,7 @@ use middle::infer;
 use middle::lang_items::LangItem;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::Typer;
+use middle::ty::ClosureTyper;
 use middle::region;
 use middle::subst::{self, Substs};
 use trans::base;
@@ -642,8 +643,8 @@ impl<'blk, 'tcx> ty::ClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
                     def_id: ast::DefId)
                     -> Option<ty::ClosureKind>
     {
-        let typer = NormalizingClosureTyper::new(self.tcx());
-        typer.closure_kind(def_id)
+        let infcx = infer::normalizing_infer_ctxt(self.tcx(), &self.tcx().tables);
+        infcx.closure_kind(def_id)
     }
 
     fn closure_type(&self,
@@ -651,8 +652,8 @@ impl<'blk, 'tcx> ty::ClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
                     substs: &subst::Substs<'tcx>)
                     -> ty::ClosureTy<'tcx>
     {
-        let typer = NormalizingClosureTyper::new(self.tcx());
-        typer.closure_type(def_id, substs)
+        let infcx = infer::normalizing_infer_ctxt(self.tcx(), &self.tcx().tables);
+        infcx.closure_type(def_id, substs)
     }
 
     fn closure_upvars(&self,
@@ -660,8 +661,8 @@ impl<'blk, 'tcx> ty::ClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
                       substs: &Substs<'tcx>)
                       -> Option<Vec<ty::ClosureUpvar<'tcx>>>
     {
-        let typer = NormalizingClosureTyper::new(self.tcx());
-        typer.closure_upvars(def_id, substs)
+        let infcx = infer::new_infer_ctxt(self.tcx(), &self.tcx().tables, None, true);
+        infcx.closure_upvars(def_id, substs)
     }
 }
 
@@ -957,12 +958,12 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            trait_ref, trait_ref.def_id());
 
     tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    let typer = NormalizingClosureTyper::new(tcx);
-    let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+    let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+    let mut selcx = traits::SelectionContext::new(&infcx, &infcx);
+
     let obligation =
         traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID),
                                 trait_ref.to_poly_trait_predicate());
@@ -1019,9 +1020,8 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            predicates);
 
     let tcx = ccx.tcx();
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
-    let typer = NormalizingClosureTyper::new(tcx);
-    let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
+    let mut selcx = traits::SelectionContext::new(&infcx, &infcx);
     let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
     let cause = traits::ObligationCause::dummy();
     let traits::Normalized { value: predicates, obligations } =
@@ -1036,57 +1036,6 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
 }
 
-// NOTE: here is another use of parameter environment without an InferCtxt,
-// this is obviously related to the typer interface requiring a parameter env.
-// We should pay attention to this when refactoring
-// - @jroesch
-pub struct NormalizingClosureTyper<'a,'tcx:'a> {
-    param_env: ty::ParameterEnvironment<'a, 'tcx>
-}
-
-impl<'a,'tcx> NormalizingClosureTyper<'a,'tcx> {
-    pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingClosureTyper<'a,'tcx> {
-        // Parameter environment is used to give details about type parameters,
-        // but since we are in trans, everything is fully monomorphized.
-        NormalizingClosureTyper { param_env: tcx.empty_parameter_environment() }
-    }
-}
-
-impl<'a,'tcx> ty::ClosureTyper<'tcx> for NormalizingClosureTyper<'a,'tcx> {
-    fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
-        &self.param_env
-    }
-
-    fn closure_kind(&self,
-                    def_id: ast::DefId)
-                    -> Option<ty::ClosureKind>
-    {
-        self.param_env.closure_kind(def_id)
-    }
-
-    fn 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.param_env.tcx.closure_type(def_id, substs);
-        monomorphize::normalize_associated_type(self.param_env.tcx, &closure_ty)
-    }
-
-    fn closure_upvars(&self,
-                      def_id: ast::DefId,
-                      substs: &Substs<'tcx>)
-                      -> Option<Vec<ty::ClosureUpvar<'tcx>>>
-    {
-        // the substitutions in `substs` are already monomorphized,
-        // but we still must normalize associated types
-        let result = self.param_env.closure_upvars(def_id, substs);
-        monomorphize::normalize_associated_type(self.param_env.tcx, &result)
-    }
-}
-
 pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
                                                 infcx: &infer::InferCtxt<'a,'tcx>,
                                                 fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
@@ -1120,12 +1069,12 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>,
 {
     debug!("drain_fulfillment_cx(result={:?})",
            result);
-
+    // this is stupid but temporary
+    let typer: &ClosureTyper<'tcx> = infcx;
     // 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.
-    let typer = NormalizingClosureTyper::new(infcx.tcx);
-    match fulfill_cx.select_all_or_error(infcx, &typer) {
+    match fulfill_cx.select_all_or_error(infcx, typer) {
         Ok(()) => { }
         Err(errors) => {
             return Err(errors);
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
index 1fbbf0763aa..12892c87b46 100644
--- a/src/librustc_trans/trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/trans/debuginfo/metadata.rs
@@ -26,9 +26,10 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
 use metadata::csearch;
 use middle::pat_util;
 use middle::subst::{self, Substs};
+use middle::infer;
 use rustc::ast_map;
 use trans::{type_of, adt, machine, monomorphize};
-use trans::common::{self, CrateContext, FunctionContext, NormalizingClosureTyper, Block};
+use trans::common::{self, CrateContext, FunctionContext, Block};
 use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
 use trans::type_::Type;
 use middle::ty::{self, Ty, ClosureTyper};
@@ -287,8 +288,8 @@ impl<'tcx> TypeMap<'tcx> {
                 }
             },
             ty::TyClosure(def_id, substs) => {
-                let typer = NormalizingClosureTyper::new(cx.tcx());
-                let closure_ty = typer.closure_type(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,
                                                         closure_ty,
                                                         &mut unique_type_id);
@@ -796,8 +797,8 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
         }
         ty::TyClosure(def_id, substs) => {
-            let typer = NormalizingClosureTyper::new(cx.tcx());
-            let sig = typer.closure_type(def_id, substs).sig;
+            let infcx = infer::normalizing_infer_ctxt(cx.tcx(), &cx.tcx().tables);
+            let sig = infcx.closure_type(def_id, substs).sig;
             subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
         }
         ty::TyStruct(def_id, substs) => {
diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs
index 646ca6733c3..0eaaaaa5b34 100644
--- a/src/librustc_trans/trans/declare.rs
+++ b/src/librustc_trans/trans/declare.rs
@@ -21,10 +21,10 @@
 //! * When in doubt, define.
 use llvm::{self, ValueRef};
 use middle::ty::{self, ClosureTyper};
+use middle::infer;
 use syntax::abi;
 use trans::attributes;
 use trans::base;
-use trans::common;
 use trans::context::CrateContext;
 use trans::monomorphize;
 use trans::type_::Type;
@@ -117,8 +117,8 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
             (&f.sig, f.abi, None)
         }
         ty::TyClosure(closure_did, substs) => {
-            let typer = common::NormalizingClosureTyper::new(ccx.tcx());
-            function_type = typer.closure_type(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);
             let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type);
             debug!("declare_rust_fn function_type={:?} self_type={:?}",
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index b88251c69a0..b297a731d29 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -324,9 +324,8 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
     // FIXME(#20304) -- cache
     // NOTE: @jroesch
     // Here is of an example where we do not use a param_env but use a typer instead.
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
-    let typer = NormalizingClosureTyper::new(tcx);
-    let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+    let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables);
+    let mut selcx = traits::SelectionContext::new(&infcx, &infcx);
     let cause = traits::ObligationCause::dummy();
     let traits::Normalized { value: result, obligations } =
         traits::normalize(&mut selcx, cause, &value);
@@ -336,7 +335,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
            obligations);
 
     let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
-    
+
     for obligation in obligations {
         fulfill_cx.register_predicate_obligation(&infcx, obligation);
     }