about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-11-09 10:49:28 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-11-16 09:25:19 +0000
commit4f11f3b2571c895c08757aa91af57fc1091e45ef (patch)
treefa952f5375f2f1270bd3e4a794434e4836a383bf /compiler
parent634df06fae22066e2a9f2d3ce68c0fc7203bfa92 (diff)
downloadrust-4f11f3b2571c895c08757aa91af57fc1091e45ef.tar.gz
rust-4f11f3b2571c895c08757aa91af57fc1091e45ef.zip
Convert predicates into Predicate in the Obligation constructor
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs13
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs6
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs3
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs5
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs4
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs9
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs7
-rw-r--r--compiler/rustc_infer/src/infer/projection.rs10
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs6
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs29
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs31
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/relationships.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs69
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs44
-rw-r--r--compiler/rustc_traits/src/evaluate_obligation.rs2
-rw-r--r--compiler/rustc_traits/src/type_op.rs9
45 files changed, 248 insertions, 226 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index dd222485daf..b2db77944fd 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -7,9 +7,7 @@ use rustc_infer::infer::{DefiningAnchor, InferCtxt};
 use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{
-    self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable,
-};
+use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -256,8 +254,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         // Require the hidden type to be well-formed with only the generics of the opaque type.
         // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
         // hidden type is well formed even without those bounds.
-        let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
-            .to_predicate(infcx.tcx);
+        let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
 
         let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
 
@@ -282,6 +279,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         }
 
         ocx.register_obligation(Obligation::misc(
+            infcx.tcx,
             instantiated_ty.span,
             body_id,
             param_env,
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index ac44f47530e..d0cf8622a44 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -92,8 +92,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 trait_ref,
                 constness: ty::BoundConstness::NotConst,
                 polarity: ty::ImplPolarity::Positive,
-            }))
-            .to_predicate(self.tcx()),
+            })),
             locations,
             category,
         );
@@ -122,14 +121,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
     pub(super) fn prove_predicates(
         &mut self,
-        predicates: impl IntoIterator<Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>>>,
+        predicates: impl IntoIterator<
+            Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
+        >,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
         for predicate in predicates {
-            let predicate = predicate.to_predicate(self.tcx());
-            debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
-
             self.prove_predicate(predicate, locations, category);
         }
     }
@@ -137,11 +135,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     pub(super) fn prove_predicate(
         &mut self,
-        predicate: ty::Predicate<'tcx>,
+        predicate: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
         let param_env = self.param_env;
+        let predicate = predicate.to_predicate(self.tcx());
         self.fully_perform_op(
             locations,
             category,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 6ccc29b09c0..7d36a63943c 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -33,8 +33,7 @@ use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
     self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
-    OpaqueHiddenType, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType,
-    UserTypeAnnotationIndex,
+    OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
 };
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::{Span, DUMMY_SP};
@@ -1069,8 +1068,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
 
                     self.prove_predicate(
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into()))
-                            .to_predicate(self.tcx()),
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into())),
                         Locations::All(span),
                         ConstraintCategory::TypeAnnotation,
                     );
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 5a8b3e30b9f..36956f5dd6d 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -732,7 +732,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         polarity: ty::ImplPolarity::Positive,
                     });
                     let obligation =
-                        Obligation::new(ObligationCause::dummy(), param_env, poly_trait_pred);
+                        Obligation::new(tcx, ObligationCause::dummy(), param_env, poly_trait_pred);
 
                     let implsrc = {
                         let infcx = tcx.infer_ctxt().build();
@@ -816,6 +816,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                             if !nonconst_call_permission {
                                 let obligation = Obligation::new(
+                                    tcx,
                                     ObligationCause::dummy_with_span(*fn_span),
                                     param_env,
                                     tcx.mk_predicate(
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index b28d7019491..2d4afd0dc35 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -147,6 +147,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                 }
                 Adt(..) => {
                     let obligation = Obligation::new(
+                        tcx,
                         ObligationCause::dummy(),
                         param_env,
                         Binder::dummy(TraitPredicate {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index d995d533ca3..be6070e9178 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -156,6 +156,7 @@ impl Qualif for NeedsNonConstDrop {
         let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None);
 
         let obligation = Obligation::new(
+            cx.tcx,
             ObligationCause::dummy(),
             cx.param_env,
             ty::Binder::dummy(ty::TraitPredicate {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 0ba5e615101..f76b282fa76 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -19,9 +19,7 @@ use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{
-    self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
-};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
@@ -464,9 +462,8 @@ fn check_opaque_meets_bounds<'tcx>(
     // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
     // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
     // hidden type is well formed even without those bounds.
-    let predicate =
-        ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into())).to_predicate(tcx);
-    ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
+    let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into()));
+    ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate));
 
     // Check that all obligations are satisfied by the implementation's
     // version.
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 7c99896b457..ad3e5e034f3 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -238,7 +238,7 @@ fn compare_predicate_entailment<'tcx>(
                 kind: impl_m.kind,
             },
         );
-        ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
+        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
     }
 
     // We now need to check that the signature of the impl method is
@@ -605,6 +605,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
                 );
 
                 self.ocx.register_obligation(traits::Obligation::new(
+                    self.tcx(),
                     ObligationCause::new(
                         self.span,
                         self.body_id,
@@ -1579,7 +1580,7 @@ fn compare_type_predicate_entailment<'tcx>(
             },
         );
         ocx.register_obligations(obligations);
-        ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
+        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
     }
 
     // Check that all obligations are satisfied by the implementation's
@@ -1784,7 +1785,7 @@ pub fn check_type_bounds<'tcx>(
         .subst_iter_copied(tcx, rebased_substs)
         .map(|(concrete_ty_bound, span)| {
             debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
-            traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
+            traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
         })
         .collect();
     debug!("check_type_bounds: item_bounds={:?}", obligations);
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 837ff0bdf3e..2c932de537e 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -14,8 +14,8 @@ use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
-    self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
-    TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    self, AdtKind, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+    TypeVisitable, TypeVisitor,
 };
 use rustc_middle::ty::{GenericArgKind, InternalSubsts};
 use rustc_session::parse::feature_err;
@@ -75,9 +75,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
         // for a type to be WF, we do not need to check if const trait predicates satisfy.
         let param_env = self.param_env.without_const();
         self.ocx.register_obligation(traits::Obligation::new(
+            self.tcx(),
             cause,
             param_env,
-            ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx()),
+            ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
         ));
     }
 }
@@ -1111,12 +1112,12 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
                     traits::MiscObligation,
                 );
                 wfcx.register_obligation(traits::Obligation::new(
+                    tcx,
                     cause,
                     wfcx.param_env,
                     ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
                         ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
-                    ))
-                    .to_predicate(tcx),
+                    )),
                 ));
             }
         }
@@ -1453,7 +1454,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
                 wfcx.body_id,
                 traits::ItemObligation(def_id.to_def_id()),
             );
-            traits::Obligation::new(cause, wfcx.param_env, pred)
+            traits::Obligation::new(tcx, cause, wfcx.param_env, pred)
         });
 
     let predicates = predicates.0.instantiate_identity(tcx);
@@ -1783,8 +1784,7 @@ fn receiver_is_implemented<'tcx>(
         substs: tcx.mk_substs_trait(receiver_ty, &[]),
     });
 
-    let obligation =
-        traits::Obligation::new(cause, wfcx.param_env, trait_ref.without_const().to_predicate(tcx));
+    let obligation = traits::Obligation::new(tcx, cause, wfcx.param_env, trait_ref.without_const());
 
     if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {
         true
@@ -1931,6 +1931,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
                 }
 
                 let obligation = traits::Obligation::new(
+                    tcx,
                     traits::ObligationCause::new(span, self.body_id, traits::TrivialBound),
                     empty_env,
                     pred,
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index b0fdfcf38a6..4f9d5826583 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -5,7 +5,7 @@ use rustc_hir::{ForeignItem, ForeignItemKind, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder};
+use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_trait_selection::traits;
 
 pub fn provide(providers: &mut Providers) {
@@ -74,10 +74,10 @@ fn diagnostic_hir_wf_check<'tcx>(
             let errors = traits::fully_solve_obligation(
                 &infcx,
                 traits::Obligation::new(
+                    self.tcx,
                     cause,
                     self.param_env,
-                    ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into()))
-                        .to_predicate(self.tcx),
+                    ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())),
                 ),
             );
             if !errors.is_empty() {
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 6a4a6a5b0a5..139f2e84136 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diagnostic, MultiSpan};
 use rustc_hir::{self as hir, ExprKind};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::Obligation;
-use rustc_middle::ty::{self, ToPredicate, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
@@ -538,23 +538,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .bound_explicit_item_bounds(rpit_def_id)
                         .subst_iter_copied(self.tcx, substs)
                     {
-                        let pred = match pred.kind().skip_binder() {
+                        let pred = pred.kind().rebind(match pred.kind().skip_binder() {
                             ty::PredicateKind::Trait(mut trait_pred) => {
                                 assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
                                 trait_pred.trait_ref.substs =
                                     self.tcx.mk_substs_trait(ty, &trait_pred.trait_ref.substs[1..]);
-                                pred.kind().rebind(trait_pred).to_predicate(self.tcx)
+                                ty::PredicateKind::Trait(trait_pred)
                             }
                             ty::PredicateKind::Projection(mut proj_pred) => {
                                 assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
                                 proj_pred.projection_ty.substs = self
                                     .tcx
                                     .mk_substs_trait(ty, &proj_pred.projection_ty.substs[1..]);
-                                pred.kind().rebind(proj_pred).to_predicate(self.tcx)
+                                ty::PredicateKind::Projection(proj_pred)
                             }
                             _ => continue,
-                        };
+                        });
                         if !self.predicate_must_hold_modulo_regions(&Obligation::new(
+                            self.tcx,
                             ObligationCause::misc(span, self.body_id),
                             self.param_env,
                             pred,
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 2b019c8c9b7..2b1d8ac14eb 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -380,6 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         predicates.predicates.iter().zip(&predicates.spans)
                     {
                         let obligation = Obligation::new(
+                            self.tcx,
                             ObligationCause::dummy_with_span(callee_expr.span),
                             self.param_env,
                             *predicate,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 71949b42118..174b4331382 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -55,7 +55,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{self, ToPredicate, Ty, TypeAndMut};
+use rustc_middle::ty::{self, Ty, TypeAndMut};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{self, BytePos, DesugaringKind, Span};
@@ -278,13 +278,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             for &source_ty in &[a, b] {
                 if source_ty != target_ty {
                     obligations.push(Obligation::new(
+                        self.tcx(),
                         self.cause.clone(),
                         self.param_env,
                         ty::Binder::dummy(ty::PredicateKind::Coerce(ty::CoercePredicate {
                             a: source_ty,
                             b: target_ty,
-                        }))
-                        .to_predicate(self.tcx()),
+                        })),
                     ));
                 }
             }
@@ -669,7 +669,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                     continue;
                 }
             };
-            match selcx.select(&obligation.with(trait_pred)) {
+            match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) {
                 // Uncertain or unimplemented.
                 Ok(None) => {
                     if trait_pred.def_id() == unsize_did {
@@ -783,10 +783,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 // and then require that the resulting predicate (e.g., `usize: Clone`)
                 // holds (it does).
                 let predicate = predicate.with_self_ty(self.tcx, a);
-                Obligation::new(self.cause.clone(), self.param_env, predicate)
+                Obligation::new(self.tcx, self.cause.clone(), self.param_env, predicate)
             })
             // Enforce the region bound (e.g., `usize: 'static`, in our example).
             .chain([Obligation::new(
+                self.tcx,
                 self.cause.clone(),
                 self.param_env,
                 self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index c6bd771fad2..a0997874b0d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -22,8 +22,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
-    self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty,
-    UserType,
+    self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, Ty, UserType,
 };
 use rustc_middle::ty::{GenericArgKind, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts};
 use rustc_session::lint;
@@ -562,9 +561,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // WF obligations never themselves fail, so no real need to give a detailed cause:
         let cause = traits::ObligationCause::new(span, self.body_id, code);
         self.register_predicate(traits::Obligation::new(
+            self.tcx,
             cause,
             self.param_env,
-            ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx),
+            ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
         ));
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8cf70eb5431..b339a5f34ab 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -2150,6 +2150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             ),
                         );
                         let obligation = traits::Obligation::new(
+                            self.tcx,
                             traits::ObligationCause::dummy(),
                             self.param_env,
                             ty::Binder::dummy(ty::TraitPredicate {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 06e6e4350fc..316ecb0ed52 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1090,14 +1090,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let Some(into_def_id) = self.tcx.get_diagnostic_item(sym::Into)
             && self.predicate_must_hold_modulo_regions(&traits::Obligation::new(
+                self.tcx,
                 self.misc(expr.span),
                 self.param_env,
                 ty::Binder::dummy(ty::TraitRef {
                     def_id: into_def_id,
                     substs: self.tcx.mk_substs_trait(expr_ty, &[expected_ty.into()]),
                 })
-                .to_poly_trait_predicate()
-                .to_predicate(self.tcx),
+                .to_poly_trait_predicate(),
             ))
         {
             let sugg = if expr.precedence().order() >= PREC_POSTFIX {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 4a8b7749365..346a48432cd 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -20,7 +20,7 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
-use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable};
+use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable};
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
@@ -295,10 +295,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
         (
             traits::Obligation::misc(
+                self.tcx,
                 span,
                 self.body_id,
                 self.param_env,
-                poly_trait_ref.without_const().to_predicate(self.tcx),
+                poly_trait_ref.without_const(),
             ),
             substs,
         )
@@ -337,6 +338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         (
             traits::Obligation::new(
+                self.tcx,
                 traits::ObligationCause::new(
                     span,
                     self.body_id,
@@ -348,7 +350,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     },
                 ),
                 self.param_env,
-                poly_trait_ref.without_const().to_predicate(self.tcx),
+                poly_trait_ref.without_const(),
             ),
             substs,
         )
@@ -525,9 +527,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             method_ty, obligation
         );
         obligations.push(traits::Obligation::new(
+            tcx,
             cause,
             self.param_env,
-            ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())).to_predicate(tcx),
+            ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())),
         ));
 
         let callee = MethodCallee { def_id, substs, sig: fn_sig };
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 3fcd073f597..4419a3c04db 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -18,7 +18,8 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
 use rustc_middle::middle::stability;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::ToPredicate;
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitable};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_session::lint;
 use rustc_span::def_id::DefId;
@@ -1415,7 +1416,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> {
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
         let predicate = ty::Binder::dummy(trait_ref).to_poly_trait_predicate();
-        let obligation = traits::Obligation::new(cause, self.param_env, predicate);
+        let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, predicate);
         traits::SelectionContext::new(self).select(&obligation)
     }
 
@@ -1546,7 +1547,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     let predicate =
                         ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx);
                     parent_pred = Some(predicate);
-                    let obligation = traits::Obligation::new(cause, self.param_env, predicate);
+                    let obligation =
+                        traits::Obligation::new(self.tcx, cause, self.param_env, predicate);
                     if !self.predicate_may_hold(&obligation) {
                         result = ProbeResult::NoMatch;
                         if self.probe(|_| {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index edfe12963dc..7578d08e8e7 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -23,7 +23,7 @@ use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::with_crate_prefix;
-use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
@@ -80,10 +80,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
                         let poly_trait_ref = ty::Binder::dummy(trait_ref);
                         let obligation = Obligation::misc(
+                            tcx,
                             span,
                             self.body_id,
                             self.param_env,
-                            poly_trait_ref.without_const().to_predicate(tcx),
+                            poly_trait_ref.without_const(),
                         );
                         self.predicate_may_hold(&obligation)
                     })
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index a299a3e578d..34f54328230 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -581,9 +581,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
             }
         };
-        let predicate = predicate.0.rebind(atom).to_predicate(self.tcx);
+        let predicate = predicate.0.rebind(atom);
 
-        Obligation::new(cause, param_env, predicate)
+        Obligation::new(self.tcx, cause, param_env, predicate)
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index a973bf54b05..37f071a19ac 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -37,7 +37,7 @@ use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitable};
 use rustc_middle::ty::{IntType, UintType};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -347,10 +347,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
 
         if needs_wf {
             self.obligations.push(Obligation::new(
+                self.tcx(),
                 self.trace.cause.clone(),
                 self.param_env,
-                ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into()))
-                    .to_predicate(self.infcx.tcx),
+                ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into())),
             ));
         }
 
@@ -444,9 +444,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
             ty::PredicateKind::ConstEquate(b, a)
         };
         self.obligations.push(Obligation::new(
+            self.tcx(),
             self.trace.cause.clone(),
             self.param_env,
-            ty::Binder::dummy(predicate).to_predicate(self.tcx()),
+            ty::Binder::dummy(predicate),
         ));
     }
 }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index a982f11f718..1fa95f8d62a 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -595,7 +595,12 @@ impl<'tcx> InferCtxt<'tcx> {
             }
             // Require that the predicate holds for the concrete type.
             debug!(?predicate);
-            obligations.push(traits::Obligation::new(cause.clone(), param_env, predicate));
+            obligations.push(traits::Obligation::new(
+                self.tcx,
+                cause.clone(),
+                param_env,
+                predicate,
+            ));
         }
         Ok(InferOk { value: (), obligations })
     }
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index 9f12bc972a8..eb6deee291c 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -1,5 +1,5 @@
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{self, ToPredicate, Ty};
+use rustc_middle::ty::{self, Ty};
 
 use crate::traits::{Obligation, PredicateObligation};
 
@@ -28,12 +28,8 @@ impl<'tcx> InferCtxt<'tcx> {
         });
         let projection =
             ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, term: ty_var.into() });
-        let obligation = Obligation::with_depth(
-            cause,
-            recursion_depth,
-            param_env,
-            projection.to_predicate(self.tcx),
-        );
+        let obligation =
+            Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
         obligations.push(obligation);
         ty_var
     }
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 97354ba5d1b..8c8445a4d9e 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -6,7 +6,7 @@ use crate::traits::Obligation;
 use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::TyVar;
-use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use std::mem;
 
 /// Ensures `a` is made a subtype of `b`. Returns `a` on success.
@@ -95,14 +95,14 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
                 // can't make progress on `A <: B` if both A and B are
                 // type variables, so record an obligation.
                 self.fields.obligations.push(Obligation::new(
+                    self.tcx(),
                     self.fields.trace.cause.clone(),
                     self.fields.param_env,
                     ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
                         a_is_expected: self.a_is_expected,
                         a,
                         b,
-                    }))
-                    .to_predicate(self.tcx()),
+                    })),
                 ));
 
                 Ok(a)
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index c8600ded987..a9e6241bf6b 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -10,7 +10,7 @@ pub mod util;
 
 use rustc_hir as hir;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, Const, Ty, TyCtxt};
+use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt};
 use rustc_span::Span;
 
 pub use self::FulfillmentErrorCode::*;
@@ -124,38 +124,41 @@ pub enum FulfillmentErrorCode<'tcx> {
 
 impl<'tcx, O> Obligation<'tcx, O> {
     pub fn new(
+        tcx: TyCtxt<'tcx>,
         cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        predicate: O,
+        predicate: impl ToPredicate<'tcx, O>,
     ) -> Obligation<'tcx, O> {
-        Obligation { cause, param_env, recursion_depth: 0, predicate }
+        Self::with_depth(tcx, cause, 0, param_env, predicate)
     }
 
     pub fn with_depth(
+        tcx: TyCtxt<'tcx>,
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
-        predicate: O,
+        predicate: impl ToPredicate<'tcx, O>,
     ) -> Obligation<'tcx, O> {
+        let predicate = predicate.to_predicate(tcx);
         Obligation { cause, param_env, recursion_depth, predicate }
     }
 
     pub fn misc(
+        tcx: TyCtxt<'tcx>,
         span: Span,
         body_id: hir::HirId,
         param_env: ty::ParamEnv<'tcx>,
-        trait_ref: O,
+        trait_ref: impl ToPredicate<'tcx, O>,
     ) -> Obligation<'tcx, O> {
-        Obligation::new(ObligationCause::misc(span, body_id), param_env, trait_ref)
+        Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref)
     }
 
-    pub fn with<P>(&self, value: P) -> Obligation<'tcx, P> {
-        Obligation {
-            cause: self.cause.clone(),
-            param_env: self.param_env,
-            recursion_depth: self.recursion_depth,
-            predicate: value,
-        }
+    pub fn with<P>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        value: impl ToPredicate<'tcx, P>,
+    ) -> Obligation<'tcx, P> {
+        Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
     }
 }
 
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 7443d131c64..0e6731fa251 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -104,6 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                 // then we must've taken advantage of the hack in `project_and_unify_types` where
                 // we replace opaques with inference vars. Emit a warning!
                 if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new(
+                    cx.tcx,
                     traits::ObligationCause::dummy(),
                     cx.param_env,
                     assoc_pred,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f87d048c656..f9a762261e2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1129,8 +1129,8 @@ pub trait ToPredicate<'tcx, Predicate> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate;
 }
 
-impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Predicate<'tcx> {
-    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+impl<'tcx, T> ToPredicate<'tcx, T> for T {
+    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T {
         self
     }
 }
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index 54c738d8389..b7240a82897 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_trait_selection/src/autoderef.rs
@@ -3,8 +3,8 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 use rustc_hir as hir;
 use rustc_infer::infer::InferCtxt;
+use rustc_middle::ty::TypeVisitable;
 use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
-use rustc_middle::ty::{ToPredicate, TypeVisitable};
 use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Span;
@@ -130,9 +130,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
 
         let obligation = traits::Obligation::new(
+            tcx,
             cause.clone(),
             self.param_env,
-            ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
+            ty::Binder::dummy(trait_ref).without_const(),
         );
         if !self.infcx.predicate_may_hold(&obligation) {
             debug!("overloaded_deref_ty: cannot match obligation");
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 188f8bb7e2a..5869bc76b59 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -96,8 +96,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             PolyTraitRef::to_poly_trait_predicate,
             PolyTraitRef::to_poly_trait_predicate_negative_polarity,
         ] {
-            let result =
-                selcx.select(&Obligation::new(ObligationCause::dummy(), orig_env, f(&trait_pred)));
+            let result = selcx.select(&Obligation::new(
+                tcx,
+                ObligationCause::dummy(),
+                orig_env,
+                f(&trait_pred),
+            ));
             if let Ok(Some(ImplSource::UserDefined(_))) = result {
                 debug!(
                     "find_auto_trait_generics({:?}): \
@@ -280,8 +284,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
 
             // Call `infcx.resolve_vars_if_possible` to see if we can
             // get rid of any inference variables.
-            let obligation =
-                infcx.resolve_vars_if_possible(Obligation::new(dummy_cause.clone(), new_env, pred));
+            let obligation = infcx.resolve_vars_if_possible(Obligation::new(
+                tcx,
+                dummy_cause.clone(),
+                new_env,
+                pred,
+            ));
             let result = select.select(&obligation);
 
             match result {
@@ -706,7 +714,10 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                     // and turn them into an explicit negative impl for our type.
                     debug!("Projecting and unifying projection predicate {:?}", predicate);
 
-                    match project::poly_project_and_unify_type(select, &obligation.with(p)) {
+                    match project::poly_project_and_unify_type(
+                        select,
+                        &obligation.with(self.tcx, p),
+                    ) {
                         ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
                             debug!(
                                 "evaluate_nested_obligations: Unable to unify predicate \
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 8a62bf01567..ca4299f7db3 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -40,7 +40,7 @@ pub fn codegen_select_candidate<'tcx>(
 
     let obligation_cause = ObligationCause::dummy();
     let obligation =
-        Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
+        Obligation::new(tcx, obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
 
     let selection = match selcx.select(&obligation) {
         Ok(Some(selection)) => selection,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index 58da54afb75..6a5744f5f76 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -32,7 +32,7 @@ pub fn recompute_applicable_impls<'tcx>(
             impl_predicates
                 .predicates
                 .iter()
-                .map(|&predicate| Obligation::new(dummy_cause.clone(), param_env, predicate)),
+                .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
         );
 
         ocx.select_where_possible().is_empty()
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 41b252a8265..a310ad0b479 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -344,14 +344,14 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
                 });
                 let substs = self.tcx.mk_substs_trait(ty.skip_binder(), &[var.into()]);
                 let obligation = Obligation::new(
+                    self.tcx,
                     ObligationCause::dummy(),
                     param_env,
                     ty.rebind(ty::TraitPredicate {
                         trait_ref: ty::TraitRef::new(trait_def_id, substs),
                         constness,
                         polarity,
-                    })
-                    .to_predicate(self.tcx),
+                    }),
                 );
                 let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx);
                 fulfill_cx.register_predicate_obligation(self, obligation);
@@ -984,7 +984,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 );
                                 trait_pred
                             });
-                            let unit_obligation = obligation.with(predicate.to_predicate(tcx));
+                            let unit_obligation = obligation.with(tcx, predicate);
                             if self.predicate_may_hold(&unit_obligation) {
                                 err.note(
                                     "this error might have been caused by changes to \
@@ -2012,7 +2012,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ..*tr
         });
 
-        Obligation::new(ObligationCause::dummy(), param_env, trait_pred.to_predicate(self.tcx))
+        Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -2100,11 +2100,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     )
                 };
 
-                let obligation = Obligation::new(
-                    obligation.cause.clone(),
-                    obligation.param_env,
-                    trait_ref.to_poly_trait_predicate(),
-                );
+                let obligation = obligation.with(self.tcx, trait_ref.to_poly_trait_predicate());
                 let mut selcx = SelectionContext::with_query_mode(
                     &self,
                     crate::traits::TraitQueryMode::Standard,
@@ -2534,11 +2530,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             )
             .value;
 
-            let obligation = Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                cleaned_pred.to_predicate(selcx.tcx()),
-            );
+            let obligation =
+                Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred);
 
             self.predicate_may_hold(&obligation)
         })
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 84daaf97ecf..b8609077036 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -301,7 +301,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display;
+        T: fmt::Display + ToPredicate<'tcx, T>;
 
     /// Suggest to await before try: future? => future.await?
     fn suggest_await_before_try(
@@ -334,7 +334,7 @@ pub trait TypeErrCtxtExt<'tcx> {
     );
 }
 
-fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
+fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
     (
         generics.tail_span_for_predicate_suggestion(),
         format!("{} {}", generics.add_where_or_trailing_comma(), pred),
@@ -416,7 +416,7 @@ fn suggest_restriction<'tcx>(
             },
             // `fn foo(t: impl Trait)`
             //                       ^ suggest `where <T as Trait>::A: Bound`
-            predicate_constraint(hir_generics, trait_pred.to_predicate(tcx).to_string()),
+            predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)),
         ];
         sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string())));
 
@@ -440,9 +440,7 @@ fn suggest_restriction<'tcx>(
                 .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })),
             super_traits,
         ) {
-            (_, None) => {
-                predicate_constraint(hir_generics, trait_pred.to_predicate(tcx).to_string())
-            }
+            (_, None) => predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)),
             (None, Some((ident, []))) => (
                 ident.span.shrink_to_hi(),
                 format!(": {}", trait_pred.print_modifiers_and_trait_path()),
@@ -1162,7 +1160,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         for predicate in predicates.iter() {
             if !self.predicate_must_hold_modulo_regions(
-                &obligation.with(predicate.with_self_ty(self.tcx, self_ref_ty)),
+                &obligation.with(self.tcx, predicate.with_self_ty(self.tcx, self_ref_ty)),
             ) {
                 return;
             }
@@ -1523,7 +1521,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let self_ty_satisfies_dyn_predicates = |self_ty| {
                             predicates.iter().all(|predicate| {
                                 let pred = predicate.with_self_ty(self.tcx, self_ty);
-                                let obl = Obligation::new(cause.clone(), param_env, pred);
+                                let obl = Obligation::new(self.tcx, cause.clone(), param_env, pred);
                                 self.predicate_may_hold(&obl)
                             })
                         };
@@ -2704,7 +2702,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                 obligated_types.push(ty);
 
-                let parent_predicate = parent_trait_ref.to_predicate(tcx);
+                let parent_predicate = parent_trait_ref;
                 if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
                     // #74711: avoid a stack overflow
                     ensure_sufficient_stack(|| {
@@ -2766,7 +2764,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     _ => err.note(&msg),
                 };
 
-                let mut parent_predicate = parent_trait_pred.to_predicate(tcx);
+                let mut parent_predicate = parent_trait_pred;
                 let mut data = &data.derived;
                 let mut count = 0;
                 seen_requirements.insert(parent_def_id);
@@ -2826,7 +2824,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
             ObligationCauseCode::DerivedObligation(ref data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
-                let parent_predicate = parent_trait_ref.to_predicate(tcx);
+                let parent_predicate = parent_trait_ref;
                 // #74711: avoid a stack overflow
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
@@ -3070,9 +3068,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         ..*tr
                     });
                     let field_obl = Obligation::new(
+                        self.tcx,
                         obligation.cause.clone(),
                         obligation.param_env,
-                        trait_pred.to_predicate(self.tcx),
+                        trait_pred,
                     );
                     self.predicate_must_hold_modulo_regions(&field_obl)
                 })
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index b486c07f354..40b077bb94d 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -9,7 +9,6 @@ use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{self, Binder, Const, Ty, TypeVisitable};
 use std::marker::PhantomData;
 
@@ -296,7 +295,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 &mut obligations,
             );
             if predicate != obligation.predicate {
-                obligations.push(obligation.with(predicate));
+                obligations.push(obligation.with(infcx.tcx, predicate));
                 return ProcessResult::Changed(mk_pending(obligations));
             }
         }
@@ -307,7 +306,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 // This means we need to pass it the bound version of our
                 // predicate.
                 ty::PredicateKind::Trait(trait_ref) => {
-                    let trait_obligation = obligation.with(binder.rebind(trait_ref));
+                    let trait_obligation = obligation.with(infcx.tcx, binder.rebind(trait_ref));
 
                     self.process_trait_obligation(
                         obligation,
@@ -316,7 +315,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     )
                 }
                 ty::PredicateKind::Projection(data) => {
-                    let project_obligation = obligation.with(binder.rebind(data));
+                    let project_obligation = obligation.with(infcx.tcx, binder.rebind(data));
 
                     self.process_projection_obligation(
                         obligation,
@@ -335,9 +334,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 | ty::PredicateKind::ConstEquate(..) => {
                     let pred =
                         ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
-                    ProcessResult::Changed(mk_pending(vec![
-                        obligation.with(pred.to_predicate(self.selcx.tcx())),
-                    ]))
+                    ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
                 }
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for Chalk")
@@ -345,7 +342,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
             },
             Some(pred) => match pred {
                 ty::PredicateKind::Trait(data) => {
-                    let trait_obligation = obligation.with(Binder::dummy(data));
+                    let trait_obligation = obligation.with(infcx.tcx, Binder::dummy(data));
 
                     self.process_trait_obligation(
                         obligation,
@@ -370,7 +367,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 }
 
                 ty::PredicateKind::Projection(ref data) => {
-                    let project_obligation = obligation.with(Binder::dummy(*data));
+                    let project_obligation = obligation.with(infcx.tcx, Binder::dummy(*data));
 
                     self.process_projection_obligation(
                         obligation,
@@ -703,7 +700,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             }
             // Let the caller handle the recursion
             ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![
-                project_obligation.with(project_obligation.predicate.to_predicate(tcx)),
+                project_obligation.with(tcx, project_obligation.predicate),
             ])),
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
                 ProcessResult::Error(CodeProjectionError(e))
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 10e48610e3a..ddc9b768f07 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -440,7 +440,7 @@ pub fn impossible_predicates<'tcx>(
     let ocx = ObligationCtxt::new(&infcx);
     let predicates = ocx.normalize(ObligationCause::dummy(), param_env, predicates);
     for predicate in predicates {
-        let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+        let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
         ocx.register_obligation(obligation);
     }
     let errors = ocx.select_all_or_error();
@@ -530,6 +530,7 @@ fn is_impossible_method<'tcx>(
     let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
         if pred.visit_with(&mut visitor).is_continue() {
             Some(Obligation::new(
+                tcx,
                 ObligationCause::dummy_with_span(*span),
                 param_env,
                 ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 0bb25a74dc8..eaca3eaef0c 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -723,10 +723,9 @@ fn receiver_is_dispatchable<'tcx>(
             def_id: dispatch_from_dyn_did,
             substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
         })
-        .without_const()
-        .to_predicate(tcx);
+        .without_const();
 
-        Obligation::new(ObligationCause::dummy(), param_env, predicate)
+        Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
     };
 
     let infcx = tcx.infer_ctxt().build();
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 572f82117cc..ede6cd607b7 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -200,7 +200,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
             infcx.replace_bound_vars_with_placeholders(obligation.predicate);
         let new_universe = infcx.universe();
 
-        let placeholder_obligation = obligation.with(placeholder_predicate);
+        let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
         match project_and_unify_type(selcx, &placeholder_obligation) {
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
             ProjectAndUnifyResult::Holds(obligations)
@@ -517,6 +517,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
                             let obligation = Obligation::with_depth(
+                                self.tcx(),
                                 self.cause.clone(),
                                 recursion_limit.0,
                                 self.param_env,
@@ -573,6 +574,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                     && !self.tcx().sess.opts.actually_rustdoc
                 {
                     let obligation = Obligation::with_depth(
+                        self.selcx.tcx(),
                         self.cause.clone(),
                         recursion_limit.0,
                         self.param_env,
@@ -1110,7 +1112,8 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
         }
     }
 
-    let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
+    let obligation =
+        Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_ty);
 
     match project(selcx, &obligation) {
         Ok(Projected::Progress(Progress {
@@ -1343,8 +1346,8 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
             ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs })
                 .to_poly_trait_predicate();
 
-        let _ =
-            selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) {
+        let _ = selcx.infcx().commit_if_ok(|_| {
+            match selcx.select(&obligation.with(tcx, trait_predicate)) {
                 Ok(Some(super::ImplSource::UserDefined(data))) => {
                     candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
                         ImplTraitInTraitCandidate::Impl(data),
@@ -1364,7 +1367,8 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
                     candidate_set.mark_error(e);
                     return Err(());
                 }
-            });
+            }
+        });
     }
 }
 
@@ -1538,7 +1542,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
     // start out by selecting the predicate `T as TraitRef<...>`:
     let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
-    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
+    let trait_obligation = obligation.with(selcx.tcx(), poly_trait_ref.to_poly_trait_predicate());
     let _ = selcx.infcx().commit_if_ok(|_| {
         let impl_source = match selcx.select(&trait_obligation) {
             Ok(Some(impl_source)) => impl_source,
@@ -1705,12 +1709,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
                         if selcx.infcx().predicate_must_hold_modulo_regions(
                             &obligation.with(
+                                selcx.tcx(),
                                 ty::Binder::dummy(ty::TraitRef::new(
                                     selcx.tcx().require_lang_item(LangItem::Sized, None),
                                     selcx.tcx().mk_substs_trait(self_ty, &[]),
                                 ))
-                                .without_const()
-                                .to_predicate(selcx.tcx()),
+                                .without_const(),
                             ),
                         ) =>
                     {
@@ -1966,13 +1970,8 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
             tcx.require_lang_item(LangItem::Sized, None),
             tcx.mk_substs_trait(self_ty, &[]),
         ))
-        .without_const()
-        .to_predicate(tcx);
-        obligations.push(Obligation::new(
-            obligation.cause.clone(),
-            obligation.param_env,
-            sized_predicate,
-        ));
+        .without_const();
+        obligations.push(obligation.with(tcx, sized_predicate));
     }
 
     let substs = tcx.mk_substs([self_ty.into()].iter());
@@ -2289,6 +2288,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map(
         |(pred, span)| {
             Obligation::with_depth(
+                tcx,
                 ObligationCause::new(
                     obligation.cause.span,
                     obligation.cause.body_id,
@@ -2342,6 +2342,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
             nested,
         );
         nested.push(Obligation::with_depth(
+            tcx,
             obligation.cause.clone(),
             obligation.recursion_depth + 1,
             obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index a7932b332c9..f5c98558a25 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -208,6 +208,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
                             let obligation = Obligation::with_depth(
+                                self.tcx(),
                                 self.cause.clone(),
                                 recursion_limit.0,
                                 self.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
index 8cf500a466b..dfe19a5a86d 100644
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ b/compiler/rustc_trait_selection/src/traits/relationships.rs
@@ -1,8 +1,8 @@
 use crate::infer::InferCtxt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::{ObligationCause, PredicateObligation};
+use crate::traits::PredicateObligation;
 use rustc_infer::traits::TraitEngine;
-use rustc_middle::ty::{self, ToPredicate};
+use rustc_middle::ty;
 
 pub(crate) fn update<'tcx, T>(
     engine: &mut T,
@@ -25,9 +25,7 @@ pub(crate) fn update<'tcx, T>(
 
         // Then construct a new obligation with Self = () added
         // to the ParamEnv, and see if it holds.
-        let o = rustc_infer::traits::Obligation::new(
-            ObligationCause::dummy(),
-            obligation.param_env,
+        let o = obligation.with(infcx.tcx,
             obligation
                 .predicate
                 .kind()
@@ -38,8 +36,7 @@ pub(crate) fn update<'tcx, T>(
                         constness: tpred.constness,
                         polarity: tpred.polarity,
                     })
-                )
-                .to_predicate(infcx.tcx),
+                ),
         );
         // Don't report overflow errors. Otherwise equivalent to may_hold.
         if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 3671a0d87df..3995ea58db1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -13,7 +13,7 @@ use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
 use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitable};
 use rustc_target::spec::abi::Abi;
 
 use crate::traits;
@@ -718,9 +718,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         };
 
         let obligation = traits::Obligation::new(
+            tcx,
             cause.clone(),
             param_env,
-            ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
+            ty::Binder::dummy(trait_ref).without_const(),
         );
         if !self.infcx.predicate_may_hold(&obligation) {
             return None;
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 28b4bae7cbe..9d43f72b85f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -194,6 +194,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     &mut obligations,
                 );
                 obligations.push(Obligation::with_depth(
+                    self.tcx(),
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
                     obligation.param_env,
@@ -482,11 +483,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 super_trait,
                 &mut nested,
             );
-            nested.push(Obligation::new(
-                obligation.cause.clone(),
-                obligation.param_env,
-                normalized_super_trait,
-            ));
+            nested.push(obligation.with(tcx, normalized_super_trait));
         }
 
         let assoc_types: Vec<_> = tcx
@@ -581,11 +578,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     subst_bound,
                     &mut nested,
                 );
-                nested.push(Obligation::new(
-                    obligation.cause.clone(),
-                    obligation.param_env,
-                    normalized_bound,
-                ));
+                nested.push(obligation.with(tcx, normalized_bound));
             }
         }
 
@@ -644,9 +637,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             self.tcx().mk_substs_trait(output_ty, &[]),
         ));
         nested.push(Obligation::new(
+            self.infcx.tcx,
             cause,
             obligation.param_env,
-            tr.to_poly_trait_predicate().to_predicate(self.tcx()),
+            tr.to_poly_trait_predicate(),
         ));
 
         Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
@@ -727,11 +721,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // FIXME: Chalk
 
         if !self.tcx().sess.opts.unstable_opts.chalk {
-            nested.push(Obligation::new(
-                obligation.cause.clone(),
-                obligation.param_env,
-                ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind))
-                    .to_predicate(self.tcx()),
+            nested.push(obligation.with(
+                self.tcx(),
+                ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
             ));
         }
 
@@ -860,10 +852,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(
+                    tcx,
                     cause,
                     obligation.recursion_depth + 1,
                     obligation.param_env,
-                    obligation.predicate.rebind(outlives).to_predicate(tcx),
+                    obligation.predicate.rebind(outlives),
                 ));
             }
             _ => bug!(),
@@ -957,10 +950,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(
+                    tcx,
                     cause,
                     obligation.recursion_depth + 1,
                     obligation.param_env,
-                    obligation.predicate.rebind(outlives).to_predicate(tcx),
+                    obligation.predicate.rebind(outlives),
                 ));
             }
 
@@ -979,6 +973,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                 let predicate_to_obligation = |predicate| {
                     Obligation::with_depth(
+                        tcx,
                         cause.clone(),
                         obligation.recursion_depth + 1,
                         obligation.param_env,
@@ -1255,20 +1250,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         obligation.param_env,
                         cause.clone(),
                         obligation.recursion_depth + 1,
-                        self_ty
-                            .rebind(ty::TraitPredicate {
-                                trait_ref: ty::TraitRef {
-                                    def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
-                                    substs: self.tcx().mk_substs_trait(nested_ty, &[]),
-                                },
-                                constness: ty::BoundConstness::ConstIfConst,
-                                polarity: ty::ImplPolarity::Positive,
-                            })
-                            .to_predicate(tcx),
+                        self_ty.rebind(ty::TraitPredicate {
+                            trait_ref: ty::TraitRef {
+                                def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
+                                substs: self.tcx().mk_substs_trait(nested_ty, &[]),
+                            },
+                            constness: ty::BoundConstness::ConstIfConst,
+                            polarity: ty::ImplPolarity::Positive,
+                        }),
                         &mut nested,
                     );
 
                     nested.push(Obligation::with_depth(
+                        tcx,
                         cause.clone(),
                         obligation.recursion_depth + 1,
                         obligation.param_env,
@@ -1280,18 +1274,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // since it's either not `const Drop` (and we raise an error during selection),
                 // or it's an ADT (and we need to check for a custom impl during selection)
                 _ => {
-                    let predicate = self_ty
-                        .rebind(ty::TraitPredicate {
-                            trait_ref: ty::TraitRef {
-                                def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
-                                substs: self.tcx().mk_substs_trait(nested_ty, &[]),
-                            },
-                            constness: ty::BoundConstness::ConstIfConst,
-                            polarity: ty::ImplPolarity::Positive,
-                        })
-                        .to_predicate(tcx);
+                    let predicate = self_ty.rebind(ty::TraitPredicate {
+                        trait_ref: ty::TraitRef {
+                            def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
+                            substs: self.tcx().mk_substs_trait(nested_ty, &[]),
+                        },
+                        constness: ty::BoundConstness::ConstIfConst,
+                        polarity: ty::ImplPolarity::Positive,
+                    });
 
                     nested.push(Obligation::with_depth(
+                        tcx,
                         cause.clone(),
                         obligation.recursion_depth + 1,
                         obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index a12f67125bb..f90b11cdb1f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -445,7 +445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ty::PredicateKind::Trait(t) => {
                     let t = bound_predicate.rebind(t);
                     debug_assert!(!t.has_escaping_bound_vars());
-                    let obligation = obligation.with(t);
+                    let obligation = obligation.with(self.tcx(), t);
                     self.evaluate_trait_predicate_recursively(previous_stack, obligation)
                 }
 
@@ -596,7 +596,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                 ty::PredicateKind::Projection(data) => {
                     let data = bound_predicate.rebind(data);
-                    let project_obligation = obligation.with(data);
+                    let project_obligation = obligation.with(self.tcx(), data);
                     match project::poly_project_and_unify_type(self, &project_obligation) {
                         ProjectAndUnifyResult::Holds(mut subobligations) => {
                             'compute_res: {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index fc0a9f69003..d05e893de43 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -4,7 +4,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
 use rustc_span::Span;
 
 use std::iter;
@@ -324,7 +324,7 @@ impl<'tcx> WfPredicates<'tcx> {
             extend_cause_with_original_assoc_item_obligation(
                 tcx, trait_ref, item, &mut cause, predicate,
             );
-            traits::Obligation::with_depth(cause, depth, param_env, predicate)
+            traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate)
         };
 
         if let Elaborate::All = elaborate {
@@ -356,10 +356,11 @@ impl<'tcx> WfPredicates<'tcx> {
                         }
                     }
                     traits::Obligation::with_depth(
+                        tcx,
                         cause,
                         depth,
                         param_env,
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx),
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
                     )
                 }),
         );
@@ -407,10 +408,11 @@ impl<'tcx> WfPredicates<'tcx> {
                 .filter(|arg| !arg.has_escaping_bound_vars())
                 .map(|arg| {
                     traits::Obligation::with_depth(
+                        tcx,
                         cause.clone(),
                         depth,
                         param_env,
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx),
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
                     )
                 }),
         );
@@ -424,10 +426,11 @@ impl<'tcx> WfPredicates<'tcx> {
                 substs: self.tcx.mk_substs_trait(subty, &[]),
             };
             self.out.push(traits::Obligation::with_depth(
+                self.tcx,
                 cause,
                 self.recursion_depth,
                 self.param_env,
-                ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx),
+                ty::Binder::dummy(trait_ref).without_const(),
             ));
         }
     }
@@ -454,10 +457,10 @@ impl<'tcx> WfPredicates<'tcx> {
                             self.out.extend(obligations);
 
                             let predicate =
-                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
-                                    .to_predicate(self.tcx());
+                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
                             let cause = self.cause(traits::WellFormed(None));
                             self.out.push(traits::Obligation::with_depth(
+                                self.tcx(),
                                 cause,
                                 self.recursion_depth,
                                 self.param_env,
@@ -468,11 +471,11 @@ impl<'tcx> WfPredicates<'tcx> {
                             let cause = self.cause(traits::WellFormed(None));
 
                             self.out.push(traits::Obligation::with_depth(
+                                self.tcx(),
                                 cause,
                                 self.recursion_depth,
                                 self.param_env,
-                                ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into()))
-                                    .to_predicate(self.tcx()),
+                                ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())),
                             ));
                         }
                         ty::ConstKind::Error(_)
@@ -556,13 +559,13 @@ impl<'tcx> WfPredicates<'tcx> {
                     if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
                         let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
                         self.out.push(traits::Obligation::with_depth(
+                            self.tcx(),
                             cause,
                             depth,
                             param_env,
                             ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
                                 ty::OutlivesPredicate(rty, r),
-                            ))
-                            .to_predicate(self.tcx()),
+                            )),
                         ));
                     }
                 }
@@ -656,11 +659,11 @@ impl<'tcx> WfPredicates<'tcx> {
                         let tcx = self.tcx();
                         self.out.extend(component_traits.map(|did| {
                             traits::Obligation::with_depth(
+                                tcx,
                                 cause.clone(),
                                 depth,
                                 param_env,
-                                ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did))
-                                    .to_predicate(tcx),
+                                ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)),
                             )
                         }));
                     }
@@ -681,11 +684,11 @@ impl<'tcx> WfPredicates<'tcx> {
                 ty::Infer(_) => {
                     let cause = self.cause(traits::WellFormed(None));
                     self.out.push(traits::Obligation::with_depth(
+                        self.tcx(),
                         cause,
                         self.recursion_depth,
                         param_env,
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()))
-                            .to_predicate(self.tcx()),
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())),
                     ));
                 }
             }
@@ -724,7 +727,13 @@ impl<'tcx> WfPredicates<'tcx> {
                 if remap_constness {
                     pred = pred.without_const(self.tcx);
                 }
-                traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
+                traits::Obligation::with_depth(
+                    self.tcx,
+                    cause,
+                    self.recursion_depth,
+                    self.param_env,
+                    pred,
+                )
             })
             .filter(|pred| !pred.has_escaping_bound_vars())
             .collect()
@@ -794,10 +803,11 @@ impl<'tcx> WfPredicates<'tcx> {
                 let outlives =
                     ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
                 self.out.push(traits::Obligation::with_depth(
+                    self.tcx,
                     cause,
                     self.recursion_depth,
                     self.param_env,
-                    outlives.to_predicate(self.tcx),
+                    outlives,
                 ));
             }
         }
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index 493d5de0807..e94c8efe69a 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -26,7 +26,7 @@ fn evaluate_obligation<'tcx>(
     let ParamEnvAnd { param_env, value: predicate } = goal;
 
     let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
-    let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+    let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
 
     selcx.evaluate_root_obligation(&obligation)
 }
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 98cb3f21555..9eceae8b44f 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -91,7 +91,12 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
     }
 
     fn prove_predicate(&self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) {
-        self.ocx.register_obligation(Obligation::new(cause, self.param_env, predicate));
+        self.ocx.register_obligation(Obligation::new(
+            self.ocx.infcx.tcx,
+            cause,
+            self.param_env,
+            predicate,
+        ));
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
@@ -256,5 +261,5 @@ pub fn type_op_prove_predicate_with_cause<'tcx>(
     cause: ObligationCause<'tcx>,
 ) {
     let (param_env, ProvePredicate { predicate }) = key.into_parts();
-    ocx.register_obligation(Obligation::new(cause, param_env, predicate));
+    ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
 }