about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJack Huey <jack.huey@umassmed.edu>2020-10-07 20:02:06 -0400
committerJack Huey <jack.huey@umassmed.edu>2020-10-16 12:58:50 -0400
commitdd5c9bf1392bdc697740e62a1924b7942cdfd86a (patch)
treed98fd43351d17cd47664b76ec663a250f534cc23
parenta78a62fc996ba16f7a111c99520b23f77029f4eb (diff)
downloadrust-dd5c9bf1392bdc697740e62a1924b7942cdfd86a.tar.gz
rust-dd5c9bf1392bdc697740e62a1924b7942cdfd86a.zip
Use map_bound(_ref) instead of Binder::bind when possible
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs26
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs6
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs4
-rw-r--r--compiler/rustc_infer/src/traits/util.rs5
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs3
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs7
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs31
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs42
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs34
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs7
-rw-r--r--compiler/rustc_typeck/src/check/closure.rs3
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs5
-rw-r--r--compiler/rustc_typeck/src/check/dropck.rs14
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs4
-rw-r--r--compiler/rustc_typeck/src/check/method/probe.rs43
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs8
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs5
-rw-r--r--compiler/rustc_typeck/src/lib.rs2
-rw-r--r--src/librustdoc/clean/auto_trait.rs17
24 files changed, 173 insertions, 143 deletions
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index e78a4ea2e3c..e1f675e3ae9 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -673,17 +673,9 @@ fn codegen_emcc_try(
 fn gen_fn<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     name: &str,
-    inputs: Vec<Ty<'tcx>>,
-    output: Ty<'tcx>,
+    rust_fn_sig: ty::PolyFnSig<'tcx>,
     codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
 ) -> &'ll Value {
-    let rust_fn_sig = ty::Binder::bind(cx.tcx.mk_fn_sig(
-        inputs.into_iter(),
-        output,
-        false,
-        hir::Unsafety::Unsafe,
-        Abi::Rust,
-    ));
     let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
     let llfn = cx.declare_fn(name, &fn_abi);
     cx.set_frame_pointer_elimination(llfn);
@@ -710,14 +702,16 @@ fn get_rust_try_fn<'ll, '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 try_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
+    // `unsafe fn(*mut i8) -> ()`
+    let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
         iter::once(i8p),
         tcx.mk_unit(),
         false,
         hir::Unsafety::Unsafe,
         Abi::Rust,
     )));
-    let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
+    // `unsafe fn(*mut i8, *mut i8) -> ()`
+    let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
         [i8p, i8p].iter().cloned(),
         tcx.mk_unit(),
         false,
@@ -725,7 +719,15 @@ fn get_rust_try_fn<'ll, 'tcx>(
         Abi::Rust,
     )));
     let output = tcx.types.i32;
-    let rust_try = gen_fn(cx, "__rust_try", vec![try_fn_ty, i8p, catch_fn_ty], output, codegen);
+    // `unsafe fn(unsafe fn(*mut i8) -> (), unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
+    let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig(
+        vec![try_fn_ty, i8p, catch_fn_ty].into_iter(),
+        output,
+        false,
+        hir::Unsafety::Unsafe,
+        Abi::Rust,
+    ));
+    let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen);
     cx.rust_try_fn.set(Some(rust_try));
     rust_try
 }
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 6a1715ef818..afa6a2a8166 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -551,7 +551,8 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
-        Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
+        let result = self.relate(a.skip_binder(), b.skip_binder())?;
+        Ok(a.map_bound(|_| result))
     }
 
     fn relate_item_substs(
@@ -833,7 +834,8 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
     where
         T: Relate<'tcx>,
     {
-        Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
+        let result = self.relate(a.skip_binder(), b.skip_binder())?;
+        Ok(a.map_bound(|_| result))
     }
 
     fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 2fb9f638e36..b1ec7a7902d 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -636,7 +636,7 @@ where
         if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) {
             // Fast path for the common case.
             self.relate(a, b)?;
-            return Ok(ty::Binder::bind(a));
+            return Ok(ty::Binder::dummy(a));
         }
 
         if self.ambient_covariance() {
@@ -1004,6 +1004,6 @@ where
         self.first_free_index.shift_in(1);
         let result = self.relate(a.skip_binder(), a.skip_binder())?;
         self.first_free_index.shift_out(1);
-        Ok(ty::Binder::bind(result))
+        Ok(a.map_bound(|_| result))
     }
 }
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 1b7269706a7..043d24c9767 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -126,14 +126,15 @@ impl Elaborator<'tcx> {
     fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
         let tcx = self.visited.tcx;
 
-        match obligation.predicate.skip_binders() {
+        let bound_predicate = obligation.predicate.bound_atom(tcx);
+        match bound_predicate.skip_binder() {
             ty::PredicateAtom::Trait(data, _) => {
                 // Get predicates declared on the trait.
                 let predicates = tcx.super_predicates_of(data.def_id());
 
                 let obligations = predicates.predicates.iter().map(|&(pred, _)| {
                     predicate_obligation(
-                        pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)),
+                        pred.subst_supertrait(tcx, &bound_predicate.map_bound(|_| data.trait_ref)),
                         obligation.param_env,
                         obligation.cause.clone(),
                     )
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index 27bccc0bcaf..5f5593eb0d8 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -118,6 +118,7 @@ impl TypeRelation<'tcx> for Match<'tcx> {
     where
         T: Relate<'tcx>,
     {
-        Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?))
+        let result = self.relate(a.skip_binder(), b.skip_binder())?;
+        Ok(a.map_bound(|_| result))
     }
 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 08f88eed66f..20dc49991b4 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -618,10 +618,9 @@ pub trait PrettyPrinter<'tcx>:
                         // may contain unbound variables. We therefore do this manually.
                         //
                         // FIXME(lcnr): Find out why exactly this is the case :)
-                        if let ty::PredicateAtom::Trait(pred, _) =
-                            predicate.bound_atom(self.tcx()).skip_binder()
-                        {
-                            let trait_ref = ty::Binder::bind(pred.trait_ref);
+                        let bound_predicate = predicate.bound_atom(self.tcx());
+                        if let ty::PredicateAtom::Trait(pred, _) = bound_predicate.skip_binder() {
+                            let trait_ref = bound_predicate.map_bound(|_| pred.trait_ref);
                             // Don't print +Sized, but rather +?Sized if absent.
                             if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
                                 is_sized = true;
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 597ceac9386..5f326d700ee 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -549,7 +549,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateAtom<'a> {
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> {
     type Lifted = ty::Binder<T::Lifted>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(self.as_ref().skip_binder()).map(ty::Binder::bind)
+        tcx.lift(self.as_ref().skip_binder()).map(|v| self.map_bound_ref(|_| v))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 870cc4eee05..932cadee100 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -702,15 +702,19 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
     pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
         use crate::ty::ToPredicate;
         match self.skip_binder() {
-            ExistentialPredicate::Trait(tr) => {
-                Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx)
-            }
+            ExistentialPredicate::Trait(tr) => self
+                .map_bound_ref(|_| tr)
+                .with_self_ty(tcx, self_ty)
+                .without_const()
+                .to_predicate(tcx),
             ExistentialPredicate::Projection(p) => {
-                Binder(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
+                self.map_bound_ref(|_| p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
             }
             ExistentialPredicate::AutoTrait(did) => {
-                let trait_ref =
-                    Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) });
+                let trait_ref = self.map_bound_ref(|_| ty::TraitRef {
+                    def_id: did,
+                    substs: tcx.mk_substs_trait(self_ty, &[]),
+                });
                 trait_ref.without_const().to_predicate(tcx)
             }
         }
@@ -775,7 +779,7 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
 
 impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
     pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
-        self.skip_binder().principal().map(Binder::bind)
+        self.map_bound_ref(|b| b.principal()).transpose()
     }
 
     pub fn principal_def_id(&self) -> Option<DefId> {
@@ -858,8 +862,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
     }
 
     pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
-        // Note that we preserve binding levels
-        Binder(ty::TraitPredicate { trait_ref: self.skip_binder() })
+        self.map_bound(|trait_ref| ty::TraitPredicate { trait_ref })
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index e40067202e1..96a0c339e18 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -642,7 +642,8 @@ impl AutoTraitFinder<'tcx> {
             // We check this by calling is_of_param on the relevant types
             // from the various possible predicates
 
-            match predicate.skip_binders() {
+            let bound_predicate = predicate.bound_atom(select.infcx().tcx);
+            match bound_predicate.skip_binder() {
                 ty::PredicateAtom::Trait(p, _) => {
                     if self.is_param_no_infer(p.trait_ref.substs)
                         && !only_projections
@@ -650,10 +651,10 @@ impl AutoTraitFinder<'tcx> {
                     {
                         self.add_user_pred(computed_preds, predicate);
                     }
-                    predicates.push_back(ty::Binder::bind(p));
+                    predicates.push_back(bound_predicate.map_bound_ref(|_| p));
                 }
                 ty::PredicateAtom::Projection(p) => {
-                    let p = ty::Binder::bind(p);
+                    let p = bound_predicate.map_bound_ref(|_| p);
                     debug!(
                         "evaluate_nested_obligations: examining projection predicate {:?}",
                         predicate
@@ -783,13 +784,13 @@ impl AutoTraitFinder<'tcx> {
                     }
                 }
                 ty::PredicateAtom::RegionOutlives(binder) => {
-                    let binder = ty::Binder::bind(binder);
+                    let binder = bound_predicate.map_bound_ref(|_| binder);
                     if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
                         return false;
                     }
                 }
                 ty::PredicateAtom::TypeOutlives(binder) => {
-                    let binder = ty::Binder::bind(binder);
+                    let binder = bound_predicate.map_bound_ref(|_| binder);
                     match (
                         binder.no_bound_vars(),
                         binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 05e3ed34351..3c4394e7d03 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -255,9 +255,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     return;
                 }
 
-                match obligation.predicate.skip_binders() {
+                let bound_predicate = obligation.predicate.bound_atom(self.tcx);
+                match bound_predicate.skip_binder() {
                     ty::PredicateAtom::Trait(trait_predicate, _) => {
-                        let trait_predicate = ty::Binder::bind(trait_predicate);
+                        let trait_predicate = bound_predicate.map_bound_ref(|_| trait_predicate);
                         let trait_predicate = self.resolve_vars_if_possible(&trait_predicate);
 
                         if self.tcx.sess.has_errors() && trait_predicate.references_error() {
@@ -531,7 +532,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     }
 
                     ty::PredicateAtom::RegionOutlives(predicate) => {
-                        let predicate = ty::Binder::bind(predicate);
+                        let predicate = bound_predicate.map_bound_ref(|_| predicate);
                         let predicate = self.resolve_vars_if_possible(&predicate);
                         let err = self
                             .region_outlives_predicate(&obligation.cause, predicate)
@@ -1078,9 +1079,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
         }
 
         // FIXME: It should be possible to deal with `ForAll` in a cleaner way.
-        let (cond, error) = match (cond.skip_binders(), error.skip_binders()) {
+        let bound_error = error.bound_atom(self.tcx);
+        let (cond, error) = match (cond.skip_binders(), bound_error.skip_binder()) {
             (ty::PredicateAtom::Trait(..), ty::PredicateAtom::Trait(error, _)) => {
-                (cond, ty::Binder::bind(error))
+                (cond, bound_error.map_bound_ref(|_| error))
             }
             _ => {
                 // FIXME: make this work in other cases too.
@@ -1089,9 +1091,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
         };
 
         for obligation in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
-            if let ty::PredicateAtom::Trait(implication, _) = obligation.predicate.skip_binders() {
+            let bound_predicate = obligation.predicate.bound_atom(self.tcx);
+            if let ty::PredicateAtom::Trait(implication, _) = bound_predicate.skip_binder() {
                 let error = error.to_poly_trait_ref();
-                let implication = ty::Binder::bind(implication.trait_ref);
+                let implication = bound_predicate.map_bound_ref(|_| implication.trait_ref);
                 // FIXME: I'm just not taking associated types at all here.
                 // Eventually I'll need to implement param-env-aware
                 // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
@@ -1169,12 +1172,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             //
             // this can fail if the problem was higher-ranked, in which
             // cause I have no idea for a good error message.
-            if let ty::PredicateAtom::Projection(data) = predicate.skip_binders() {
+            let bound_predicate = predicate.bound_atom(self.tcx);
+            if let ty::PredicateAtom::Projection(data) = bound_predicate.skip_binder() {
                 let mut selcx = SelectionContext::new(self);
                 let (data, _) = self.replace_bound_vars_with_fresh_vars(
                     obligation.cause.span,
                     infer::LateBoundRegionConversionTime::HigherRankedType,
-                    &ty::Binder::bind(data),
+                    &bound_predicate.map_bound_ref(|_| data),
                 );
                 let mut obligations = vec![];
                 let normalized_ty = super::normalize_projection_type(
@@ -1455,10 +1459,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             return;
         }
 
-        let mut err = match predicate.skip_binders() {
+        let bound_predicate = predicate.bound_atom(self.tcx);
+        let mut err = match bound_predicate.skip_binder() {
             ty::PredicateAtom::Trait(data, _) => {
-                let trait_ref = ty::Binder::bind(data.trait_ref);
-                let self_ty = trait_ref.skip_binder().self_ty();
+                let self_ty = data.trait_ref.self_ty();
+                let trait_ref = bound_predicate.map_bound_ref(|_| data.trait_ref);
                 debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind(), trait_ref);
 
                 if predicate.references_error() {
@@ -1582,7 +1587,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                 self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282)
             }
             ty::PredicateAtom::Projection(data) => {
-                let trait_ref = ty::Binder::bind(data).to_poly_trait_ref(self.tcx);
+                let trait_ref = bound_predicate.map_bound_ref(|_| data).to_poly_trait_ref(self.tcx);
                 let self_ty = trait_ref.skip_binder().self_ty();
                 let ty = data.ty;
                 if predicate.references_error() {
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 97dd180b27b..01217457eb4 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -353,7 +353,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
                 // This means we need to pass it the bound version of our
                 // predicate.
                 ty::PredicateAtom::Trait(trait_ref, _constness) => {
-                    let trait_obligation = obligation.with(Binder::bind(trait_ref));
+                    let trait_obligation = obligation.with(binder.map_bound_ref(|_| trait_ref));
 
                     self.process_trait_obligation(
                         obligation,
@@ -362,7 +362,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
                     )
                 }
                 ty::PredicateAtom::Projection(data) => {
-                    let project_obligation = obligation.with(Binder::bind(data));
+                    let project_obligation = obligation.with(binder.map_bound_ref(|_| data));
 
                     self.process_projection_obligation(
                         project_obligation,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 8dbf7ec51c6..295ba6041fb 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -623,7 +623,8 @@ fn prune_cache_value_obligations<'a, 'tcx>(
         .obligations
         .iter()
         .filter(|obligation| {
-            match obligation.predicate.skip_binders() {
+            let bound_predicate = obligation.predicate.bound_atom(infcx.tcx);
+            match bound_predicate.skip_binder() {
                 // We found a `T: Foo<X = U>` predicate, let's check
                 // if `U` references any unresolved type
                 // variables. In principle, we only care if this
@@ -633,9 +634,9 @@ fn prune_cache_value_obligations<'a, 'tcx>(
                 // indirect obligations (e.g., we project to `?0`,
                 // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
                 // ?0>`).
-                ty::PredicateAtom::Projection(data) => {
-                    infcx.unresolved_type_vars(&ty::Binder::bind(data.ty)).is_some()
-                }
+                ty::PredicateAtom::Projection(data) => infcx
+                    .unresolved_type_vars(&bound_predicate.map_bound_ref(|_| data.ty))
+                    .is_some(),
 
                 // We are only interested in `T: Foo<X = U>` predicates, whre
                 // `U` references one of `unresolved_type_vars`. =)
@@ -907,8 +908,9 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
     let infcx = selcx.infcx();
     for predicate in env_predicates {
         debug!(?predicate);
+        let bound_predicate = predicate.bound_atom(infcx.tcx);
         if let ty::PredicateAtom::Projection(data) = predicate.skip_binders() {
-            let data = ty::Binder::bind(data);
+            let data = bound_predicate.map_bound_ref(|_| data);
             let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
 
             let is_match = same_def_id
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 4d347380c6c..29c9c29d208 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -449,16 +449,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         let result = ensure_sufficient_stack(|| {
-            match obligation.predicate.skip_binders() {
+            let bound_predicate = obligation.predicate.bound_atom(self.infcx().tcx);
+            match bound_predicate.skip_binder() {
                 ty::PredicateAtom::Trait(t, _) => {
-                    let t = ty::Binder::bind(t);
+                    let t = bound_predicate.map_bound_ref(|_| t);
                     debug_assert!(!t.has_escaping_bound_vars());
                     let obligation = obligation.with(t);
                     self.evaluate_trait_predicate_recursively(previous_stack, obligation)
                 }
 
                 ty::PredicateAtom::Subtype(p) => {
-                    let p = ty::Binder::bind(p);
+                    let p = bound_predicate.map_bound_ref(|_| p);
                     // Does this code ever run?
                     match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
                         Some(Ok(InferOk { mut obligations, .. })) => {
@@ -502,7 +503,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
 
                 ty::PredicateAtom::Projection(data) => {
-                    let data = ty::Binder::bind(data);
+                    let data = bound_predicate.map_bound_ref(|_| data);
                     let project_obligation = obligation.with(data);
                     match project::poly_project_and_unify_type(self, &project_obligation) {
                         Ok(Ok(Some(mut subobligations))) => {
@@ -1174,8 +1175,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .iter()
             .enumerate()
             .filter_map(|(idx, bound)| {
-                if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() {
-                    let bound = ty::Binder::bind(pred.trait_ref);
+                let bound_predicate = bound.bound_atom(self.infcx.tcx);
+                if let ty::PredicateAtom::Trait(pred, _) = bound_predicate.skip_binder() {
+                    let bound = bound_predicate.map_bound_ref(|_| pred.trait_ref);
                     if self.infcx.probe(|_| {
                         match self.match_projection(
                             obligation,
@@ -1529,16 +1531,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
 
-            ty::Tuple(tys) => {
-                Where(ty::Binder::bind(tys.last().into_iter().map(|k| k.expect_ty()).collect()))
-            }
+            ty::Tuple(tys) => Where(
+                obligation
+                    .predicate
+                    .map_bound_ref(|_| tys.last().into_iter().map(|k| k.expect_ty()).collect()),
+            ),
 
             ty::Adt(def, substs) => {
                 let sized_crit = def.sized_constraint(self.tcx());
                 // (*) binder moved here
-                Where(ty::Binder::bind(
-                    sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect(),
-                ))
+                Where(obligation.predicate.map_bound_ref(|_| {
+                    sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect()
+                }))
             }
 
             ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
@@ -1590,12 +1594,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             ty::Array(element_ty, _) => {
                 // (*) binder moved here
-                Where(ty::Binder::bind(vec![element_ty]))
+                Where(obligation.predicate.map_bound_ref(|_| vec![*element_ty]))
             }
 
             ty::Tuple(tys) => {
                 // (*) binder moved here
-                Where(ty::Binder::bind(tys.iter().map(|k| k.expect_ty()).collect()))
+                Where(
+                    obligation
+                        .predicate
+                        .map_bound_ref(|_| tys.iter().map(|k| k.expect_ty()).collect()),
+                )
             }
 
             ty::Closure(_, substs) => {
@@ -1605,7 +1613,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // Not yet resolved.
                     Ambiguous
                 } else {
-                    Where(ty::Binder::bind(substs.as_closure().upvar_tys().collect()))
+                    Where(
+                        obligation
+                            .predicate
+                            .map_bound_ref(|_| substs.as_closure().upvar_tys().collect()),
+                    )
                 }
             }
 
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 391251b6fa5..2ca94c6444a 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -762,27 +762,19 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru
         self,
         interner: &RustInterner<'tcx>,
     ) -> Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>> {
-        match self.bound_atom(interner.tcx).skip_binder() {
-            ty::PredicateAtom::Trait(predicate, _) => {
-                let (predicate, binders, _named_regions) =
-                    collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate));
-
-                Some(chalk_ir::Binders::new(
-                    binders,
-                    chalk_solve::rust_ir::InlineBound::TraitBound(
-                        predicate.trait_ref.lower_into(interner),
-                    ),
-                ))
-            }
-            ty::PredicateAtom::Projection(predicate) => {
-                let (predicate, binders, _named_regions) =
-                    collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate));
-
-                Some(chalk_ir::Binders::new(
-                    binders,
-                    chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
-                ))
-            }
+        let (predicate, binders, _named_regions) =
+            collect_bound_vars(interner, interner.tcx, &self.bound_atom(interner.tcx));
+        match predicate {
+            ty::PredicateAtom::Trait(predicate, _) => Some(chalk_ir::Binders::new(
+                binders,
+                chalk_solve::rust_ir::InlineBound::TraitBound(
+                    predicate.trait_ref.lower_into(interner),
+                ),
+            )),
+            ty::PredicateAtom::Projection(predicate) => Some(chalk_ir::Binders::new(
+                binders,
+                chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
+            )),
             ty::PredicateAtom::TypeOutlives(_predicate) => None,
             ty::PredicateAtom::WellFormed(_ty) => None,
 
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 170ca2ce744..cea7eaec9a7 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1095,9 +1095,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     obligation.predicate
                 );
 
-                match obligation.predicate.skip_binders() {
+                let bound_predicate = obligation.predicate.bound_atom(tcx);
+                match bound_predicate.skip_binder() {
                     ty::PredicateAtom::Trait(pred, _) => {
-                        let pred = ty::Binder::bind(pred);
+                        let pred = bound_predicate.map_bound_ref(|_| pred);
                         associated_types.entry(span).or_default().extend(
                             tcx.associated_items(pred.def_id())
                                 .in_definition_order()
@@ -1106,7 +1107,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         );
                     }
                     ty::PredicateAtom::Projection(pred) => {
-                        let pred = ty::Binder::bind(pred);
+                        let pred = bound_predicate.map_bound_ref(|_| pred);
                         // A `Self` within the original bound will be substituted with a
                         // `trait_object_dummy_self`, so check for that.
                         let references_self =
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs
index 8bdd933644a..500cc92921b 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_typeck/src/check/closure.rs
@@ -192,6 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     obligation.predicate
                 );
 
+                let bound_predicate = obligation.predicate.bound_atom(self.tcx);
                 if let ty::PredicateAtom::Projection(proj_predicate) =
                     obligation.predicate.skip_binders()
                 {
@@ -199,7 +200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // the complete signature.
                     self.deduce_sig_from_projection(
                         Some(obligation.cause.span),
-                        ty::Binder::bind(proj_predicate),
+                        bound_predicate.map_bound_ref(|_| proj_predicate),
                     )
                 } else {
                     None
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index db32a736181..0eb5593e8bd 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -583,7 +583,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         while !queue.is_empty() {
             let obligation = queue.remove(0);
             debug!("coerce_unsized resolve step: {:?}", obligation);
-            let trait_pred = match obligation.predicate.skip_binders() {
+            let bound_predicate = obligation.predicate.bound_atom(self.tcx);
+            let trait_pred = match bound_predicate.skip_binder() {
                 ty::PredicateAtom::Trait(trait_pred, _)
                     if traits.contains(&trait_pred.def_id()) =>
                 {
@@ -594,7 +595,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                             has_unsized_tuple_coercion = true;
                         }
                     }
-                    ty::Binder::bind(trait_pred)
+                    bound_predicate.map_bound_ref(|_| trait_pred)
                 }
                 _ => {
                     coercion.obligations.push(obligation);
diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs
index ae94a6df5fd..c777b87d488 100644
--- a/compiler/rustc_typeck/src/check/dropck.rs
+++ b/compiler/rustc_typeck/src/check/dropck.rs
@@ -226,13 +226,15 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
         // could be extended easily also to the other `Predicate`.
         let predicate_matches_closure = |p: Predicate<'tcx>| {
             let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
+            let bound_predicate = predicate.bound_atom(tcx);
+            let bound_p = p.bound_atom(tcx);
             match (predicate.skip_binders(), p.skip_binders()) {
-                (ty::PredicateAtom::Trait(a, _), ty::PredicateAtom::Trait(b, _)) => {
-                    relator.relate(ty::Binder::bind(a), ty::Binder::bind(b)).is_ok()
-                }
-                (ty::PredicateAtom::Projection(a), ty::PredicateAtom::Projection(b)) => {
-                    relator.relate(ty::Binder::bind(a), ty::Binder::bind(b)).is_ok()
-                }
+                (ty::PredicateAtom::Trait(a, _), ty::PredicateAtom::Trait(b, _)) => relator
+                    .relate(bound_predicate.map_bound_ref(|_| a), bound_p.map_bound_ref(|_| b))
+                    .is_ok(),
+                (ty::PredicateAtom::Projection(a), ty::PredicateAtom::Projection(b)) => relator
+                    .relate(bound_predicate.map_bound_ref(|_| a), bound_p.map_bound_ref(|_| b))
+                    .is_ok(),
                 _ => predicate == p,
             }
         };
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index 2ee867c2dd6..f40a250200e 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -328,14 +328,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
 
             kw::Try => {
                 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
-                let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
+                let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
                     iter::once(mut_u8),
                     tcx.mk_unit(),
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust,
                 ));
-                let catch_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
+                let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
                     [mut_u8, mut_u8].iter().cloned(),
                     tcx.mk_unit(),
                     false,
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index c1ba29284da..e6e7e229f88 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -796,29 +796,30 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         // FIXME: do we want to commit to this behavior for param bounds?
         debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
 
-        let bounds =
-            self.param_env.caller_bounds().iter().map(ty::Predicate::skip_binders).filter_map(
-                |predicate| match predicate {
-                    ty::PredicateAtom::Trait(trait_predicate, _) => {
-                        match trait_predicate.trait_ref.self_ty().kind() {
-                            ty::Param(ref p) if *p == param_ty => {
-                                Some(ty::Binder::bind(trait_predicate.trait_ref))
-                            }
-                            _ => None,
+        let tcx = self.tcx;
+        let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
+            let bound_predicate = predicate.bound_atom(tcx);
+            match bound_predicate.skip_binder() {
+                ty::PredicateAtom::Trait(trait_predicate, _) => {
+                    match trait_predicate.trait_ref.self_ty().kind() {
+                        ty::Param(ref p) if *p == param_ty => {
+                            Some(bound_predicate.map_bound_ref(|_| trait_predicate.trait_ref))
                         }
+                        _ => None,
                     }
-                    ty::PredicateAtom::Subtype(..)
-                    | ty::PredicateAtom::Projection(..)
-                    | ty::PredicateAtom::RegionOutlives(..)
-                    | ty::PredicateAtom::WellFormed(..)
-                    | ty::PredicateAtom::ObjectSafe(..)
-                    | ty::PredicateAtom::ClosureKind(..)
-                    | ty::PredicateAtom::TypeOutlives(..)
-                    | ty::PredicateAtom::ConstEvaluatable(..)
-                    | ty::PredicateAtom::ConstEquate(..)
-                    | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
-                },
-            );
+                }
+                ty::PredicateAtom::Subtype(..)
+                | ty::PredicateAtom::Projection(..)
+                | ty::PredicateAtom::RegionOutlives(..)
+                | ty::PredicateAtom::WellFormed(..)
+                | ty::PredicateAtom::ObjectSafe(..)
+                | ty::PredicateAtom::ClosureKind(..)
+                | ty::PredicateAtom::TypeOutlives(..)
+                | ty::PredicateAtom::ConstEvaluatable(..)
+                | ty::PredicateAtom::ConstEquate(..)
+                | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+            }
+        });
 
         self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
             let trait_ref = this.erase_late_bound_regions(&poly_trait_ref);
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index e33a4e98c59..d1d6d002d4c 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -637,9 +637,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     };
                     let mut format_pred = |pred: ty::Predicate<'tcx>| {
-                        match pred.skip_binders() {
+                        let bound_predicate = pred.bound_atom(tcx);
+                        match bound_predicate.skip_binder() {
                             ty::PredicateAtom::Projection(pred) => {
-                                let pred = ty::Binder::bind(pred);
+                                let pred = bound_predicate.map_bound_ref(|_| pred);
                                 // `<Foo as Iterator>::Item = String`.
                                 let trait_ref =
                                     pred.skip_binder().projection_ty.trait_ref(self.tcx);
@@ -658,8 +659,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 Some((obligation, trait_ref.self_ty()))
                             }
                             ty::PredicateAtom::Trait(poly_trait_ref, _) => {
-                                let poly_trait_ref = ty::Binder::bind(poly_trait_ref);
-                                let p = poly_trait_ref.skip_binder().trait_ref;
+                                let p = poly_trait_ref.trait_ref;
                                 let self_ty = p.self_ty();
                                 let path = p.print_only_trait_path();
                                 let obligation = format!("{}: {}", self_ty, path);
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 24ffe944128..124ba91f74c 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -850,7 +850,8 @@ fn bounds_from_generic_predicates<'tcx>(
     let mut projections = vec![];
     for (predicate, _) in predicates.predicates {
         debug!("predicate {:?}", predicate);
-        match predicate.skip_binders() {
+        let bound_predicate = predicate.bound_atom(tcx);
+        match bound_predicate.skip_binder() {
             ty::PredicateAtom::Trait(trait_predicate, _) => {
                 let entry = types.entry(trait_predicate.self_ty()).or_default();
                 let def_id = trait_predicate.def_id();
@@ -861,7 +862,7 @@ fn bounds_from_generic_predicates<'tcx>(
                 }
             }
             ty::PredicateAtom::Projection(projection_pred) => {
-                projections.push(ty::Binder::bind(projection_pred));
+                projections.push(bound_predicate.map_bound_ref(|_| projection_pred));
             }
             _ => {}
         }
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 7efda54fbe0..c1fa39e96eb 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -317,7 +317,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
                 }
             }
 
-            let se_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig(
+            let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
                 [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
                 tcx.types.isize,
                 false,
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 1ea1a091069..f6a4dfd85a5 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -315,13 +315,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
         tcx: TyCtxt<'tcx>,
         pred: ty::Predicate<'tcx>,
     ) -> FxHashSet<GenericParamDef> {
-        let regions = match pred.skip_binders() {
-            ty::PredicateAtom::Trait(poly_trait_pred, _) => {
-                tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(poly_trait_pred))
-            }
-            ty::PredicateAtom::Projection(poly_proj_pred) => {
-                tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(poly_proj_pred))
-            }
+        let bound_predicate = pred.bound_atom(tcx);
+        let regions = match bound_predicate.skip_binder() {
+            ty::PredicateAtom::Trait(poly_trait_pred, _) => tcx
+                .collect_referenced_late_bound_regions(
+                    &bound_predicate.map_bound_ref(|_| poly_trait_pred),
+                ),
+            ty::PredicateAtom::Projection(poly_proj_pred) => tcx
+                .collect_referenced_late_bound_regions(
+                    &bound_predicate.map_bound_ref(|_| poly_proj_pred),
+                ),
             _ => return FxHashSet::default(),
         };