about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTyler Mandry <tmandry@gmail.com>2018-04-24 21:45:49 -0500
committerTyler Mandry <tmandry@gmail.com>2018-04-24 22:12:07 -0500
commit98546f8b265c7d8dc2346d8bfce3d277dbc3fd5d (patch)
treef0445622107e91f8190aef47d83b8c6e33651ea8
parent190a6c41cf2afdb11e81545846f2639ee96998e8 (diff)
downloadrust-98546f8b265c7d8dc2346d8bfce3d277dbc3fd5d.tar.gz
rust-98546f8b265c7d8dc2346d8bfce3d277dbc3fd5d.zip
Make Binder's field private and clean up its usage
-rw-r--r--src/librustc/ich/impls_ty.rs3
-rw-r--r--src/librustc/infer/canonical.rs6
-rw-r--r--src/librustc/infer/combine.rs4
-rw-r--r--src/librustc/infer/error_reporting/mod.rs2
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs6
-rw-r--r--src/librustc/infer/sub.rs2
-rw-r--r--src/librustc/traits/error_reporting.rs12
-rw-r--r--src/librustc/traits/mod.rs4
-rw-r--r--src/librustc/traits/object_safety.rs8
-rw-r--r--src/librustc/traits/project.rs69
-rw-r--r--src/librustc/traits/select.rs96
-rw-r--r--src/librustc/traits/util.rs8
-rw-r--r--src/librustc/ty/_match.rs2
-rw-r--r--src/librustc/ty/fold.rs4
-rw-r--r--src/librustc/ty/instance.rs2
-rw-r--r--src/librustc/ty/mod.rs59
-rw-r--r--src/librustc/ty/relate.rs6
-rw-r--r--src/librustc/ty/structural_impls.rs6
-rw-r--r--src/librustc/ty/sty.rs44
-rw-r--r--src/librustc/ty/util.rs9
-rw-r--r--src/librustc/ty/wf.rs5
-rw-r--r--src/librustc/util/ppaux.rs6
-rw-r--r--src/librustc_driver/test.rs2
-rw-r--r--src/librustc_lint/builtin.rs2
-rw-r--r--src/librustc_mir/monomorphize/mod.rs2
-rw-r--r--src/librustc_traits/util.rs4
-rw-r--r--src/librustc_trans/context.rs2
-rw-r--r--src/librustc_trans/intrinsic.rs4
-rw-r--r--src/librustc_typeck/astconv.rs18
-rw-r--r--src/librustc_typeck/check/callee.rs2
-rw-r--r--src/librustc_typeck/check/closure.rs10
-rw-r--r--src/librustc_typeck/check/coercion.rs3
-rw-r--r--src/librustc_typeck/check/compare_method.rs14
-rw-r--r--src/librustc_typeck/check/generator_interior.rs2
-rw-r--r--src/librustc_typeck/check/intrinsic.rs4
-rw-r--r--src/librustc_typeck/check/method/confirm.rs4
-rw-r--r--src/librustc_typeck/check/method/mod.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/librustc_typeck/collect.rs10
-rw-r--r--src/librustc_typeck/lib.rs4
-rw-r--r--src/librustc_typeck/outlives/implicit_infer.rs4
-rw-r--r--src/librustc_typeck/outlives/mod.rs4
-rw-r--r--src/librustc_typeck/variance/constraints.rs10
-rw-r--r--src/librustdoc/clean/auto_trait.rs4
-rw-r--r--src/librustdoc/clean/mod.rs10
-rw-r--r--src/librustdoc/clean/simplify.rs2
48 files changed, 262 insertions, 234 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 322cfd55510..5ab8d6eb7b3 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -262,8 +262,7 @@ impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<T>
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        let ty::Binder(ref inner) = *self;
-        inner.hash_stable(hcx, hasher);
+        self.skip_binder().hash_stable(hcx, hasher);
     }
 }
 
diff --git a/src/librustc/infer/canonical.rs b/src/librustc/infer/canonical.rs
index 25f8b5d8c9c..4bb191a878f 100644
--- a/src/librustc/infer/canonical.rs
+++ b/src/librustc/infer/canonical.rs
@@ -388,14 +388,16 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
                     Obligation::new(
                         cause.clone(),
                         param_env,
-                        ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))),
+                        ty::Predicate::RegionOutlives(
+                            ty::Binder::dummy(ty::OutlivesPredicate(r1, r2))),
                     ),
 
                 UnpackedKind::Type(t1) =>
                     Obligation::new(
                         cause.clone(),
                         param_env,
-                        ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))),
+                        ty::Predicate::TypeOutlives(
+                            ty::Binder::dummy(ty::OutlivesPredicate(t1, r2))),
                     ),
             }
         })) as Box<dyn Iterator<Item = _>>
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index c2167751a27..096aed85f55 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -302,7 +302,7 @@ struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
 
 /// Result from a generalization operation. This includes
 /// not only the generalized type, but also a bool flag
-/// indicating whether further WF checks are needed.q
+/// indicating whether further WF checks are needed.
 struct Generalization<'tcx> {
     ty: Ty<'tcx>,
 
@@ -351,7 +351,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
                   -> RelateResult<'tcx, ty::Binder<T>>
         where T: Relate<'tcx>
     {
-        Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?))
+        Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
     }
 
     fn relate_item_substs(&mut self,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index d8a2c95ab59..588f75f809c 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -916,7 +916,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                         };
 
                         if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) {
-                            if exp_is_struct && exp_found.expected == ret_ty.0 {
+                            if exp_is_struct && &exp_found.expected == ret_ty.skip_binder() {
                                 let message = format!(
                                     "did you mean `{}(/* fields */)`?",
                                     self.tcx.item_path_str(def_id)
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index d44f2ec9549..c23836071ff 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -80,7 +80,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
 
             debug!("higher_ranked_sub: OK result={:?}", result);
 
-            Ok(ty::Binder(result))
+            Ok(ty::Binder::bind(result))
         });
     }
 
@@ -239,7 +239,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                    b,
                    result1);
 
-            Ok(ty::Binder(result1))
+            Ok(ty::Binder::bind(result1))
         });
 
         fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
@@ -335,7 +335,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                    b,
                    result1);
 
-            Ok(ty::Binder(result1))
+            Ok(ty::Binder::bind(result1))
         });
 
         fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index f891f692c7d..58eae5e6a5b 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -98,7 +98,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
                         self.fields.trace.cause.clone(),
                         self.fields.param_env,
                         ty::Predicate::Subtype(
-                            ty::Binder(ty::SubtypePredicate {
+                            ty::Binder::dummy(ty::SubtypePredicate {
                                 a_is_expected: self.a_is_expected,
                                 a,
                                 b,
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 2af4c3f9fd4..a7669b942e3 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -537,7 +537,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     &data.parent_trait_ref);
                 match self.get_parent_trait_ref(&data.parent_code) {
                     Some(t) => Some(t),
-                    None => Some(format!("{}", parent_trait_ref.0.self_ty())),
+                    None => Some(format!("{}", parent_trait_ref.skip_binder().self_ty())),
                 }
             }
             _ => None,
@@ -862,7 +862,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                 obligation: &PredicateObligation<'tcx>,
                                 err: &mut DiagnosticBuilder<'tcx>,
                                 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>) {
-        let ty::Binder(trait_ref) = trait_ref;
+        let trait_ref = trait_ref.skip_binder();
         let span = obligation.cause.span;
 
         if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
@@ -1102,7 +1102,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     ::syntax::abi::Abi::Rust
                 )
             };
-            format!("{}", ty::Binder(sig))
+            format!("{}", ty::Binder::bind(sig))
         }
 
         let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
@@ -1436,7 +1436,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             }
             ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
                 let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
-                let ty = parent_trait_ref.0.self_ty();
+                let ty = parent_trait_ref.skip_binder().self_ty();
                 err.note(&format!("required because it appears within the type `{}`", ty));
                 obligated_types.push(ty);
 
@@ -1453,7 +1453,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 err.note(
                     &format!("required because of the requirements on the impl of `{}` for `{}`",
                              parent_trait_ref,
-                             parent_trait_ref.0.self_ty()));
+                             parent_trait_ref.skip_binder().self_ty()));
                 let parent_predicate = parent_trait_ref.to_predicate();
                 self.note_obligation_cause_code(err,
                                             &parent_predicate,
@@ -1484,7 +1484,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
             let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
             for obligated_type in obligated_types {
-                if obligated_type == &parent_trait_ref.0.self_ty() {
+                if obligated_type == &parent_trait_ref.skip_binder().self_ty() {
                     return true;
                 }
             }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 5bfea163189..9e636db3a76 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -864,7 +864,7 @@ fn vtable_methods<'a, 'tcx>(
                 // at some particular call site
                 let substs = tcx.normalize_erasing_late_bound_regions(
                     ty::ParamEnv::reveal_all(),
-                    &ty::Binder(substs),
+                    &ty::Binder::bind(substs),
                 );
 
                 // It's possible that the method relies on where clauses that
@@ -997,7 +997,7 @@ impl<'tcx> FulfillmentError<'tcx> {
 
 impl<'tcx> TraitObligation<'tcx> {
     fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
-        ty::Binder(self.predicate.skip_binder().self_ty())
+        self.predicate.map_bound(|p| p.self_ty())
     }
 }
 
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 52a0a897595..c0d5a337cee 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -149,7 +149,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         trait_def_id: DefId,
         supertraits_only: bool) -> bool
     {
-        let trait_ref = ty::Binder(ty::TraitRef {
+        let trait_ref = ty::Binder::dummy(ty::TraitRef {
             def_id: trait_def_id,
             substs: Substs::identity_for_item(self, trait_def_id)
         });
@@ -199,7 +199,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             .any(|predicate| {
                 match predicate {
                     ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
-                        trait_pred.0.self_ty().is_self()
+                        trait_pred.skip_binder().self_ty().is_self()
                     }
                     ty::Predicate::Projection(..) |
                     ty::Predicate::Trait(..) |
@@ -352,7 +352,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
                     // Compute supertraits of current trait lazily.
                     if supertraits.is_none() {
-                        let trait_ref = ty::Binder(ty::TraitRef {
+                        let trait_ref = ty::Binder::bind(ty::TraitRef {
                             def_id: trait_def_id,
                             substs: Substs::identity_for_item(self, trait_def_id)
                         });
@@ -367,7 +367,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     // direct equality here because all of these types
                     // are part of the formal parameter listing, and
                     // hence there should be no inference variables.
-                    let projection_trait_ref = ty::Binder(data.trait_ref(self));
+                    let projection_trait_ref = ty::Binder::bind(data.trait_ref(self));
                     let is_supertrait_of_current_trait =
                         supertraits.as_ref().unwrap().contains(&projection_trait_ref);
 
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 9f21ea14d0f..1c7942139e9 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -478,7 +478,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
             let def_id = projection_ty.item_def_id;
             let ty_var = selcx.infcx().next_ty_var(
                 TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
-            let projection = ty::Binder(ty::ProjectionPredicate {
+            let projection = ty::Binder::dummy(ty::ProjectionPredicate {
                 projection_ty,
                 ty: ty_var
             });
@@ -982,8 +982,7 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
                predicate);
         match predicate {
             ty::Predicate::Projection(data) => {
-                let same_def_id =
-                    data.0.projection_ty.item_def_id == obligation.predicate.item_def_id;
+                let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
 
                 let is_match = same_def_id && infcx.probe(|_| {
                     let data_poly_trait_ref =
@@ -1241,7 +1240,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
         // item with the correct name
         let env_predicates = env_predicates.filter_map(|p| match p {
             ty::Predicate::Projection(data) =>
-                if data.0.projection_ty.item_def_id == obligation.predicate.item_def_id {
+                if data.projection_def_id() == obligation.predicate.item_def_id {
                     Some(data)
                 } else {
                     None
@@ -1302,28 +1301,28 @@ fn confirm_generator_candidate<'cx, 'gcx, 'tcx>(
 
     let gen_def_id = tcx.lang_items().gen_trait().unwrap();
 
-    // Note: we unwrap the binder here but re-create it below (1)
-    let ty::Binder((trait_ref, yield_ty, return_ty)) =
+    let predicate =
         tcx.generator_trait_ref_and_outputs(gen_def_id,
                                             obligation.predicate.self_ty(),
-                                            gen_sig);
-
-    let name = tcx.associated_item(obligation.predicate.item_def_id).name;
-    let ty = if name == Symbol::intern("Return") {
-        return_ty
-    } else if name == Symbol::intern("Yield") {
-        yield_ty
-    } else {
-        bug!()
-    };
+                                            gen_sig)
+        .map_bound(|(trait_ref, yield_ty, return_ty)| {
+            let name = tcx.associated_item(obligation.predicate.item_def_id).name;
+            let ty = if name == Symbol::intern("Return") {
+                return_ty
+            } else if name == Symbol::intern("Yield") {
+                yield_ty
+            } else {
+                bug!()
+            };
 
-    let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here
-        projection_ty: ty::ProjectionTy {
-            substs: trait_ref.substs,
-            item_def_id: obligation.predicate.item_def_id,
-        },
-        ty: ty
-    });
+            ty::ProjectionPredicate {
+                projection_ty: ty::ProjectionTy {
+                    substs: trait_ref.substs,
+                    item_def_id: obligation.predicate.item_def_id,
+                },
+                ty: ty
+            }
+        });
 
     confirm_param_env_candidate(selcx, obligation, predicate)
         .with_addl_obligations(vtable.nested)
@@ -1400,21 +1399,21 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
     // the `Output` associated type is declared on `FnOnce`
     let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap();
 
-    // Note: we unwrap the binder here but re-create it below (1)
-    let ty::Binder((trait_ref, ret_type)) =
+    let predicate =
         tcx.closure_trait_ref_and_return_type(fn_once_def_id,
                                               obligation.predicate.self_ty(),
                                               fn_sig,
-                                              flag);
-
-    let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here
-        projection_ty: ty::ProjectionTy::from_ref_and_name(
-            tcx,
-            trait_ref,
-            Symbol::intern(FN_OUTPUT_NAME),
-        ),
-        ty: ret_type
-    });
+                                              flag)
+        .map_bound(|(trait_ref, ret_type)| {
+            ty::ProjectionPredicate {
+                projection_ty: ty::ProjectionTy::from_ref_and_name(
+                    tcx,
+                    trait_ref,
+                    Symbol::intern(FN_OUTPUT_NAME),
+                ),
+                ty: ret_type
+            }
+        });
 
     confirm_param_env_candidate(selcx, obligation, predicate)
 }
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 51493f26194..b61407ffdb6 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1274,7 +1274,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                              -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>>
     {
         let tcx = self.tcx();
-        let trait_ref = &cache_fresh_trait_pred.0.trait_ref;
+        let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;
         if self.can_use_global_caches(param_env) {
             let cache = tcx.selection_cache.hashmap.borrow();
             if let Some(cached) = cache.get(&trait_ref) {
@@ -1294,7 +1294,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                               candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>)
     {
         let tcx = self.tcx();
-        let trait_ref = cache_fresh_trait_pred.0.trait_ref;
+        let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref;
         if self.can_use_global_caches(param_env) {
             let mut cache = tcx.selection_cache.hashmap.borrow_mut();
             if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
@@ -1357,7 +1357,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let lang_items = self.tcx().lang_items();
         if lang_items.copy_trait() == Some(def_id) {
             debug!("obligation self ty is {:?}",
-                   obligation.predicate.0.self_ty());
+                   obligation.predicate.skip_binder().self_ty());
 
             // User-defined copy impls are permitted, but only for
             // structs and enums.
@@ -1409,7 +1409,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         // before we go into the whole skolemization thing, just
         // quickly check if the self-type is a projection at all.
-        match obligation.predicate.0.trait_ref.self_ty().sty {
+        match obligation.predicate.skip_binder().trait_ref.self_ty().sty {
             ty::TyProjection(_) | ty::TyAnon(..) => {}
             ty::TyInfer(ty::TyVar(_)) => {
                 span_bug!(obligation.cause.span,
@@ -1507,7 +1507,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     {
         assert!(!skol_trait_ref.has_escaping_regions());
         if let Err(_) = self.infcx.at(&obligation.cause, obligation.param_env)
-                                  .sup(ty::Binder(skol_trait_ref), trait_bound) {
+                                  .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) {
             return false;
         }
 
@@ -1605,7 +1605,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                    candidates: &mut SelectionCandidateSet<'tcx>)
                                    -> Result<(),SelectionError<'tcx>>
     {
-        let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.0.def_id()) {
+        let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) {
             Some(k) => k,
             None => { return Ok(()); }
         };
@@ -1661,12 +1661,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
             // provide an impl, but only for suitable `fn` pointers
             ty::TyFnDef(..) | ty::TyFnPtr(_) => {
-                if let ty::Binder(ty::FnSig {
+                if let ty::FnSig {
                     unsafety: hir::Unsafety::Normal,
                     abi: Abi::Rust,
                     variadic: false,
                     ..
-                }) = self_ty.fn_sig(self.tcx()) {
+                } = self_ty.fn_sig(self.tcx()).skip_binder() {
                     candidates.vec.push(FnPointerCandidate);
                 }
             }
@@ -1687,7 +1687,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         self.tcx().for_each_relevant_impl(
             obligation.predicate.def_id(),
-            obligation.predicate.0.trait_ref.self_ty(),
+            obligation.predicate.skip_binder().trait_ref.self_ty(),
             |impl_def_id| {
                 self.probe(|this, snapshot| { /* [1] */
                     match this.match_impl(impl_def_id, obligation, snapshot) {
@@ -2046,19 +2046,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             ty::TyGeneratorWitness(..) | ty::TyArray(..) | ty::TyClosure(..) |
             ty::TyNever | ty::TyError => {
                 // safe for everything
-                Where(ty::Binder(Vec::new()))
+                Where(ty::Binder::dummy(Vec::new()))
             }
 
             ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => Never,
 
             ty::TyTuple(tys) => {
-                Where(ty::Binder(tys.last().into_iter().cloned().collect()))
+                Where(ty::Binder::bind(tys.last().into_iter().cloned().collect()))
             }
 
             ty::TyAdt(def, substs) => {
                 let sized_crit = def.sized_constraint(self.tcx());
                 // (*) binder moved here
-                Where(ty::Binder(
+                Where(ty::Binder::bind(
                     sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect()
                 ))
             }
@@ -2088,7 +2088,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         match self_ty.sty {
             ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
             ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyError => {
-                Where(ty::Binder(Vec::new()))
+                Where(ty::Binder::dummy(Vec::new()))
             }
 
             ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
@@ -2106,12 +2106,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
             ty::TyArray(element_ty, _) => {
                 // (*) binder moved here
-                Where(ty::Binder(vec![element_ty]))
+                Where(ty::Binder::bind(vec![element_ty]))
             }
 
             ty::TyTuple(tys) => {
                 // (*) binder moved here
-                Where(ty::Binder(tys.to_vec()))
+                Where(ty::Binder::bind(tys.to_vec()))
             }
 
             ty::TyClosure(def_id, substs) => {
@@ -2119,7 +2119,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 let is_copy_trait = Some(trait_id) == self.tcx().lang_items().copy_trait();
                 let is_clone_trait = Some(trait_id) == self.tcx().lang_items().clone_trait();
                 if is_copy_trait || is_clone_trait {
-                    Where(ty::Binder(substs.upvar_tys(def_id, self.tcx()).collect()))
+                    Where(ty::Binder::bind(substs.upvar_tys(def_id, self.tcx()).collect()))
                 } else {
                     Never
                 }
@@ -2260,7 +2260,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         // 3. Re-bind the regions back to `for<'a> &'a int : Copy`
 
         types.skip_binder().into_iter().flat_map(|ty| { // binder moved -\
-            let ty: ty::Binder<Ty<'tcx>> = ty::Binder(ty); // <----------/
+            let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
 
             self.in_snapshot(|this, snapshot| {
                 let (skol_ty, skol_map) =
@@ -2450,18 +2450,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
     /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
     fn confirm_auto_impl_candidate(&mut self,
-                                      obligation: &TraitObligation<'tcx>,
-                                      trait_def_id: DefId)
-                                      -> VtableAutoImplData<PredicateObligation<'tcx>>
+                                   obligation: &TraitObligation<'tcx>,
+                                   trait_def_id: DefId)
+                                   -> VtableAutoImplData<PredicateObligation<'tcx>>
     {
         debug!("confirm_auto_impl_candidate({:?}, {:?})",
                obligation,
                trait_def_id);
 
-        // binder is moved below
-        let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
-        let types = self.constituent_types_for_ty(self_ty);
-        self.vtable_auto_impl(obligation, trait_def_id, ty::Binder(types))
+        let types = obligation.predicate.map_bound(|inner| {
+            let self_ty = self.infcx.shallow_resolve(inner.self_ty());
+            self.constituent_types_for_ty(self_ty)
+        });
+        self.vtable_auto_impl(obligation, trait_def_id, types)
     }
 
     /// See `confirm_auto_impl_candidate`
@@ -2726,7 +2727,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     {
         debug!("confirm_closure_candidate({:?})", obligation);
 
-        let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.0.def_id()) {
+        let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) {
             Some(k) => k,
             None => bug!("closure candidate for non-fn trait {:?}", obligation)
         };
@@ -2835,14 +2836,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
             (&ty::TyDynamic(ref data_a, r_a), &ty::TyDynamic(ref data_b, r_b)) => {
                 // See assemble_candidates_for_unsizing for more info.
-                // Binders reintroduced below in call to mk_existential_predicates.
-                let principal = data_a.skip_binder().principal();
-                let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait)
-                    .chain(data_a.skip_binder().projection_bounds()
-                           .map(|x| ty::ExistentialPredicate::Projection(x)))
-                    .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
-                let new_trait = tcx.mk_dynamic(
-                    ty::Binder(tcx.mk_existential_predicates(iter)), r_b);
+                let existential_predicates = data_a.map_bound(|data_a| {
+                    let principal = data_a.principal();
+                    let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait)
+                        .chain(data_a.projection_bounds()
+                            .map(|x| ty::ExistentialPredicate::Projection(x)))
+                        .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
+                    tcx.mk_existential_predicates(iter)
+                });
+                let new_trait = tcx.mk_dynamic(existential_predicates, r_b);
                 let InferOk { obligations, .. } =
                     self.infcx.at(&obligation.cause, obligation.param_env)
                               .eq(target, new_trait)
@@ -2857,7 +2859,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 nested.push(Obligation::with_depth(cause,
                                                    obligation.recursion_depth + 1,
                                                    obligation.param_env,
-                                                   ty::Binder(outlives).to_predicate()));
+                                                   ty::Binder::bind(outlives).to_predicate()));
             }
 
             // T -> Trait.
@@ -2900,7 +2902,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 // If the type is `Foo+'a`, ensures that the type
                 // being cast to `Foo+'a` outlives `'a`:
                 let outlives = ty::OutlivesPredicate(source, r);
-                push(ty::Binder(outlives).to_predicate());
+                push(ty::Binder::dummy(outlives).to_predicate());
             }
 
             // [T; n] -> [T].
@@ -3201,18 +3203,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                       -> ty::PolyTraitRef<'tcx>
     {
         let closure_type = self.infcx.closure_sig(closure_def_id, substs);
-        let ty::Binder((trait_ref, _)) =
-            self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
-                                                         obligation.predicate.0.self_ty(), // (1)
-                                                         closure_type,
-                                                         util::TupleArgumentsFlag::No);
+
         // (1) Feels icky to skip the binder here, but OTOH we know
         // that the self-type is an unboxed closure type and hence is
         // in fact unparameterized (or at least does not reference any
         // regions bound in the obligation). Still probably some
         // refactoring could make this nicer.
 
-        ty::Binder(trait_ref)
+        self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
+                                                     obligation.predicate
+                                                         .skip_binder().self_ty(), // (1)
+                                                     closure_type,
+                                                     util::TupleArgumentsFlag::No)
+            .map_bound(|(trait_ref, _)| trait_ref)
     }
 
     fn generator_trait_ref_unnormalized(&mut self,
@@ -3222,17 +3225,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                       -> ty::PolyTraitRef<'tcx>
     {
         let gen_sig = substs.generator_poly_sig(closure_def_id, self.tcx());
-        let ty::Binder((trait_ref, ..)) =
-            self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(),
-                                                       obligation.predicate.0.self_ty(), // (1)
-                                                       gen_sig);
+
         // (1) Feels icky to skip the binder here, but OTOH we know
         // that the self-type is an generator type and hence is
         // in fact unparameterized (or at least does not reference any
         // regions bound in the obligation). Still probably some
         // refactoring could make this nicer.
 
-        ty::Binder(trait_ref)
+        self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(),
+                                                   obligation.predicate
+                                                       .skip_binder().self_ty(), // (1)
+                                                   gen_sig)
+            .map_bound(|(trait_ref, ..)| trait_ref)
     }
 
     /// Returns the obligations that are implied by instantiating an
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 9e38911f53c..3c62f04afc5 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -209,13 +209,13 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
                                None
                            } else {
                                Some(ty::Predicate::RegionOutlives(
-                                   ty::Binder(ty::OutlivesPredicate(r, r_min))))
+                                   ty::Binder::dummy(ty::OutlivesPredicate(r, r_min))))
                            },
 
                            Component::Param(p) => {
                                let ty = tcx.mk_param(p.idx, p.name);
                                Some(ty::Predicate::TypeOutlives(
-                                   ty::Binder(ty::OutlivesPredicate(ty, r_min))))
+                                   ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min))))
                            },
 
                            Component::UnresolvedInferenceVariable(_) => {
@@ -514,7 +514,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             def_id: fn_trait_def_id,
             substs: self.mk_substs_trait(self_ty, &[arguments_tuple]),
         };
-        ty::Binder((trait_ref, sig.skip_binder().output()))
+        ty::Binder::bind((trait_ref, sig.skip_binder().output()))
     }
 
     pub fn generator_trait_ref_and_outputs(self,
@@ -527,7 +527,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             def_id: fn_trait_def_id,
             substs: self.mk_substs_trait(self_ty, &[]),
         };
-        ty::Binder((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
+        ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
     }
 
     pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs
index f86c1cf0dd6..047bfcc8c6f 100644
--- a/src/librustc/ty/_match.rs
+++ b/src/librustc/ty/_match.rs
@@ -92,6 +92,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Match<'a, 'gcx, 'tcx> {
                   -> RelateResult<'tcx, ty::Binder<T>>
         where T: Relate<'tcx>
     {
-        Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?))
+        Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
     }
 }
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 8071cd0c639..eb06852c65d 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -394,7 +394,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 }
             }
         });
-        Binder(value)
+        Binder::bind(value)
     }
 
     /// Returns a set of all late-bound regions that are constrained
@@ -446,7 +446,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         where T : TypeFoldable<'tcx>,
     {
         let mut counter = 0;
-        Binder(self.replace_late_bound_regions(sig, |_| {
+        Binder::bind(self.replace_late_bound_regions(sig, |_| {
             counter += 1;
             self.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(counter)))
         }).0)
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 76f7a0b59a2..02a03bc542a 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -259,7 +259,7 @@ fn resolve_associated_item<'a, 'tcx>(
            def_id, trait_id, rcvr_substs);
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = tcx.trans_fulfill_obligation((param_env, ty::Binder(trait_ref)));
+    let vtbl = tcx.trans_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
 
     // Now that we know which impl is being used, we can dispatch to
     // the actual function:
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 1524d4b9e7f..d8aba024502 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1048,18 +1048,18 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
         // from the substitution and the value being substituted into, and
         // this trick achieves that).
 
-        let substs = &trait_ref.0.substs;
+        let substs = &trait_ref.skip_binder().substs;
         match *self {
-            Predicate::Trait(ty::Binder(ref data)) =>
-                Predicate::Trait(ty::Binder(data.subst(tcx, substs))),
-            Predicate::Subtype(ty::Binder(ref data)) =>
-                Predicate::Subtype(ty::Binder(data.subst(tcx, substs))),
-            Predicate::RegionOutlives(ty::Binder(ref data)) =>
-                Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))),
-            Predicate::TypeOutlives(ty::Binder(ref data)) =>
-                Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))),
-            Predicate::Projection(ty::Binder(ref data)) =>
-                Predicate::Projection(ty::Binder(data.subst(tcx, substs))),
+            Predicate::Trait(ref binder) =>
+                Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs))),
+            Predicate::Subtype(ref binder) =>
+                Predicate::Subtype(binder.map_bound(|data| data.subst(tcx, substs))),
+            Predicate::RegionOutlives(ref binder) =>
+                Predicate::RegionOutlives(binder.map_bound(|data| data.subst(tcx, substs))),
+            Predicate::TypeOutlives(ref binder) =>
+                Predicate::TypeOutlives(binder.map_bound(|data| data.subst(tcx, substs))),
+            Predicate::Projection(ref binder) =>
+                Predicate::Projection(binder.map_bound(|data| data.subst(tcx, substs))),
             Predicate::WellFormed(data) =>
                 Predicate::WellFormed(data.subst(tcx, substs)),
             Predicate::ObjectSafe(trait_def_id) =>
@@ -1095,7 +1095,7 @@ impl<'tcx> TraitPredicate<'tcx> {
 impl<'tcx> PolyTraitPredicate<'tcx> {
     pub fn def_id(&self) -> DefId {
         // ok to skip binder since trait def-id does not care about regions
-        self.0.def_id()
+        self.skip_binder().def_id()
     }
 }
 
@@ -1149,11 +1149,20 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
         // This is because here `self` has a `Binder` and so does our
         // return value, so we are preserving the number of binding
         // levels.
-        ty::Binder(self.0.projection_ty.trait_ref(tcx))
+        self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
     }
 
     pub fn ty(&self) -> Binder<Ty<'tcx>> {
-        Binder(self.skip_binder().ty) // preserves binding levels
+        self.map_bound(|predicate| predicate.ty)
+    }
+
+    /// The DefId of the TraitItem for the associated type.
+    ///
+    /// Note that this is not the DefId of the TraitRef containing this
+    /// associated type, which is in tcx.associated_item(projection_def_id()).container.
+    pub fn projection_def_id(&self) -> DefId {
+        // ok to skip binder since trait def-id does not care about regions
+        self.skip_binder().projection_ty.item_def_id
     }
 }
 
@@ -1163,8 +1172,7 @@ pub trait ToPolyTraitRef<'tcx> {
 
 impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
-        assert!(!self.has_escaping_regions());
-        ty::Binder(self.clone())
+        ty::Binder::dummy(self.clone())
     }
 }
 
@@ -1180,12 +1188,7 @@ pub trait ToPredicate<'tcx> {
 
 impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
     fn to_predicate(&self) -> Predicate<'tcx> {
-        // we're about to add a binder, so let's check that we don't
-        // accidentally capture anything, or else that might be some
-        // weird debruijn accounting.
-        assert!(!self.has_escaping_regions());
-
-        ty::Predicate::Trait(ty::Binder(ty::TraitPredicate {
+        ty::Predicate::Trait(ty::Binder::dummy(ty::TraitPredicate {
             trait_ref: self.clone()
         }))
     }
@@ -1224,17 +1227,19 @@ impl<'tcx> Predicate<'tcx> {
             ty::Predicate::Trait(ref data) => {
                 data.skip_binder().input_types().collect()
             }
-            ty::Predicate::Subtype(ty::Binder(SubtypePredicate { a, b, a_is_expected: _ })) => {
+            ty::Predicate::Subtype(binder) => {
+                let SubtypePredicate { a, b, a_is_expected: _ } = binder.skip_binder();
                 vec![a, b]
             }
-            ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
-                vec![data.0]
+            ty::Predicate::TypeOutlives(binder) => {
+                vec![binder.skip_binder().0]
             }
             ty::Predicate::RegionOutlives(..) => {
                 vec![]
             }
             ty::Predicate::Projection(ref data) => {
-                data.0.projection_ty.substs.types().chain(Some(data.0.ty)).collect()
+                let inner = data.skip_binder();
+                inner.projection_ty.substs.types().chain(Some(inner.ty)).collect()
             }
             ty::Predicate::WellFormed(data) => {
                 vec![data]
@@ -2090,7 +2095,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                     Some(x) => x,
                     _ => return vec![ty]
                 };
-                let sized_predicate = Binder(TraitRef {
+                let sized_predicate = Binder::dummy(TraitRef {
                     def_id: sized_trait,
                     substs: tcx.mk_substs_trait(ty, &[])
                 }).to_predicate();
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 36eb3e3f94c..348cf03dd87 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -431,10 +431,10 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
         {
             // Wrap our types with a temporary GeneratorWitness struct
             // inside the binder so we can related them
-            let a_types = ty::Binder(GeneratorWitness(*a_types.skip_binder()));
-            let b_types = ty::Binder(GeneratorWitness(*b_types.skip_binder()));
+            let a_types = a_types.map_bound(GeneratorWitness);
+            let b_types = b_types.map_bound(GeneratorWitness);
             // Then remove the GeneratorWitness for the result
-            let types = ty::Binder(relation.relate(&a_types, &b_types)?.skip_binder().0);
+            let types = relation.relate(&a_types, &b_types)?.map_bound(|witness| witness.0);
             Ok(tcx.mk_generator_witness(types))
         }
 
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 7b4b7082bb6..199a46678c8 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -270,7 +270,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> {
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> {
     type Lifted = ty::Binder<T::Lifted>;
     fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.0).map(|x| ty::Binder(x))
+        tcx.lift(self.skip_binder()).map(ty::Binder::bind)
     }
 }
 
@@ -720,7 +720,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
 
 impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        ty::Binder(self.0.fold_with(folder))
+        self.map_bound_ref(|ty| ty.fold_with(folder))
     }
 
     fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
@@ -728,7 +728,7 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.0.visit_with(visitor)
+        self.skip_binder().visit_with(visitor)
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 310fcbcfcb3..d5b63939dd6 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -345,7 +345,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// binder, but it never contains bound regions. Probably this
     /// function should be removed.
     pub fn generator_poly_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> PolyGenSig<'tcx> {
-        ty::Binder(self.generator_sig(def_id, tcx))
+        ty::Binder::dummy(self.generator_sig(def_id, tcx))
     }
 
     /// Return the "generator signature", which consists of its yield
@@ -504,13 +504,13 @@ impl<'tcx> Slice<ExistentialPredicate<'tcx>> {
 
 impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> {
     pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> {
-        self.skip_binder().principal().map(Binder)
+        self.skip_binder().principal().map(Binder::bind)
     }
 
     #[inline]
     pub fn projection_bounds<'a>(&'a self) ->
         impl Iterator<Item=PolyExistentialProjection<'tcx>> + 'a {
-        self.skip_binder().projection_bounds().map(Binder)
+        self.skip_binder().projection_bounds().map(Binder::bind)
     }
 
     #[inline]
@@ -520,7 +520,7 @@ impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> {
 
     pub fn iter<'a>(&'a self)
         -> impl DoubleEndedIterator<Item=Binder<ExistentialPredicate<'tcx>>> + 'tcx {
-        self.skip_binder().iter().cloned().map(Binder)
+        self.skip_binder().iter().cloned().map(Binder::bind)
     }
 }
 
@@ -567,26 +567,26 @@ pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>;
 
 impl<'tcx> PolyTraitRef<'tcx> {
     pub fn self_ty(&self) -> Ty<'tcx> {
-        self.0.self_ty()
+        self.skip_binder().self_ty()
     }
 
     pub fn def_id(&self) -> DefId {
-        self.0.def_id
+        self.skip_binder().def_id
     }
 
     pub fn substs(&self) -> &'tcx Substs<'tcx> {
         // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
-        self.0.substs
+        self.skip_binder().substs
     }
 
     pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
         // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
-        self.0.input_types()
+        self.skip_binder().input_types()
     }
 
     pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
         // Note that we preserve binding levels
-        Binder(ty::TraitPredicate { trait_ref: self.0.clone() })
+        Binder(ty::TraitPredicate { trait_ref: self.skip_binder().clone() })
     }
 }
 
@@ -633,12 +633,12 @@ pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>;
 
 impl<'tcx> PolyExistentialTraitRef<'tcx> {
     pub fn def_id(&self) -> DefId {
-        self.0.def_id
+        self.skip_binder().def_id
     }
 
     pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
         // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
-        self.0.input_types()
+        self.skip_binder().input_types()
     }
 }
 
@@ -650,7 +650,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
 /// type from `Binder<T>` to just `T` (see
 /// e.g. `liberate_late_bound_regions`).
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct Binder<T>(pub T);
+pub struct Binder<T>(T);
 
 impl<T> Binder<T> {
     /// Wraps `value` in a binder, asserting that `value` does not
@@ -664,6 +664,12 @@ impl<T> Binder<T> {
         Binder(value)
     }
 
+    /// Wraps `value` in a binder, binding late-bound regions (if any).
+    pub fn bind<'tcx>(value: T) -> Binder<T>
+    {
+        Binder(value)
+    }
+
     /// Skips the binder and returns the "bound" value. This is a
     /// risky thing to do because it's easy to get confused about
     /// debruijn indices and the like. It is usually better to
@@ -685,7 +691,7 @@ impl<T> Binder<T> {
     }
 
     pub fn as_ref(&self) -> Binder<&T> {
-        ty::Binder(&self.0)
+        Binder(&self.0)
     }
 
     pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U>
@@ -697,7 +703,7 @@ impl<T> Binder<T> {
     pub fn map_bound<F, U>(self, f: F) -> Binder<U>
         where F: FnOnce(T) -> U
     {
-        ty::Binder(f(self.0))
+        Binder(f(self.0))
     }
 
     /// Unwraps and returns the value within, but only if it contains
@@ -730,7 +736,7 @@ impl<T> Binder<T> {
     pub fn fuse<U,F,R>(self, u: Binder<U>, f: F) -> Binder<R>
         where F: FnOnce(T, U) -> R
     {
-        ty::Binder(f(self.0, u.0))
+        Binder(f(self.0, u.0))
     }
 
     /// Split the contents into two things that share the same binder
@@ -743,7 +749,7 @@ impl<T> Binder<T> {
         where F: FnOnce(T) -> (U, V)
     {
         let (u, v) = f(self.0);
-        (ty::Binder(u), ty::Binder(v))
+        (Binder(u), Binder(v))
     }
 }
 
@@ -839,7 +845,7 @@ pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;
 
 impl<'tcx> PolyFnSig<'tcx> {
     pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> {
-        Binder(self.skip_binder().inputs())
+        self.map_bound_ref(|fn_sig| fn_sig.inputs())
     }
     pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> {
         self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
@@ -1152,6 +1158,10 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
         -> ty::PolyProjectionPredicate<'tcx> {
         self.map_bound(|p| p.with_self_ty(tcx, self_ty))
     }
+
+    pub fn item_def_id(&self) -> DefId {
+        return self.skip_binder().item_def_id;
+    }
 }
 
 impl DebruijnIndex {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 77eff49d19f..b23e9124ddc 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -380,7 +380,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     ty::Predicate::ConstEvaluatable(..) => {
                         None
                     }
-                    ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => {
+                    ty::Predicate::TypeOutlives(predicate) => {
                         // Search for a bound of the form `erased_self_ty
                         // : 'a`, but be wary of something like `for<'a>
                         // erased_self_ty : 'a` (we interpret a
@@ -390,8 +390,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                         // it's kind of a moot point since you could never
                         // construct such an object, but this seems
                         // correct even if that code changes).
-                        if t == erased_self_ty && !r.has_escaping_regions() {
-                            Some(r)
+                        let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
+                        if t == &erased_self_ty && !r.has_escaping_regions() {
+                            Some(*r)
                         } else {
                             None
                         }
@@ -561,7 +562,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
             ty::ClosureKind::FnOnce => closure_ty,
         };
-        Some(ty::Binder(env_ty))
+        Some(ty::Binder::bind(env_ty))
     }
 
     /// Given the def-id of some item that has no type parameters, make
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index f05d56c9d83..aea84791fe8 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
                                 cause,
                                 param_env,
                                 ty::Predicate::TypeOutlives(
-                                    ty::Binder(
+                                    ty::Binder::dummy(
                                         ty::OutlivesPredicate(mt.ty, r)))));
                     }
                 }
@@ -492,7 +492,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
 
             for implicit_bound in implicit_bounds {
                 let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
-                let outlives = ty::Binder(ty::OutlivesPredicate(explicit_bound, implicit_bound));
+                let outlives = ty::Binder::dummy(
+                    ty::OutlivesPredicate(explicit_bound, implicit_bound));
                 self.out.push(traits::Obligation::new(cause,
                                                       self.param_env,
                                                       outlives.to_predicate()));
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 84e3358ff13..efe83252d0f 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -473,7 +473,7 @@ impl PrintContext {
         let value = if let Some(v) = lifted {
             v
         } else {
-            return original.0.print_display(f, self);
+            return original.skip_binder().print_display(f, self);
         };
 
         if self.binder_depth == 0 {
@@ -679,9 +679,9 @@ define_print! {
             ty::tls::with(|tcx| {
                 let dummy_self = tcx.mk_infer(ty::FreshTy(0));
 
-                let trait_ref = tcx.lift(&ty::Binder(*self))
+                let trait_ref = *tcx.lift(&ty::Binder::bind(*self))
                                    .expect("could not lift TraitRef for printing")
-                                   .with_self_ty(tcx, dummy_self).0;
+                                   .with_self_ty(tcx, dummy_self).skip_binder();
                 cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[])
             })
         }
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 04f6503d92d..83501f45ec0 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -284,7 +284,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
     }
 
     pub fn t_fn(&self, input_tys: &[Ty<'tcx>], output_ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.infcx.tcx.mk_fn_ptr(ty::Binder(self.infcx.tcx.mk_fn_sig(
+        self.infcx.tcx.mk_fn_ptr(ty::Binder::bind(self.infcx.tcx.mk_fn_sig(
             input_tys.iter().cloned(),
             output_ty,
             false,
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 6f2c51b0f18..141d491327a 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -960,7 +960,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
                 // Attempt to select a concrete impl before checking.
                 ty::TraitContainer(trait_def_id) => {
                     let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs);
-                    let trait_ref = ty::Binder(trait_ref);
+                    let trait_ref = ty::Binder::bind(trait_ref);
                     let span = tcx.hir.span(expr_id);
                     let obligation =
                         traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs
index 5c38735d920..020dce62c38 100644
--- a/src/librustc_mir/monomorphize/mod.rs
+++ b/src/librustc_mir/monomorphize/mod.rs
@@ -163,7 +163,7 @@ pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            -> CustomCoerceUnsized {
     let def_id = tcx.lang_items().coerce_unsized_trait().unwrap();
 
-    let trait_ref = ty::Binder(ty::TraitRef {
+    let trait_ref = ty::Binder::bind(ty::TraitRef {
         def_id: def_id,
         substs: tcx.mk_substs_trait(source_ty, &[target_ty])
     });
diff --git a/src/librustc_traits/util.rs b/src/librustc_traits/util.rs
index f25906a7bca..e4cb118a4f7 100644
--- a/src/librustc_traits/util.rs
+++ b/src/librustc_traits/util.rs
@@ -86,14 +86,14 @@ where
                 }
                 Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r1.into(), r2),
             })
-            .map(ty::Binder) // no bound regions in the code above
+            .map(ty::Binder::dummy) // no bound regions in the code above
             .collect();
 
         outlives.extend(
             region_obligations
                 .into_iter()
                 .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region))
-                .map(ty::Binder) // no bound regions in the code above
+                .map(ty::Binder::dummy) // no bound regions in the code above
         );
 
         outlives
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index fe8a7052bdf..4d781d7280d 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -406,7 +406,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
             return llfn;
         }
 
-        let ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
+        let ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
             iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
             tcx.types.never,
             false,
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 5c67f809114..ecdc2d20d21 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -958,7 +958,7 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     output: Ty<'tcx>,
                     trans: &mut for<'b> FnMut(Builder<'b, 'tcx>))
                     -> ValueRef {
-    let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder(cx.tcx.mk_fn_sig(
+    let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig(
         inputs.into_iter(),
         output,
         false,
@@ -985,7 +985,7 @@ fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     // Define the type up front for the signature of the rust_try function.
     let tcx = cx.tcx;
     let i8p = tcx.mk_mut_ptr(tcx.types.i8);
-    let fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
+    let fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
         iter::once(i8p),
         tcx.mk_nil(),
         false,
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 36debf677da..d657db0b125 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -363,7 +363,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                                                  trait_def_id,
                                                  self_ty,
                                                  trait_ref.path.segments.last().unwrap());
-        let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs));
+        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
 
         poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
             // specify type to assert that error was already reported in Err case:
@@ -485,7 +485,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
             let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&trait_ref);
             let late_bound_in_ty =
-                tcx.collect_referenced_late_bound_regions(&ty::Binder(binding.ty));
+                tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(binding.ty));
             debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
             debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
             for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) {
@@ -639,7 +639,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         }
 
         for projection_bound in &projection_bounds {
-            associated_types.remove(&projection_bound.0.projection_ty.item_def_id);
+            associated_types.remove(&projection_bound.projection_def_id());
         }
 
         for item_def_id in associated_types {
@@ -654,6 +654,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                         .emit();
         }
 
+        // skip_binder is okay, because the predicates are re-bound.
         let mut v =
             iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
             .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
@@ -661,7 +662,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                    .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())))
             .collect::<AccumulateVec<[_; 8]>>();
         v.sort_by(|a, b| a.cmp(tcx, b));
-        let existential_predicates = ty::Binder(tcx.mk_existential_predicates(v.into_iter()));
+        let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
 
 
         // Explicitly specified region bound. Use that.
@@ -825,7 +826,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 };
 
                 let candidates =
-                    traits::supertraits(tcx, ty::Binder(trait_ref))
+                    traits::supertraits(tcx, ty::Binder::bind(trait_ref))
                     .filter(|r| self.trait_defines_associated_type_named(r.def_id(),
                                                                          assoc_name));
 
@@ -853,7 +854,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             }
         };
 
-        let trait_did = bound.0.def_id;
+        let trait_did = bound.def_id();
         let (assoc_ident, def_scope) = tcx.adjust(assoc_name, trait_did, ref_id);
         let item = tcx.associated_items(trait_did).find(|i| {
             Namespace::from(i.kind) == Namespace::Type &&
@@ -1184,7 +1185,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
         debug!("ty_of_fn: output_ty={:?}", output_ty);
 
-        let bare_fn_ty = ty::Binder(tcx.mk_fn_sig(
+        let bare_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
             input_tys.into_iter(),
             output_ty,
             decl.variadic,
@@ -1396,7 +1397,8 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
             // account for the binder being introduced below; no need to shift `param_ty`
             // because, at present at least, it can only refer to early-bound regions
             let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
-            vec.push(ty::Binder(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate());
+            vec.push(
+                ty::Binder::dummy(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate());
         }
 
         for bound_trait_ref in &self.trait_bounds {
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index b1fb0938698..0c95f5eeb43 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -267,7 +267,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 // This is the "default" function signature, used in case of error.
                 // In that case, we check each argument against "error" in order to
                 // set up all the node type bindings.
-                (ty::Binder(self.tcx.mk_fn_sig(
+                (ty::Binder::bind(self.tcx.mk_fn_sig(
                     self.err_args(arg_exprs.len()).into_iter(),
                     self.tcx.types.err,
                     false,
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 68b0560355f..0deda993d4f 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -317,7 +317,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
         };
 
-        let ret_param_ty = projection.0.ty;
+        let ret_param_ty = projection.skip_binder().ty;
         let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
         debug!(
             "deduce_sig_from_projection: ret_param_ty {:?}",
@@ -458,7 +458,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // regions appearing free in `expected_sig` are now bound up
         // in this binder we are creating.
         assert!(!expected_sig.sig.has_regions_escaping_depth(1));
-        let bound_sig = ty::Binder(self.tcx.mk_fn_sig(
+        let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig(
             expected_sig.sig.inputs().iter().cloned(),
             expected_sig.sig.output(),
             decl.variadic,
@@ -562,7 +562,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let (supplied_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
                     hir_ty.span,
                     LateBoundRegionConversionTime::FnCall,
-                    &ty::Binder(supplied_ty),
+                    &ty::Binder::bind(supplied_ty),
                 ); // recreated from (*) above
 
                 // Check that E' = S'.
@@ -607,7 +607,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             hir::DefaultReturn(_) => astconv.ty_infer(decl.output.span()),
         };
 
-        let result = ty::Binder(self.tcx.mk_fn_sig(
+        let result = ty::Binder::bind(self.tcx.mk_fn_sig(
             supplied_arguments,
             supplied_return,
             decl.variadic,
@@ -639,7 +639,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             hir::DefaultReturn(_) => {}
         }
 
-        let result = ty::Binder(self.tcx.mk_fn_sig(
+        let result = ty::Binder::bind(self.tcx.mk_fn_sig(
             supplied_arguments,
             self.tcx.types.err,
             decl.variadic,
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index a8d1f69dfe8..8c69608a261 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -558,7 +558,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
             let trait_ref = match obligation.predicate {
                 ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
                     if unsize_did == tr.def_id() {
-                        if let ty::TyTuple(..) = tr.0.input_types().nth(1).unwrap().sty {
+                        let sty = &tr.skip_binder().input_types().nth(1).unwrap().sty;
+                        if let ty::TyTuple(..) = sty {
                             debug!("coerce_unsized: found unsized tuple coercion");
                             has_unsized_tuple_coercion = true;
                         }
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index e1e3dea9a2a..c9e53fa7674 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -234,9 +234,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let mut selcx = traits::SelectionContext::new(&infcx);
 
         let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs);
-        let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
-                                                       infer::HigherRankedType,
-                                                       &ty::Binder(impl_m_own_bounds.predicates));
+        let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(
+            impl_m_span,
+            infer::HigherRankedType,
+            &ty::Binder::bind(impl_m_own_bounds.predicates)
+        );
         for predicate in impl_m_own_bounds {
             let traits::Normalized { value: predicate, obligations } =
                 traits::normalize(&mut selcx, param_env, normalize_cause.clone(), &predicate);
@@ -270,7 +272,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                               impl_m_node_id,
                                               param_env,
                                               &impl_sig);
-        let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
+        let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
         let trait_sig = tcx.liberate_late_bound_regions(
@@ -283,7 +285,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                               impl_m_node_id,
                                               param_env,
                                               &trait_sig);
-        let trait_fty = tcx.mk_fn_ptr(ty::Binder(trait_sig));
+        let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig));
 
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
 
@@ -505,7 +507,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.infer_ctxt().enter(|infcx| {
             let self_arg_ty = tcx.liberate_late_bound_regions(
                 method.def_id,
-                &ty::Binder(self_arg_ty)
+                &ty::Binder::bind(self_arg_ty)
             );
             let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
             match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index c50ee13723f..7bae5fe4fd1 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -129,7 +129,7 @@ pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
                                         ty::BrAnon(counter)))
     });
 
-    let witness = fcx.tcx.mk_generator_witness(ty::Binder(type_list));
+    let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
 
     debug!("Types in generator after region replacement {:?}, span = {:?}",
             witness, body.value.span);
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index da0d4509353..64b0e7d0a7d 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -61,7 +61,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return;
     }
 
-    let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
+    let fty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
         inputs.into_iter(),
         output,
         false,
@@ -304,7 +304,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             "try" => {
                 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
-                let fn_ty = ty::Binder(tcx.mk_fn_sig(
+                let fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
                     iter::once(mut_u8),
                     tcx.mk_nil(),
                     false,
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 7569bdccd5a..09feaaffc5b 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -125,7 +125,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         // We won't add these if we encountered an illegal sized bound, so that we can use
         // a custom error in that case.
         if !illegal_sized_bound {
-            let method_ty = self.tcx.mk_fn_ptr(ty::Binder(method_sig));
+            let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig));
             self.add_obligations(method_ty, all_substs, &method_predicates);
         }
 
@@ -587,7 +587,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                 }
             })
             .any(|trait_pred| {
-                match trait_pred.0.self_ty().sty {
+                match trait_pred.skip_binder().self_ty().sty {
                     ty::TyDynamic(..) => true,
                     _ => false,
                 }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 49d0df555fa..5f55ee6163b 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -336,7 +336,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                            &bounds));
 
         // Also add an obligation for the method type being well-formed.
-        let method_ty = tcx.mk_fn_ptr(ty::Binder(fn_sig));
+        let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig));
         debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
                method_ty,
                obligation);
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 073f36b9f3c..5c1ca44f9f5 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -650,7 +650,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             .filter_map(|predicate| {
                 match *predicate {
                     ty::Predicate::Trait(ref trait_predicate) => {
-                        match trait_predicate.0.trait_ref.self_ty().sty {
+                        match trait_predicate.skip_binder().trait_ref.self_ty().sty {
                             ty::TyParam(ref p) if *p == param_ty => {
                                 Some(trait_predicate.to_poly_trait_ref())
                             }
@@ -1204,7 +1204,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 if !selcx.evaluate_obligation(&o) {
                     result = ProbeResult::NoMatch;
                     if let &ty::Predicate::Trait(ref pred) = &o.predicate {
-                        possibly_unsatisfied_predicates.push(pred.0.trait_ref);
+                        possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref);
                     }
                 }
             }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index acde10a6396..4083d4a21ef 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1727,7 +1727,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
             predicates: self.param_env.caller_bounds.iter().filter(|predicate| {
                 match **predicate {
                     ty::Predicate::Trait(ref data) => {
-                        data.0.self_ty().is_param(index)
+                        data.skip_binder().self_ty().is_param(index)
                     }
                     _ => false
                 }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 6348f386177..9c4807bec2f 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -508,7 +508,7 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
     let self_ty = fcx.normalize_associated_types_in(span, &self_ty);
     let self_ty = fcx.tcx.liberate_late_bound_regions(
         method.def_id,
-        &ty::Binder(self_ty)
+        &ty::Binder::bind(self_ty)
     );
 
     let self_arg_ty = sig.inputs()[0];
@@ -517,7 +517,7 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
     let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
     let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
         method.def_id,
-        &ty::Binder(self_arg_ty)
+        &ty::Binder::bind(self_arg_ty)
     );
 
     let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index a1eb043995a..fb8c6ba6401 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1171,7 +1171,7 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let inputs = fields.iter().map(|f| {
                 tcx.type_of(tcx.hir.local_def_id(f.id))
             });
-            ty::Binder(tcx.mk_fn_sig(
+            ty::Binder::bind(tcx.mk_fn_sig(
                 inputs,
                 ty,
                 false,
@@ -1434,7 +1434,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         for bound in &param.bounds {
             let bound_region = AstConv::ast_region_to_region(&icx, bound, None);
-            let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
+            let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound_region));
             predicates.push(outlives.to_predicate());
         }
     }
@@ -1482,7 +1482,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             let region = AstConv::ast_region_to_region(&icx,
                                                                        lifetime,
                                                                        None);
-                            let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
+                            let pred = ty::Binder::bind(ty::OutlivesPredicate(ty, region));
                             predicates.push(ty::Predicate::TypeOutlives(pred))
                         }
                     }
@@ -1493,7 +1493,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 let r1 = AstConv::ast_region_to_region(&icx, &region_pred.lifetime, None);
                 for bound in &region_pred.bounds {
                     let r2 = AstConv::ast_region_to_region(&icx, bound, None);
-                    let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
+                    let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2));
                     predicates.push(ty::Predicate::RegionOutlives(pred))
                 }
             }
@@ -1627,7 +1627,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
         }
         hir::RegionTyParamBound(ref lifetime) => {
             let region = astconv.ast_region_to_region(lifetime, None);
-            let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
+            let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region));
             vec![ty::Predicate::TypeOutlives(pred)]
         }
         hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index ed0cfe38a7a..d29ee3d9b3a 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -212,7 +212,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 tcx.mk_nil()
             };
 
-            let se_ty = tcx.mk_fn_ptr(ty::Binder(
+            let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
                 tcx.mk_fn_sig(
                     iter::empty(),
                     expected_return_type,
@@ -261,7 +261,7 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 _ => ()
             }
 
-            let se_ty = tcx.mk_fn_ptr(ty::Binder(
+            let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(
                 tcx.mk_fn_sig(
                     [
                         tcx.types.isize,
diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs
index ac53a6d4a3f..65c78d3593f 100644
--- a/src/librustc_typeck/outlives/implicit_infer.rs
+++ b/src/librustc_typeck/outlives/implicit_infer.rs
@@ -258,7 +258,7 @@ fn check_explicit_predicates<'tcx>(
                 // where OutlivesPredicate<type1, region1> is the predicate
                 // we want to add.
                 ty::Predicate::TypeOutlives(poly) => {
-                    let predicate = poly.0.subst(tcx, substs);
+                    let predicate = poly.skip_binder().subst(tcx, substs);
                     insert_outlives_predicate(
                         tcx,
                         predicate.0.into(),
@@ -271,7 +271,7 @@ fn check_explicit_predicates<'tcx>(
                 // where OutlivesPredicate<region1, region2> is the predicate
                 // we want to add.
                 ty::Predicate::RegionOutlives(poly) => {
-                    let predicate = poly.0.subst(tcx, substs);
+                    let predicate = poly.skip_binder().subst(tcx, substs);
                     insert_outlives_predicate(
                         tcx,
                         predicate.0.into(),
diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs
index bad0c68a6fe..e5af4c60691 100644
--- a/src/librustc_typeck/outlives/mod.rs
+++ b/src/librustc_typeck/outlives/mod.rs
@@ -89,11 +89,11 @@ fn inferred_outlives_crate<'tcx>(
             let vec: Vec<ty::Predicate<'tcx>> = set.iter()
                 .map(
                     |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
-                        UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder(
+                        UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder::bind(
                             ty::OutlivesPredicate(ty1, region2),
                         )),
                         UnpackedKind::Lifetime(region1) => ty::Predicate::RegionOutlives(
-                            ty::Binder(ty::OutlivesPredicate(region1, region2)),
+                            ty::Binder::bind(ty::OutlivesPredicate(region1, region2)),
                         ),
                     },
                 )
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index a24e501aba9..b5e7effa61e 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -313,11 +313,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
                 if let Some(p) = data.principal() {
                     let poly_trait_ref = p.with_self_ty(self.tcx(), self.tcx().types.err);
-                    self.add_constraints_from_trait_ref(current, poly_trait_ref.0, variance);
+                    self.add_constraints_from_trait_ref(
+                        current, *poly_trait_ref.skip_binder(), variance);
                 }
 
                 for projection in data.projection_bounds() {
-                    self.add_constraints_from_ty(current, projection.0.ty, self.invariant);
+                    self.add_constraints_from_ty(
+                        current, projection.skip_binder().ty, self.invariant);
                 }
             }
 
@@ -399,10 +401,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                 sig: ty::PolyFnSig<'tcx>,
                                 variance: VarianceTermPtr<'a>) {
         let contra = self.contravariant(variance);
-        for &input in sig.0.inputs() {
+        for &input in sig.skip_binder().inputs() {
             self.add_constraints_from_ty(current, input, contra);
         }
-        self.add_constraints_from_ty(current, sig.0.output(), variance);
+        self.add_constraints_from_ty(current, sig.skip_binder().output(), variance);
     }
 
     /// Adds constraints appropriate for a region appearing in a
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 52d5dbe3f05..477b576ad21 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -286,7 +286,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
             substs: tcx.mk_substs_trait(ty, &[]),
         };
 
-        let trait_pred = ty::Binder(trait_ref);
+        let trait_pred = ty::Binder::bind(trait_ref);
 
         let bail_out = tcx.infer_ctxt().enter(|infcx| {
             let mut selcx = SelectionContext::with_negative(&infcx, true);
@@ -622,7 +622,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
 
         let mut already_visited = FxHashSet();
         let mut predicates = VecDeque::new();
-        predicates.push_back(ty::Binder(ty::TraitPredicate {
+        predicates.push_back(ty::Binder::bind(ty::TraitPredicate {
             trait_ref: ty::TraitRef {
                 def_id: trait_did,
                 substs: infcx.tcx.mk_substs_trait(ty, &[]),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 443caa7618d..e37b3a7fcc4 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -120,7 +120,7 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
 
 impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
     fn clean(&self, cx: &DocContext) -> U {
-        self.0.clean(cx)
+        self.skip_binder().clean(cx)
     }
 }
 
@@ -2846,15 +2846,15 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     }
 
                     let mut bindings = vec![];
-                    for ty::Binder(ref pb) in obj.projection_bounds() {
+                    for pb in obj.projection_bounds() {
                         bindings.push(TypeBinding {
-                            name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx),
-                            ty: pb.ty.clean(cx)
+                            name: cx.tcx.associated_item(pb.item_def_id()).name.clean(cx),
+                            ty: pb.skip_binder().ty.clean(cx)
                         });
                     }
 
                     let path = external_path(cx, &cx.tcx.item_name(did), Some(did),
-                        false, bindings, principal.0.substs);
+                        false, bindings, principal.skip_binder().substs);
                     ResolvedPath {
                         path,
                         typarams: Some(typarams),
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 0eb4f9ba7e5..b7767606a6a 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -154,7 +154,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId,
     let predicates = cx.tcx.super_predicates_of(child).predicates;
     predicates.iter().filter_map(|pred| {
         if let ty::Predicate::Trait(ref pred) = *pred {
-            if pred.0.trait_ref.self_ty().is_self() {
+            if pred.skip_binder().trait_ref.self_ty().is_self() {
                 Some(pred.def_id())
             } else {
                 None