about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-06-22 18:17:13 +0000
committerMichael Goulet <michael@errs.io>2023-06-26 23:12:03 +0000
commitfbdef58414af2b3469bf4f0f83bb136945414b96 (patch)
tree7545b3a8de7c20547d91613e727e04b30f3fb67f
parent36fb58e433c782e27dd41034284e157cf86d587f (diff)
downloadrust-fbdef58414af2b3469bf4f0f83bb136945414b96.tar.gz
rust-fbdef58414af2b3469bf4f0f83bb136945414b96.zip
Migrate predicates_of and caller_bounds to Clause
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs59
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs64
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs88
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs32
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs58
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs22
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs6
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs29
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs8
-rw-r--r--compiler/rustc_infer/src/traits/util.rs5
-rw-r--r--compiler/rustc_lint/src/builtin.rs23
-rw-r--r--compiler/rustc_lint/src/lints.rs6
-rw-r--r--compiler/rustc_lint/src/multiple_supertrait_upcastable.rs2
-rw-r--r--compiler/rustc_lint/src/traits.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs6
-rw-r--r--compiler/rustc_middle/src/arena.rs4
-rw-r--r--compiler/rustc_middle/src/query/keys.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs8
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs7
-rw-r--r--compiler/rustc_middle/src/traits/chalk.rs2
-rw-r--r--compiler/rustc_middle/src/traits/util.rs4
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs18
-rw-r--r--compiler/rustc_middle/src/ty/context.rs30
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs7
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs50
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs34
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs9
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs4
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs8
-rw-r--r--compiler/rustc_privacy/src/lib.rs21
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs24
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.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/suggestions.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs60
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs27
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs63
-rw-r--r--compiler/rustc_traits/src/type_op.rs10
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs21
-rw-r--r--src/librustdoc/clean/auto_trait.rs10
-rw-r--r--src/librustdoc/clean/mod.rs44
-rw-r--r--src/librustdoc/clean/simplify.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs29
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs16
-rw-r--r--tests/ui/chalkify/recursive_where_clause_on_type.stderr21
77 files changed, 479 insertions, 706 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 5c365e98f0b..39b05829888 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -678,8 +678,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let tcx = self.infcx.tcx;
 
         // Find out if the predicates show that the type is a Fn or FnMut
-        let find_fn_kind_from_did = |(pred, _): (ty::Predicate<'tcx>, _)| {
-            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = pred.kind().skip_binder()
+        let find_fn_kind_from_did = |(pred, _): (ty::Clause<'tcx>, _)| {
+            if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
                 && pred.self_ty() == ty
             {
                 if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
@@ -705,7 +705,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
                 .explicit_item_bounds(def_id)
                 .subst_iter_copied(tcx, substs)
-                .find_map(|(clause, span)| find_fn_kind_from_did((clause.as_predicate(), span))),
+                .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
             ty::Closure(_, substs) => match substs.as_closure().kind() {
                 ty::ClosureKind::Fn => Some(hir::Mutability::Not),
                 ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 55c9864af8c..074f37bed13 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -928,7 +928,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
     fn any_param_predicate_mentions(
         &self,
-        predicates: &[ty::Predicate<'tcx>],
+        clauses: &[ty::Clause<'tcx>],
         ty: Ty<'tcx>,
         region: ty::EarlyBoundRegion,
     ) -> bool {
@@ -937,10 +937,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
             if let ty::GenericArgKind::Type(ty) = arg.unpack()
                 && let ty::Param(_) = ty.kind()
             {
-                predicates.iter().any(|pred| {
+                clauses.iter().any(|pred| {
                     match pred.kind().skip_binder() {
-                        ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) if data.self_ty() == ty => {}
-                        ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) if data.projection_ty.self_ty() == ty => {}
+                        ty::ClauseKind::Trait(data) if data.self_ty() == ty => {}
+                        ty::ClauseKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
                         _ => return false,
                     }
                     tcx.any_free_region_meets(pred, |r| {
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 41a6d94b278..eaab318739f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -945,40 +945,29 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let mut trait_bounds = vec![];
         let mut projection_bounds = vec![];
-        for (clause, span) in bounds.clauses() {
-            let pred: ty::Predicate<'tcx> = clause.as_predicate();
+        for (pred, span) in bounds.clauses() {
             let bound_pred = pred.kind();
             match bound_pred.skip_binder() {
-                ty::PredicateKind::Clause(clause) => match clause {
-                    ty::ClauseKind::Trait(trait_pred) => {
-                        assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
-                        trait_bounds.push((
-                            bound_pred.rebind(trait_pred.trait_ref),
-                            span,
-                            trait_pred.constness,
-                        ));
-                    }
-                    ty::ClauseKind::Projection(proj) => {
-                        projection_bounds.push((bound_pred.rebind(proj), span));
-                    }
-                    ty::ClauseKind::TypeOutlives(_) => {
-                        // Do nothing, we deal with regions separately
-                    }
-                    ty::ClauseKind::RegionOutlives(_)
-                    | ty::ClauseKind::ConstArgHasType(..)
-                    | ty::ClauseKind::WellFormed(_)
-                    | ty::ClauseKind::ConstEvaluatable(_) => {
-                        bug!()
-                    }
-                },
-                ty::PredicateKind::AliasRelate(..)
-                | ty::PredicateKind::ObjectSafe(_)
-                | ty::PredicateKind::ClosureKind(_, _, _)
-                | ty::PredicateKind::Subtype(_)
-                | ty::PredicateKind::Coerce(_)
-                | ty::PredicateKind::ConstEquate(_, _)
-                | ty::PredicateKind::TypeWellFormedFromEnv(_)
-                | ty::PredicateKind::Ambiguous => bug!(),
+                ty::ClauseKind::Trait(trait_pred) => {
+                    assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
+                    trait_bounds.push((
+                        bound_pred.rebind(trait_pred.trait_ref),
+                        span,
+                        trait_pred.constness,
+                    ));
+                }
+                ty::ClauseKind::Projection(proj) => {
+                    projection_bounds.push((bound_pred.rebind(proj), span));
+                }
+                ty::ClauseKind::TypeOutlives(_) => {
+                    // Do nothing, we deal with regions separately
+                }
+                ty::ClauseKind::RegionOutlives(_)
+                | ty::ClauseKind::ConstArgHasType(..)
+                | ty::ClauseKind::WellFormed(_)
+                | ty::ClauseKind::ConstEvaluatable(_) => {
+                    bug!()
+                }
             }
         }
 
@@ -1425,9 +1414,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             || {
                 traits::transitive_bounds_that_define_assoc_item(
                     tcx,
-                    predicates.iter().filter_map(|(p, _)| {
-                        Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref))
-                    }),
+                    predicates
+                        .iter()
+                        .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))),
                     assoc_name,
                 )
             },
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index b2ba566f60c..3048c175e1e 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -220,7 +220,7 @@ fn compare_method_predicate_entailment<'tcx>(
     // the new hybrid bounds we computed.
     let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
     let param_env = ty::ParamEnv::new(
-        tcx.mk_predicates(&hybrid_preds.predicates),
+        tcx.mk_clauses(&hybrid_preds.predicates),
         Reveal::UserFacing,
         hir::Constness::NotConst,
     );
@@ -1835,7 +1835,7 @@ fn compare_type_predicate_entailment<'tcx>(
     let impl_ty_span = tcx.def_span(impl_ty_def_id);
     let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
     let param_env = ty::ParamEnv::new(
-        tcx.mk_predicates(&hybrid_preds.predicates),
+        tcx.mk_clauses(&hybrid_preds.predicates),
         Reveal::UserFacing,
         hir::Constness::NotConst,
     );
@@ -2011,7 +2011,7 @@ pub(super) fn check_type_bounds<'tcx>(
                 .to_predicate(tcx),
             ),
         };
-        ty::ParamEnv::new(tcx.mk_predicates(&predicates), Reveal::UserFacing, param_env.constness())
+        ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing, param_env.constness())
     };
     debug!(?normalize_param_env);
 
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 596c5518086..ce2da7cb1a3 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -296,7 +296,7 @@ fn default_body_is_unstable(
 /// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
 fn bounds_from_generic_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
-    predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
+    predicates: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
 ) -> (String, String) {
     let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
     let mut projections = vec![];
@@ -304,7 +304,7 @@ fn bounds_from_generic_predicates<'tcx>(
         debug!("predicate {:?}", predicate);
         let bound_predicate = predicate.kind();
         match bound_predicate.skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
+            ty::ClauseKind::Trait(trait_predicate) => {
                 let entry = types.entry(trait_predicate.self_ty()).or_default();
                 let def_id = trait_predicate.def_id();
                 if Some(def_id) != tcx.lang_items().sized_trait() {
@@ -313,7 +313,7 @@ fn bounds_from_generic_predicates<'tcx>(
                     entry.push(trait_predicate.def_id());
                 }
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_pred)) => {
+            ty::ClauseKind::Projection(projection_pred) => {
                 projections.push(bound_predicate.rebind(projection_pred));
             }
             _ => {}
@@ -362,7 +362,7 @@ fn fn_sig_suggestion<'tcx>(
     tcx: TyCtxt<'tcx>,
     sig: ty::FnSig<'tcx>,
     ident: Ident,
-    predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
+    predicates: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
     assoc: ty::AssocItem,
 ) -> String {
     let args = sig
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 64e0331ac77..d34d6f644a7 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -15,7 +15,7 @@ use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
-    self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+    self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
     TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
 use rustc_middle::ty::{GenericArgKind, InternalSubsts};
@@ -322,7 +322,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
             // Gather the bounds with which all other items inside of this trait constrain the GAT.
             // This is calculated by taking the intersection of the bounds that each item
             // constrains the GAT with individually.
-            let mut new_required_bounds: Option<FxHashSet<ty::Predicate<'_>>> = None;
+            let mut new_required_bounds: Option<FxHashSet<ty::Clause<'_>>> = None;
             for item in associated_items {
                 let item_def_id = item.id.owner_id;
                 // Skip our own GAT, since it does not constrain itself at all.
@@ -419,20 +419,17 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
         let mut unsatisfied_bounds: Vec<_> = required_bounds
             .into_iter()
             .filter(|clause| match clause.kind().skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
-                    ty::OutlivesPredicate(a, b),
-                )) => !region_known_to_outlive(
-                    tcx,
-                    gat_def_id.def_id,
-                    param_env,
-                    &FxIndexSet::default(),
-                    a,
-                    b,
-                ),
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
-                    a,
-                    b,
-                ))) => !ty_known_to_outlive(
+                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
+                    !region_known_to_outlive(
+                        tcx,
+                        gat_def_id.def_id,
+                        param_env,
+                        &FxIndexSet::default(),
+                        a,
+                        b,
+                    )
+                }
+                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => !ty_known_to_outlive(
                     tcx,
                     gat_def_id.def_id,
                     param_env,
@@ -440,7 +437,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
                     a,
                     b,
                 ),
-                _ => bug!("Unexpected PredicateKind"),
+                _ => bug!("Unexpected ClauseKind"),
             })
             .map(|clause| clause.to_string())
             .collect();
@@ -488,7 +485,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
 fn augment_param_env<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    new_predicates: Option<&FxHashSet<ty::Predicate<'tcx>>>,
+    new_predicates: Option<&FxHashSet<ty::Clause<'tcx>>>,
 ) -> ty::ParamEnv<'tcx> {
     let Some(new_predicates) = new_predicates else {
         return param_env;
@@ -498,7 +495,7 @@ fn augment_param_env<'tcx>(
         return param_env;
     }
 
-    let bounds = tcx.mk_predicates_from_iter(
+    let bounds = tcx.mk_clauses_from_iter(
         param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()),
     );
     // FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
@@ -524,7 +521,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
     wf_tys: &FxIndexSet<Ty<'tcx>>,
     gat_def_id: LocalDefId,
     gat_generics: &'tcx ty::Generics,
-) -> Option<FxHashSet<ty::Predicate<'tcx>>> {
+) -> Option<FxHashSet<ty::Clause<'tcx>>> {
     // The bounds we that we would require from `to_check`
     let mut bounds = FxHashSet::default();
 
@@ -573,11 +570,10 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
                 );
                 // The predicate we expect to see. (In our example,
                 // `Self: 'me`.)
-                let clause = ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
-                    ty::OutlivesPredicate(ty_param, region_param),
-                ));
-                let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
-                bounds.insert(clause);
+                bounds.insert(
+                    ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_param, region_param))
+                        .to_predicate(tcx),
+                );
             }
         }
 
@@ -622,11 +618,13 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
                     },
                 );
                 // The predicate we expect to see.
-                let clause = ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
-                    ty::OutlivesPredicate(region_a_param, region_b_param),
-                ));
-                let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
-                bounds.insert(clause);
+                bounds.insert(
+                    ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
+                        region_a_param,
+                        region_b_param,
+                    ))
+                    .to_predicate(tcx),
+                );
             }
         }
     }
@@ -1406,7 +1404,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             infcx,
             wfcx.param_env.without_const(),
             wfcx.body_def_id,
-            p,
+            p.as_predicate(),
             sp,
         )
     });
@@ -1875,9 +1873,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
             // We lower empty bounds like `Vec<dyn Copy>:` as
             // `WellFormed(Vec<dyn Copy>)`, which will later get checked by
             // regular WF checking
-            if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) =
-                pred.kind().skip_binder()
-            {
+            if let ty::ClauseKind::WellFormed(..) = pred.kind().skip_binder() {
                 continue;
             }
             // Match the existing behavior.
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 958313fee6f..44c393bfe82 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -38,16 +38,12 @@ fn associated_type_bounds<'tcx>(
         .iter()
         .copied()
         .filter(|(pred, _)| match pred.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.self_ty() == item_ty,
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
-                proj.projection_ty.self_ty() == item_ty
-            }
-            ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
-                outlives.0 == item_ty
-            }
+            ty::ClauseKind::Trait(tr) => tr.self_ty() == item_ty,
+            ty::ClauseKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
+            ty::ClauseKind::TypeOutlives(outlives) => outlives.0 == item_ty,
             _ => false,
         })
-        .map(|(pred, span)| (pred.expect_clause(), span));
+        .map(|(clause, span)| (clause, span));
 
     let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
     debug!(
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 3081f0c386a..edb6a4cace3 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -75,7 +75,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
 
     // We use an `IndexSet` to preserve order of insertion.
     // Preserving the order of insertion is important here so as not to break UI tests.
-    let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
+    let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
 
     let ast_generics = match node {
         Node::TraitItem(item) => item.generics,
@@ -126,8 +126,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         predicates.extend(
             icx.astconv()
                 .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
-                .clauses()
-                .map(|(clause, span)| (clause.as_predicate(), span)),
+                .clauses(),
         );
     }
 
@@ -176,8 +175,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                     param.span,
                 );
                 trace!(?bounds);
-                predicates
-                    .extend(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)));
+                predicates.extend(bounds.clauses());
                 trace!(?predicates);
             }
             GenericParamKind::Const { .. } => {
@@ -188,11 +186,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
 
                 let ct = tcx.mk_const(param_const, ct_ty);
 
-                let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
-                    ty::ClauseKind::ConstArgHasType(ct, ct_ty),
-                ))
-                .to_predicate(tcx);
-                predicates.insert((predicate, param.span));
+                predicates.insert((
+                    ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx),
+                    param.span,
+                ));
 
                 index += 1;
             }
@@ -221,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                     } else {
                         let span = bound_pred.bounded_ty.span;
                         let predicate = ty::Binder::bind_with_vars(
-                            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty.into())),
+                            ty::ClauseKind::WellFormed(ty.into()),
                             bound_vars,
                         );
                         predicates.insert((predicate.to_predicate(tcx), span));
@@ -236,8 +233,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                     bound_vars,
                     OnlySelfBounds(false),
                 );
-                predicates
-                    .extend(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)));
+                predicates.extend(bounds.clauses());
             }
 
             hir::WherePredicate::RegionPredicate(region_pred) => {
@@ -249,11 +245,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                         }
                         _ => bug!(),
                     };
-                    let pred = ty::Binder::dummy(ty::PredicateKind::Clause(
-                        ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
-                    ))
-                    .to_predicate(icx.tcx);
-
+                    let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
+                        .to_predicate(icx.tcx);
                     (pred, span)
                 }))
             }
@@ -318,17 +311,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                 },
             );
             predicates.push((
-                ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
-                    ty::OutlivesPredicate(orig_region, dup_region),
-                )))
-                .to_predicate(icx.tcx),
+                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
+                    .to_predicate(icx.tcx),
                 duplicate.span,
             ));
             predicates.push((
-                ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
-                    ty::OutlivesPredicate(dup_region, orig_region),
-                )))
-                .to_predicate(icx.tcx),
+                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
+                    .to_predicate(icx.tcx),
                 duplicate.span,
             ));
         }
@@ -344,10 +333,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
 fn const_evaluatable_predicates_of(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
-) -> FxIndexSet<(ty::Predicate<'_>, Span)> {
+) -> FxIndexSet<(ty::Clause<'_>, Span)> {
     struct ConstCollector<'tcx> {
         tcx: TyCtxt<'tcx>,
-        preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>,
+        preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
     }
 
     impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
@@ -355,13 +344,8 @@ fn const_evaluatable_predicates_of(
             let ct = ty::Const::from_anon_const(self.tcx, c.def_id);
             if let ty::ConstKind::Unevaluated(_) = ct.kind() {
                 let span = self.tcx.def_span(c.def_id);
-                self.preds.insert((
-                    ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
-                        ct,
-                    )))
-                    .to_predicate(self.tcx),
-                    span,
-                ));
+                self.preds
+                    .insert((ty::ClauseKind::ConstEvaluatable(ct).to_predicate(self.tcx), span));
             }
         }
 
@@ -449,15 +433,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
             .iter()
             .copied()
             .filter(|(pred, _)| match pred.kind().skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => {
-                    !is_assoc_item_ty(tr.self_ty())
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
-                    !is_assoc_item_ty(proj.projection_ty.self_ty())
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
-                    !is_assoc_item_ty(outlives.0)
-                }
+                ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
+                ty::ClauseKind::Projection(proj) => !is_assoc_item_ty(proj.projection_ty.self_ty()),
+                ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
                 _ => true,
             })
             .collect();
@@ -498,9 +476,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
                     .predicates
                     .into_iter()
                     .filter(|(pred, _)| {
-                        if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) =
-                            pred.kind().skip_binder()
-                        {
+                        if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
                             match ct.kind() {
                                 ty::ConstKind::Param(param_const) => {
                                     let defaulted_param_idx = tcx
@@ -665,12 +641,8 @@ pub(super) fn implied_predicates_with_filter(
     };
 
     // Combine the two lists to form the complete set of superbounds:
-    let implied_bounds = &*tcx.arena.alloc_from_iter(
-        superbounds
-            .clauses()
-            .map(|(clause, span)| (clause.as_predicate(), span))
-            .chain(where_bounds_that_match),
-    );
+    let implied_bounds =
+        &*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match));
     debug!(?implied_bounds);
 
     // Now require that immediate supertraits are converted, which will, in
@@ -679,7 +651,7 @@ pub(super) fn implied_predicates_with_filter(
     if matches!(filter, PredicateFilter::SelfOnly) {
         for &(pred, span) in implied_bounds {
             debug!("superbound: {:?}", pred);
-            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(bound)) = pred.kind().skip_binder()
+            if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
                 && bound.polarity == ty::ImplPolarity::Positive
             {
                 tcx.at(span).super_predicates_of(bound.def_id());
@@ -776,9 +748,7 @@ pub(super) fn type_param_predicates(
         )
         .into_iter()
         .filter(|(predicate, _)| match predicate.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
-                data.self_ty().is_param(index)
-            }
+            ty::ClauseKind::Trait(data) => data.self_ty().is_param(index),
             _ => false,
         }),
     );
@@ -800,7 +770,7 @@ impl<'tcx> ItemCtxt<'tcx> {
         ty: Ty<'tcx>,
         only_self_bounds: OnlySelfBounds,
         assoc_name: Option<Ident>,
-    ) -> Vec<(ty::Predicate<'tcx>, Span)> {
+    ) -> Vec<(ty::Clause<'tcx>, Span)> {
         let mut bounds = Bounds::default();
 
         for predicate in ast_generics.predicates {
@@ -829,7 +799,7 @@ impl<'tcx> ItemCtxt<'tcx> {
             );
         }
 
-        bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)).collect()
+        bounds.clauses().collect()
     }
 
     #[instrument(level = "trace", skip(self))]
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index d20f39e9b05..3d75df8c69f 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1761,7 +1761,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
                 let bound_predicate = pred.kind();
                 match bound_predicate.skip_binder() {
-                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
+                    ty::ClauseKind::Trait(data) => {
                         // The order here needs to match what we would get from `subst_supertrait`
                         let pred_bound_vars = bound_predicate.bound_vars();
                         let mut all_bound_vars = bound_vars.clone();
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 6aecb95b484..35882ad352b 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -151,7 +151,7 @@ pub fn identify_constrained_generic_params<'tcx>(
 /// think of any.
 pub fn setup_constraining_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
-    predicates: &mut [(ty::Predicate<'tcx>, Span)],
+    predicates: &mut [(ty::Clause<'tcx>, Span)],
     impl_trait_ref: Option<ty::TraitRef<'tcx>>,
     input_parameters: &mut FxHashSet<Parameter>,
 ) {
@@ -187,9 +187,7 @@ pub fn setup_constraining_predicates<'tcx>(
         for j in i..predicates.len() {
             // Note that we don't have to care about binders here,
             // as the impl trait ref never contains any late-bound regions.
-            if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) =
-                predicates[j].0.kind().skip_binder()
-            {
+            if let ty::ClauseKind::Projection(projection) = predicates[j].0.kind().skip_binder() {
                 // Special case: watch out for some kind of sneaky attempt
                 // to project out an associated type defined by this very
                 // trait.
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 97813a291da..1dd45e34282 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -235,10 +235,8 @@ fn unconstrained_parent_impl_substs<'tcx>(
     // what we want here. We want only a list of constrained parameters while
     // the functions in `cgp` add the constrained parameters to a list of
     // unconstrained parameters.
-    for (predicate, _) in impl_generic_predicates.predicates.iter() {
-        if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
-            predicate.kind().skip_binder()
-        {
+    for (clause, _) in impl_generic_predicates.predicates.iter() {
+        if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder() {
             let projection_ty = proj.projection_ty;
             let projected_ty = proj.term;
 
@@ -340,8 +338,11 @@ fn check_predicates<'tcx>(
     impl2_substs: SubstsRef<'tcx>,
     span: Span,
 ) {
-    let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
-    let impl1_predicates: Vec<_> = traits::elaborate(tcx, instantiated.into_iter()).collect();
+    let impl1_predicates: Vec<_> = traits::elaborate(
+        tcx,
+        tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).into_iter(),
+    )
+    .collect();
 
     let mut impl2_predicates = if impl2_node.is_from_trait() {
         // Always applicable traits have to be always applicable without any
@@ -352,8 +353,8 @@ fn check_predicates<'tcx>(
             tcx,
             tcx.predicates_of(impl2_node.def_id())
                 .instantiate(tcx, impl2_substs)
-                .predicates
-                .into_iter(),
+                .into_iter()
+                .map(|(c, _s)| c.as_predicate()),
         )
         .collect()
     };
@@ -377,13 +378,13 @@ fn check_predicates<'tcx>(
     let always_applicable_traits = impl1_predicates
         .iter()
         .copied()
-        .filter(|&(predicate, _)| {
+        .filter(|(clause, _span)| {
             matches!(
-                trait_predicate_kind(tcx, predicate),
+                trait_predicate_kind(tcx, clause.as_predicate()),
                 Some(TraitSpecializationKind::AlwaysApplicable)
             )
         })
-        .map(|(pred, _span)| pred);
+        .map(|(c, _span)| c.as_predicate());
 
     // Include the well-formed predicates of the type parameters of the impl.
     for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs {
@@ -398,9 +399,12 @@ fn check_predicates<'tcx>(
     }
     impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits));
 
-    for (predicate, span) in impl1_predicates {
-        if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) {
-            check_specialization_on(tcx, predicate, span)
+    for (clause, span) in impl1_predicates {
+        if !impl2_predicates
+            .iter()
+            .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span))
+        {
+            check_specialization_on(tcx, clause.as_predicate(), span)
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index e63549998d2..a7fca41f86a 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -30,40 +30,30 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
             // process predicates and convert to `RequiredPredicates` entry, see below
             for &(predicate, span) in predicates.predicates {
                 match predicate.kind().skip_binder() {
-                    ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(OutlivesPredicate(
-                        ty,
-                        reg,
-                    ))) => insert_outlives_predicate(
-                        tcx,
-                        ty.into(),
-                        reg,
-                        span,
-                        &mut required_predicates,
-                    ),
-
-                    ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
-                        OutlivesPredicate(reg1, reg2),
-                    )) => insert_outlives_predicate(
-                        tcx,
-                        reg1.into(),
-                        reg2,
-                        span,
-                        &mut required_predicates,
-                    ),
-
-                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
-                    | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
-                    | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
-                    | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
-                    | ty::PredicateKind::AliasRelate(..)
-                    | ty::PredicateKind::ObjectSafe(..)
-                    | ty::PredicateKind::ClosureKind(..)
-                    | ty::PredicateKind::Subtype(..)
-                    | ty::PredicateKind::Coerce(..)
-                    | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-                    | ty::PredicateKind::ConstEquate(..)
-                    | ty::PredicateKind::Ambiguous
-                    | ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
+                    ty::ClauseKind::TypeOutlives(OutlivesPredicate(ty, reg)) => {
+                        insert_outlives_predicate(
+                            tcx,
+                            ty.into(),
+                            reg,
+                            span,
+                            &mut required_predicates,
+                        )
+                    }
+
+                    ty::ClauseKind::RegionOutlives(OutlivesPredicate(reg1, reg2)) => {
+                        insert_outlives_predicate(
+                            tcx,
+                            reg1.into(),
+                            reg2,
+                            span,
+                            &mut required_predicates,
+                        )
+                    }
+                    ty::ClauseKind::Trait(_)
+                    | ty::ClauseKind::Projection(_)
+                    | ty::ClauseKind::ConstArgHasType(_, _)
+                    | ty::ClauseKind::WellFormed(_)
+                    | ty::ClauseKind::ConstEvaluatable(_) => {}
                 }
             }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index 880437023c8..223aedefea3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -25,16 +25,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let generics = self.tcx.generics_of(def_id);
         let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
-                pred.trait_ref.substs.to_vec()
-            }
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
-                pred.projection_ty.substs.to_vec()
-            }
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(arg, ty)) => {
+            ty::ClauseKind::Trait(pred) => pred.trait_ref.substs.to_vec(),
+            ty::ClauseKind::Projection(pred) => pred.projection_ty.substs.to_vec(),
+            ty::ClauseKind::ConstArgHasType(arg, ty) => {
                 vec![ty.into(), arg.into()]
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(e)) => vec![e.into()],
+            ty::ClauseKind::ConstEvaluatable(e) => vec![e.into()],
             _ => return false,
         };
 
@@ -512,11 +508,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things.
             return Err(expr);
         }
-        let relevant_broken_predicate: ty::PredicateKind<'tcx> =
-            impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
 
-        match relevant_broken_predicate {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(broken_trait)) => {
+        match impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder() {
+            ty::ClauseKind::Trait(broken_trait) => {
                 // ...
                 self.blame_specific_part_of_expr_corresponding_to_generic_param(
                     broken_trait.trait_ref.self_ty().into(),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index f294ff0051d..5dc0ada153f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1948,7 +1948,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // do that, so it's OK.
                         for (predicate, span) in instantiated
                         {
-                            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = predicate.kind().skip_binder()
+                            if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder()
                                 && pred.self_ty().peel_refs() == callee_ty
                                 && self.tcx.is_fn_trait(pred.def_id())
                             {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index d311ebe8c32..00a3f47b306 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -226,9 +226,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
             predicates: tcx.arena.alloc_from_iter(
                 self.param_env.caller_bounds().iter().filter_map(|predicate| {
                     match predicate.kind().skip_binder() {
-                        ty::PredicateKind::Clause(ty::ClauseKind::Trait(data))
-                            if data.self_ty().is_param(index) =>
-                        {
+                        ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => {
                             // HACK(eddyb) should get the original `Span`.
                             let span = tcx.def_span(def_id);
                             Some((predicate, span))
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 279ff849e3d..31894d25b60 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -606,9 +606,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         traits::elaborate(self.tcx, predicates.predicates.iter().copied())
             // We don't care about regions here.
             .filter_map(|pred| match pred.kind().skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))
-                    if trait_pred.def_id() == sized_def_id =>
-                {
+                ty::ClauseKind::Trait(trait_pred) if trait_pred.def_id() == sized_def_id => {
                     let span = predicates
                         .iter()
                         .find_map(|(p, span)| if p == pred { Some(span) } else { None })
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 762176ecfc7..b15d76a3590 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -834,7 +834,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
             let bound_predicate = predicate.kind();
             match bound_predicate.skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
+                ty::ClauseKind::Trait(trait_predicate) => {
                     match *trait_predicate.trait_ref.self_ty().kind() {
                         ty::Param(p) if p == param_ty => {
                             Some(bound_predicate.rebind(trait_predicate.trait_ref))
@@ -842,20 +842,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         _ => None,
                     }
                 }
-                ty::PredicateKind::Subtype(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
-                | ty::PredicateKind::Coerce(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
-                | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
-                | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
-                | ty::PredicateKind::ObjectSafe(..)
-                | ty::PredicateKind::ClosureKind(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-                | ty::PredicateKind::ConstEquate(..)
-                | ty::PredicateKind::Ambiguous
-                | ty::PredicateKind::AliasRelate(..)
-                | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
+                ty::ClauseKind::RegionOutlives(_)
+                | ty::ClauseKind::TypeOutlives(_)
+                | ty::ClauseKind::Projection(_)
+                | ty::ClauseKind::ConstArgHasType(_, _)
+                | ty::ClauseKind::WellFormed(_)
+                | ty::ClauseKind::ConstEvaluatable(_) => None,
             }
         });
 
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 630014e2380..32054e6d125 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -739,10 +739,8 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
         self.obligations.push(Obligation {
             cause: self.cause.clone(),
             param_env: self.param_env,
-            predicate: ty::Binder::dummy(ty::PredicateKind::Clause(
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(sup, sub)),
-            ))
-            .to_predicate(self.infcx.tcx),
+            predicate: ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(sup, sub))
+                .to_predicate(self.infcx.tcx),
             recursion_depth: 0,
         });
     }
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index d926f7f7cbd..cb92fc6ddb6 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -20,27 +20,18 @@ pub fn explicit_outlives_bounds<'tcx>(
     param_env
         .caller_bounds()
         .into_iter()
-        .map(ty::Predicate::kind)
+        .map(ty::Clause::kind)
         .filter_map(ty::Binder::no_bound_vars)
         .filter_map(move |kind| match kind {
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
-            | ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
-            | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
-            | ty::PredicateKind::AliasRelate(..)
-            | ty::PredicateKind::Coerce(..)
-            | ty::PredicateKind::Subtype(..)
-            | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
-            | ty::PredicateKind::ObjectSafe(..)
-            | ty::PredicateKind::ClosureKind(..)
-            | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
-            | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-            | ty::PredicateKind::ConstEquate(..)
-            | ty::PredicateKind::Ambiguous
-            | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
-            ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
-                r_a,
-                r_b,
-            ))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)),
+            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
+                Some(OutlivesBound::RegionSubRegion(r_b, r_a))
+            }
+            ty::ClauseKind::Trait(_)
+            | ty::ClauseKind::TypeOutlives(_)
+            | ty::ClauseKind::Projection(_)
+            | ty::ClauseKind::ConstArgHasType(_, _)
+            | ty::ClauseKind::WellFormed(_)
+            | ty::ClauseKind::ConstEvaluatable(_) => None,
         })
 }
 
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 871171f9447..1a5e2b520b8 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -223,7 +223,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         // parameter environments are already elaborated, so we don't
         // have to worry about that.
         let c_b = self.param_env.caller_bounds();
-        let param_bounds = self.collect_outlives_from_predicate_list(erased_ty, c_b.into_iter());
+        let param_bounds = self.collect_outlives_from_clause_list(erased_ty, c_b.into_iter());
 
         // Next, collect regions we scraped from the well-formedness
         // constraints in the fn signature. To do that, we walk the list
@@ -307,15 +307,15 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     /// when comparing `ty` for equality, so `ty` must be something
     /// that does not involve inference variables and where you
     /// otherwise want a precise match.
-    fn collect_outlives_from_predicate_list(
+    fn collect_outlives_from_clause_list(
         &self,
         erased_ty: Ty<'tcx>,
-        predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
+        clauses: impl Iterator<Item = ty::Clause<'tcx>>,
     ) -> impl Iterator<Item = ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>>
     {
         let tcx = self.tcx;
         let param_env = self.param_env;
-        predicates.filter_map(|p| p.to_opt_type_outlives()).filter(move |outlives_predicate| {
+        clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| {
             super::test_type_match::can_match_erased_ty(
                 tcx,
                 param_env,
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 26919872952..52f16a1b25c 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -258,7 +258,8 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
                             pred = pred.without_const(tcx);
                         }
                         elaboratable.child_with_derived_cause(
-                            pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
+                            pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref))
+                                .as_predicate(),
                             span,
                             bound_predicate.rebind(data),
                             index,
@@ -440,7 +441,7 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>(
                     tcx.super_predicates_that_define_assoc_item((trait_ref.def_id(), assoc_name));
                 for (super_predicate, _) in super_predicates.predicates {
                     let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref);
-                    if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() {
+                    if let Some(binder) = subst_predicate.as_trait_clause() {
                         stack.push(binder.map_bound(|t| t.trait_ref));
                     }
                 }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 5c5ec452850..6c1619819e0 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1593,33 +1593,24 @@ declare_lint_pass!(
 impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         use rustc_middle::ty::ClauseKind;
-        use rustc_middle::ty::PredicateKind::*;
 
         if cx.tcx.features().trivial_bounds {
             let predicates = cx.tcx.predicates_of(item.owner_id);
             for &(predicate, span) in predicates.predicates {
                 let predicate_kind_name = match predicate.kind().skip_binder() {
-                    Clause(ClauseKind::Trait(..)) => "trait",
-                    Clause(ClauseKind::TypeOutlives(..)) |
-                    Clause(ClauseKind::RegionOutlives(..)) => "lifetime",
+                    ClauseKind::Trait(..) => "trait",
+                    ClauseKind::TypeOutlives(..) |
+                    ClauseKind::RegionOutlives(..) => "lifetime",
 
                     // `ConstArgHasType` is never global as `ct` is always a param
-                    Clause(ClauseKind::ConstArgHasType(..)) |
+                    ClauseKind::ConstArgHasType(..)
                     // Ignore projections, as they can only be global
                     // if the trait bound is global
-                    Clause(ClauseKind::Projection(..)) |
+                    | ClauseKind::Projection(..)
                     // Ignore bounds that a user can't type
-                    Clause(ClauseKind::WellFormed(..)) |
+                    | ClauseKind::WellFormed(..)
                     // FIXME(generic_const_exprs): `ConstEvaluatable` can be written
-                    Clause(ClauseKind::ConstEvaluatable(..)) |
-                    AliasRelate(..) |
-                    ObjectSafe(..) |
-                    ClosureKind(..) |
-                    Subtype(..) |
-                    Coerce(..) |
-                    ConstEquate(..) |
-                    Ambiguous |
-                    TypeWellFormedFromEnv(..) => continue,
+                    | ClauseKind::ConstEvaluatable(..)  => continue,
                 };
                 if predicate.is_global() {
                     cx.emit_spanned_lint(
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 49597516b36..0613ef2c5e9 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -10,7 +10,7 @@ use rustc_errors::{
 use rustc_hir::def_id::DefId;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{
-    inhabitedness::InhabitedPredicate, PolyExistentialTraitRef, Predicate, Ty, TyCtxt,
+    inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
 };
 use rustc_session::parse::ParseSess;
 use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
@@ -352,7 +352,7 @@ impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
 #[diag(lint_builtin_trivial_bounds)]
 pub struct BuiltinTrivialBounds<'a> {
     pub predicate_kind_name: &'a str,
-    pub predicate: Predicate<'a>,
+    pub predicate: Clause<'a>,
 }
 
 #[derive(LintDiagnostic)]
@@ -1262,7 +1262,7 @@ pub struct RedundantSemicolonsDiag {
 
 // traits.rs
 pub struct DropTraitConstraintsDiag<'a> {
-    pub predicate: Predicate<'a>,
+    pub predicate: Clause<'a>,
     pub tcx: TyCtxt<'a>,
     pub def_id: DefId,
 }
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
index c2ed0e19f40..53fe0ceb234 100644
--- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
                     .super_predicates_of(def_id)
                     .predicates
                     .into_iter()
-                    .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred());
+                    .filter_map(|(pred, _)| pred.as_trait_clause());
             if direct_super_traits_iter.count() > 1 {
                 cx.emit_spanned_lint(
                     MULTIPLE_SUPERTRAIT_UPCASTABLE,
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index 8aba5349578..de11208062d 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -88,11 +88,10 @@ declare_lint_pass!(
 impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         use rustc_middle::ty::ClauseKind;
-        use rustc_middle::ty::PredicateKind::*;
 
         let predicates = cx.tcx.explicit_predicates_of(item.owner_id);
         for &(predicate, span) in predicates.predicates {
-            let Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
+            let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
                 continue
             };
             let def_id = trait_predicate.trait_ref.def_id;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 90014bd9267..b9318aee581 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -636,12 +636,6 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Symbol {
     }
 }
 
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
-    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
-        ty::codec::RefDecodable::decode(d)
-    }
-}
-
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
         ty::codec::RefDecodable::decode(d)
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index ac4cef34fdd..5a320865c95 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -83,9 +83,9 @@ macro_rules! arena_types {
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>>
                 >,
-            [] type_op_normalize_predicate:
+            [] type_op_normalize_clause:
                 rustc_middle::infer::canonical::Canonical<'tcx,
-                    rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>>
+                    rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Clause<'tcx>>
                 >,
             [] type_op_normalize_ty:
                 rustc_middle::infer::canonical::Canonical<'tcx,
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index fa62b7f32b1..4006a6cd1cc 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -420,7 +420,7 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
     }
 }
 
-impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
+impl<'tcx> Key for &'tcx ty::List<ty::Clause<'tcx>> {
     type CacheSelector = DefaultCacheSelector<Self>;
 
     fn default_span(&self, _: TyCtxt<'_>) -> Span {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 5d6a477b9ad..15215552f52 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -2031,10 +2031,10 @@ rustc_queries! {
     }
 
     /// Do not call this query directly: part of the `Normalize` type-op
-    query type_op_normalize_predicate(
-        goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>
+    query type_op_normalize_clause(
+        goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Clause<'tcx>>
     ) -> Result<
-        &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>,
+        &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>,
         NoSolution,
     > {
         desc { "normalizing `{:?}`", goal.value.value.value }
@@ -2125,7 +2125,7 @@ rustc_queries! {
         desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
     }
 
-    query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+    query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Clause<'tcx>>) -> &'tcx ty::List<ty::Clause<'tcx>> {
         desc { "revealing opaque types in `{:?}`", key }
     }
 
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 220118ae5cc..8751d3b7890 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -791,13 +791,6 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
     }
 }
 
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
-    #[inline]
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
-        RefDecodable::decode(d)
-    }
-}
-
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
     #[inline]
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs
index fcc8f457a8b..6e3d2d91ae9 100644
--- a/compiler/rustc_middle/src/traits/chalk.rs
+++ b/compiler/rustc_middle/src/traits/chalk.rs
@@ -385,7 +385,7 @@ impl<'tcx> chalk_ir::interner::HasInterner for RustInterner<'tcx> {
 /// A chalk environment and goal.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, TypeVisitable)]
 pub struct ChalkEnvironmentAndGoal<'tcx> {
-    pub environment: &'tcx ty::List<ty::Predicate<'tcx>>,
+    pub environment: &'tcx ty::List<ty::Clause<'tcx>>,
     pub goal: ty::Predicate<'tcx>,
 }
 
diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs
index d54b8c599d9..05c06efaf16 100644
--- a/compiler/rustc_middle/src/traits/util.rs
+++ b/compiler/rustc_middle/src/traits/util.rs
@@ -25,9 +25,7 @@ impl<'tcx> Elaborator<'tcx> {
             .super_predicates_of(trait_ref.def_id())
             .predicates
             .into_iter()
-            .flat_map(|(pred, _)| {
-                pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred()
-            })
+            .flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause())
             .map(|t| t.map_bound(|pred| pred.trait_ref))
             .filter(|supertrait_ref| self.visited.insert(*supertrait_ref));
 
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 248251e1ef5..22bed6ad1c5 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -368,16 +368,6 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> {
     }
 }
 
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
-    for [(ty::Predicate<'tcx>, Span)]
-{
-    fn decode(decoder: &mut D) -> &'tcx Self {
-        decoder.interner().arena.alloc_from_iter(
-            (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(),
-        )
-    }
-}
-
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
     fn decode(decoder: &mut D) -> &'tcx Self {
         decoder.interner().arena.alloc_from_iter(
@@ -406,11 +396,11 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty
     }
 }
 
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Predicate<'tcx>> {
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Clause<'tcx>> {
     fn decode(decoder: &mut D) -> &'tcx Self {
         let len = decoder.read_usize();
-        decoder.interner().mk_predicates_from_iter(
-            (0..len).map::<ty::Predicate<'tcx>, _>(|_| Decodable::decode(decoder)),
+        decoder.interner().mk_clauses_from_iter(
+            (0..len).map::<ty::Clause<'tcx>, _>(|_| Decodable::decode(decoder)),
         )
     }
 }
@@ -434,7 +424,7 @@ impl_decodable_via_ref! {
     &'tcx mir::BorrowCheckResult<'tcx>,
     &'tcx mir::coverage::CodeRegion,
     &'tcx ty::List<ty::BoundVariableKind>,
-    &'tcx ty::List<ty::Predicate<'tcx>>,
+    &'tcx ty::List<ty::Clause<'tcx>>,
     &'tcx ty::List<FieldIdx>,
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 1f9cf2c6448..1c610d6891b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -141,8 +141,6 @@ pub struct CtxtInterners<'tcx> {
     region: InternedSet<'tcx, RegionKind<'tcx>>,
     poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
     predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
-    // FIXME(clause): remove this when all usages are moved to predicate
-    predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
     clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
     projs: InternedSet<'tcx, List<ProjectionKind>>,
     place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@@ -168,7 +166,6 @@ impl<'tcx> CtxtInterners<'tcx> {
             poly_existential_predicates: Default::default(),
             canonical_var_infos: Default::default(),
             predicate: Default::default(),
-            predicates: Default::default(),
             clauses: Default::default(),
             projs: Default::default(),
             place_elems: Default::default(),
@@ -1260,10 +1257,11 @@ nop_lift! {region; Region<'a> => Region<'tcx>}
 nop_lift! {const_; Const<'a> => Const<'tcx>}
 nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
 nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
+nop_lift! {predicate; Clause<'a> => Clause<'tcx>}
 
 nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>}
 nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
-nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
+nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>}
 nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
 nop_list_lift! {projs; ProjectionKind => ProjectionKind}
 nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
@@ -1541,7 +1539,6 @@ slice_interners!(
     type_lists: pub mk_type_list(Ty<'tcx>),
     canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
     poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
-    predicates: intern_predicates(Predicate<'tcx>),
     clauses: intern_clauses(Clause<'tcx>),
     projs: pub mk_projs(ProjectionKind),
     place_elems: pub mk_place_elems(PlaceElem<'tcx>),
@@ -1597,9 +1594,7 @@ impl<'tcx> TyCtxt<'tcx> {
             let generic_predicates = self.super_predicates_of(trait_did);
 
             for (predicate, _) in generic_predicates.predicates {
-                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) =
-                    predicate.kind().skip_binder()
-                {
+                if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() {
                     if set.insert(data.def_id()) {
                         stack.push(data.def_id());
                     }
@@ -2087,18 +2082,11 @@ impl<'tcx> TyCtxt<'tcx> {
         self.intern_poly_existential_predicates(eps)
     }
 
-    pub fn mk_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
+    pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> {
         // FIXME consider asking the input slice to be sorted to avoid
         // re-interning permutations, in which case that would be asserted
         // here.
-        self.intern_predicates(preds)
-    }
-
-    pub fn mk_clauses(self, preds: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> {
-        // FIXME consider asking the input slice to be sorted to avoid
-        // re-interning permutations, in which case that would be asserted
-        // here.
-        self.intern_clauses(preds)
+        self.intern_clauses(clauses)
     }
 
     pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
@@ -2144,14 +2132,6 @@ impl<'tcx> TyCtxt<'tcx> {
         T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
     }
 
-    pub fn mk_predicates_from_iter<I, T>(self, iter: I) -> T::Output
-    where
-        I: Iterator<Item = T>,
-        T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>,
-    {
-        T::collect_and_apply(iter, |xs| self.mk_predicates(xs))
-    }
-
     pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
     where
         I: Iterator<Item = T>,
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 30f92b91cb7..58fd6e1aa27 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::Span;
 
-use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt};
+use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, TyCtxt};
 
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum GenericParamDefKind {
@@ -323,7 +323,7 @@ impl<'tcx> Generics {
 #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct GenericPredicates<'tcx> {
     pub parent: Option<DefId>,
-    pub predicates: &'tcx [(Predicate<'tcx>, Span)],
+    pub predicates: &'tcx [(Clause<'tcx>, Span)],
 }
 
 impl<'tcx> GenericPredicates<'tcx> {
@@ -341,8 +341,7 @@ impl<'tcx> GenericPredicates<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         substs: SubstsRef<'tcx>,
-    ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
-    {
+    ) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
         EarlyBinder::bind(self.predicates).subst_iter_copied(tcx, substs)
     }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 0e604fdf6f4..acb55a303b3 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -566,6 +566,12 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
     }
 }
 
+impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
+    }
+}
+
 /// A subset of predicates which can be assumed by the trait solver. They show up in
 /// an item's where clauses, hence the name `Clause`, and may either be user-written
 /// (such as traits) or may be inserted during lowering.
@@ -620,6 +626,10 @@ impl<'tcx> Clause<'tcx> {
             None
         }
     }
+
+    pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+        self.as_predicate().without_const(tcx).expect_clause()
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@@ -730,11 +740,10 @@ pub struct CratePredicatesMap<'tcx> {
     /// For each struct with outlive bounds, maps to a vector of the
     /// predicate of its outlive bounds. If an item has no outlives
     /// bounds, it will have no entry.
-    // FIXME(clause): should this be a `Clause`?
     pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
 }
 
-impl<'tcx> Predicate<'tcx> {
+impl<'tcx> Clause<'tcx> {
     /// Performs a substitution suitable for going from a
     /// poly-trait-ref to supertraits that must hold if that
     /// poly-trait-ref holds. This is slightly different from a normal
@@ -744,7 +753,7 @@ impl<'tcx> Predicate<'tcx> {
         self,
         tcx: TyCtxt<'tcx>,
         trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) -> Predicate<'tcx> {
+    ) -> Clause<'tcx> {
         // The interaction between HRTB and supertraits is not entirely
         // obvious. Let me walk you (and myself) through an example.
         //
@@ -830,7 +839,13 @@ impl<'tcx> Predicate<'tcx> {
         // 3) ['x] + ['b] -> ['x, 'b]
         let bound_vars =
             tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
-        tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars))
+
+        // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here?
+        tcx.reuse_or_mk_predicate(
+            self.as_predicate(),
+            ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
+        )
+        .expect_clause()
     }
 }
 
@@ -1301,6 +1316,14 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
     }
 }
 
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> {
+    #[inline(always)]
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+        let p: Predicate<'tcx> = self.to_predicate(tcx);
+        p.expect_clause()
+    }
+}
+
 impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
@@ -1456,8 +1479,7 @@ impl<'tcx> Predicate<'tcx> {
         }
     }
 
-    /// Turns a predicate into a clause without checking that it is a `PredicateKind::Clause`
-    /// first. This will ICE when methods are called on `Clause`.
+    /// Assert that the predicate is a clause.
     pub fn expect_clause(self) -> Clause<'tcx> {
         match self.kind().skip_binder() {
             PredicateKind::Clause(..) => Clause(self.0),
@@ -1487,7 +1509,7 @@ impl<'tcx> Predicate<'tcx> {
 /// [usize:Bar<isize>]]`.
 #[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
 pub struct InstantiatedPredicates<'tcx> {
-    pub predicates: Vec<Predicate<'tcx>>,
+    pub predicates: Vec<Clause<'tcx>>,
     pub spans: Vec<Span>,
 }
 
@@ -1506,9 +1528,9 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
 }
 
 impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
-    type Item = (Predicate<'tcx>, Span);
+    type Item = (Clause<'tcx>, Span);
 
-    type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>;
+    type IntoIter = std::iter::Zip<std::vec::IntoIter<Clause<'tcx>>, std::vec::IntoIter<Span>>;
 
     fn into_iter(self) -> Self::IntoIter {
         debug_assert_eq!(self.predicates.len(), self.spans.len());
@@ -1517,10 +1539,10 @@ impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
 }
 
 impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
-    type Item = (Predicate<'tcx>, Span);
+    type Item = (Clause<'tcx>, Span);
 
     type IntoIter = std::iter::Zip<
-        std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>,
+        std::iter::Copied<std::slice::Iter<'a, Clause<'tcx>>>,
         std::iter::Copied<std::slice::Iter<'a, Span>>,
     >;
 
@@ -1670,7 +1692,7 @@ pub struct ParamEnv<'tcx> {
     /// want `Reveal::All`.
     ///
     /// Note: This is packed, use the reveal() method to access it.
-    packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>,
+    packed: CopyTaggedPtr<&'tcx List<Clause<'tcx>>, ParamTag, true>,
 }
 
 #[derive(Copy, Clone)]
@@ -1736,7 +1758,7 @@ impl<'tcx> ParamEnv<'tcx> {
     }
 
     #[inline]
-    pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> {
+    pub fn caller_bounds(self) -> &'tcx List<Clause<'tcx>> {
         self.packed.pointer()
     }
 
@@ -1770,7 +1792,7 @@ impl<'tcx> ParamEnv<'tcx> {
     /// Construct a trait environment with the given set of predicates.
     #[inline]
     pub fn new(
-        caller_bounds: &'tcx List<Predicate<'tcx>>,
+        caller_bounds: &'tcx List<Clause<'tcx>>,
         reveal: Reveal,
         constness: hir::Constness,
     ) -> Self {
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 7afda73862d..af41a77c75b 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2864,20 +2864,35 @@ define_print_and_forward_display! {
         p!(print(binder))
     }
 
+    ty::Clause<'tcx> {
+        p!(print(self.kind()))
+    }
+
+    ty::ClauseKind<'tcx> {
+        match *self {
+            ty::ClauseKind::Trait(ref data) => {
+                p!(print(data))
+            }
+            ty::ClauseKind::RegionOutlives(predicate) => p!(print(predicate)),
+            ty::ClauseKind::TypeOutlives(predicate) => p!(print(predicate)),
+            ty::ClauseKind::Projection(predicate) => p!(print(predicate)),
+            ty::ClauseKind::ConstArgHasType(ct, ty) => {
+                p!("the constant `", print(ct), "` has type `", print(ty), "`")
+            },
+            ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"),
+            ty::ClauseKind::ConstEvaluatable(ct) => {
+                p!("the constant `", print(ct), "` can be evaluated")
+            }
+        }
+    }
+
     ty::PredicateKind<'tcx> {
         match *self {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref data)) => {
+            ty::PredicateKind::Clause(data) => {
                 p!(print(data))
             }
             ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
             ty::PredicateKind::Coerce(predicate) => p!(print(predicate)),
-            ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => p!(print(predicate)),
-            ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => p!(print(predicate)),
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => p!(print(predicate)),
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
-                p!("the constant `", print(ct), "` has type `", print(ty), "`")
-            },
-            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => p!(print(arg), " well-formed"),
             ty::PredicateKind::ObjectSafe(trait_def_id) => {
                 p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
             }
@@ -2886,9 +2901,6 @@ define_print_and_forward_display! {
                 print_value_path(closure_def_id, &[]),
                 write("` implements the trait `{}`", kind)
             ),
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
-                p!("the constant `", print(ct), "` can be evaluated")
-            }
             ty::PredicateKind::ConstEquate(c1, c2) => {
                 p!("the constant `", print(c1), "` equals `", print(c2), "`")
             }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 959bf032a83..bcc2b02758f 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -701,15 +701,6 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> {
-    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
-        self,
-        folder: &mut F,
-    ) -> Result<Self, F::Error> {
-        ty::util::fold_list(self, folder, |tcx, v| tcx.mk_predicates(v))
-    }
-}
-
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Clause<'tcx>> {
     fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
         self,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index c0627ab5c01..bb6d49e1773 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -715,7 +715,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
     /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
     /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
     /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example).
-    pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
+    pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> {
         use crate::ty::ToPredicate;
         match self.skip_binder() {
             ExistentialPredicate::Trait(tr) => {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index fcd624b3fef..bb08deff294 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1419,8 +1419,8 @@ pub struct AlwaysRequiresDrop;
 /// with their underlying types.
 pub fn reveal_opaque_types_in_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
-    val: &'tcx ty::List<ty::Predicate<'tcx>>,
-) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+    val: &'tcx ty::List<ty::Clause<'tcx>>,
+) -> &'tcx ty::List<ty::Clause<'tcx>> {
     let mut visitor = OpaqueTypeExpander {
         seen_opaque_tys: FxHashSet::default(),
         expanded_cache: FxHashMap::default(),
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 502f367dcb6..0b41e57be3b 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -2,7 +2,7 @@ use itertools::Itertools;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, EarlyBinder, PredicateKind, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt};
 use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
 use rustc_span::{symbol::sym, Span};
 use rustc_target::spec::abi::Abi;
@@ -74,7 +74,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
         let param_env = self.tcx.param_env(def_id);
         let bounds = param_env.caller_bounds();
         for bound in bounds {
-            if let Some(bound_ty) = self.is_pointer_trait(&bound.kind().skip_binder()) {
+            if let Some(bound_ty) = self.is_pointer_trait(bound) {
                 // Get the argument types as they appear in the function signature.
                 let arg_defs = self.tcx.fn_sig(def_id).subst_identity().skip_binder().inputs();
                 for (arg_num, arg_def) in arg_defs.iter().enumerate() {
@@ -104,8 +104,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
     }
 
     /// If the given predicate is the trait `fmt::Pointer`, returns the bound parameter type.
-    fn is_pointer_trait(&self, bound: &PredicateKind<'tcx>) -> Option<Ty<'tcx>> {
-        if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) = bound {
+    fn is_pointer_trait(&self, bound: ty::Clause<'tcx>) -> Option<Ty<'tcx>> {
+        if let ty::ClauseKind::Trait(predicate) = bound.kind().skip_binder() {
             self.tcx
                 .is_diagnostic_item(sym::Pointer, predicate.def_id())
                 .then(|| predicate.trait_ref.self_ty())
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 8a848e5db62..2be0ed7c0f6 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -112,13 +112,13 @@ trait DefIdVisitor<'tcx> {
         &mut self,
         predicates: ty::GenericPredicates<'tcx>,
     ) -> ControlFlow<Self::BreakTy> {
-        self.skeleton().visit_predicates(predicates)
+        self.skeleton().visit_clauses(predicates.predicates)
     }
     fn visit_clauses(
         &mut self,
-        predicates: &[(ty::Clause<'tcx>, Span)],
+        clauses: &[(ty::Clause<'tcx>, Span)],
     ) -> ControlFlow<Self::BreakTy> {
-        self.skeleton().visit_clauses(predicates)
+        self.skeleton().visit_clauses(clauses)
     }
 }
 
@@ -185,21 +185,8 @@ where
         }
     }
 
-    fn visit_predicates(
-        &mut self,
-        predicates: ty::GenericPredicates<'tcx>,
-    ) -> ControlFlow<V::BreakTy> {
-        let ty::GenericPredicates { parent: _, predicates } = predicates;
-        predicates.iter().try_for_each(|&(predicate, _span)| {
-            let clause = predicate
-                .as_clause()
-                .unwrap_or_else(|| bug!("unexpected predicate: {:?}", predicate));
-            self.visit_clause(clause)
-        })
-    }
-
     fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow<V::BreakTy> {
-        clauses.iter().try_for_each(|&(clause, _span)| self.visit_clause(clause))
+        clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause))
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index cde8a52cdec..9e8dbd0cde2 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -469,13 +469,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         candidates: &mut Vec<Candidate<'tcx>>,
     ) {
         for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() {
-            if let Some(clause) = assumption.as_clause() {
-                match G::consider_implied_clause(self, goal, clause, []) {
-                    Ok(result) => {
-                        candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result })
-                    }
-                    Err(NoSolution) => (),
+            match G::consider_implied_clause(self, goal, assumption, []) {
+                Ok(result) => {
+                    candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result })
                 }
+                Err(NoSolution) => (),
             }
         }
     }
@@ -685,19 +683,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             // since that'll cause ambiguity.
             //
             // We can remove this when we have implemented lifetime intersections in responses.
-            if assumption.to_opt_poly_projection_pred().is_some()
-                && !own_bounds.contains(&assumption)
-            {
+            if assumption.as_projection_clause().is_some() && !own_bounds.contains(&assumption) {
                 continue;
             }
 
-            if let Some(clause) = assumption.as_clause() {
-                match G::consider_object_bound_candidate(self, goal, clause) {
-                    Ok(result) => {
-                        candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
-                    }
-                    Err(NoSolution) => (),
+            match G::consider_object_bound_candidate(self, goal, assumption) {
+                Ok(result) => {
+                    candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
                 }
+                Err(NoSolution) => (),
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 439cf788ab4..9eac53c3983 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -343,7 +343,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     trait_ref: ty::TraitRef<'tcx>,
     object_bound: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-) -> Vec<ty::Predicate<'tcx>> {
+) -> Vec<ty::Clause<'tcx>> {
     let tcx = ecx.tcx();
     let mut requirements = vec![];
     requirements.extend(
@@ -353,11 +353,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
         // FIXME(associated_const_equality): Also add associated consts to
         // the requirements here.
         if item.kind == ty::AssocKind::Type {
-            requirements.extend(
-                tcx.item_bounds(item.def_id)
-                    .subst_iter(tcx, trait_ref.substs)
-                    .map(|clause| clause.as_predicate()),
-            );
+            requirements.extend(tcx.item_bounds(item.def_id).subst_iter(tcx, trait_ref.substs));
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 71557e8930d..05e9793130f 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -255,7 +255,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         // that are already in the `ParamEnv` (modulo regions): we already
         // know that they must hold.
         for predicate in param_env.caller_bounds() {
-            fresh_preds.insert(self.clean_pred(infcx, predicate));
+            fresh_preds.insert(self.clean_pred(infcx, predicate.as_predicate()));
         }
 
         let mut select = SelectionContext::new(&infcx);
@@ -270,8 +270,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             polarity: ty::ImplPolarity::Positive,
         }));
 
-        let computed_preds = param_env.caller_bounds().iter();
-        let mut user_computed_preds: FxIndexSet<_> = user_env.caller_bounds().iter().collect();
+        let computed_preds = param_env.caller_bounds().iter().map(|c| c.as_predicate());
+        let mut user_computed_preds: FxIndexSet<_> =
+            user_env.caller_bounds().iter().map(|c| c.as_predicate()).collect();
 
         let mut new_env = param_env;
         let dummy_cause = ObligationCause::dummy();
@@ -349,14 +350,14 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             let normalized_preds =
                 elaborate(tcx, computed_preds.clone().chain(user_computed_preds.iter().cloned()));
             new_env = ty::ParamEnv::new(
-                tcx.mk_predicates_from_iter(normalized_preds),
+                tcx.mk_clauses_from_iter(normalized_preds.filter_map(|p| p.as_clause())),
                 param_env.reveal(),
                 param_env.constness(),
             );
         }
 
         let final_user_env = ty::ParamEnv::new(
-            tcx.mk_predicates_from_iter(user_computed_preds.into_iter()),
+            tcx.mk_clauses_from_iter(user_computed_preds.into_iter().filter_map(|p| p.as_clause())),
             user_env.reveal(),
             user_env.constness(),
         );
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 0065c7fc253..9e1332c1c81 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -148,7 +148,12 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
         impl_def_id,
         self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs),
         trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)),
-        predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
+        predicates: tcx
+            .predicates_of(impl_def_id)
+            .instantiate(tcx, impl_substs)
+            .iter()
+            .map(|(c, _)| c.as_predicate())
+            .collect(),
     };
 
     let InferOk { value: mut header, obligations } =
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index f9f242d29f6..ab4727b8697 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -207,7 +207,7 @@ fn satisfied_from_param_env<'tcx>(
 
     for pred in param_env.caller_bounds() {
         match pred.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ce)) => {
+            ty::ClauseKind::ConstEvaluatable(ce) => {
                 let b_ct = tcx.expand_abstract_consts(ce);
                 let mut v = Visitor { ct, infcx, param_env, single_match };
                 let _ = b_ct.visit_with(&mut v);
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 1351d9bb257..96c183f9a58 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -84,7 +84,7 @@ pub fn recompute_applicable_impls<'tcx>(
         tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
     for (pred, span) in elaborate(tcx, predicates.into_iter()) {
         let kind = pred.kind();
-        if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = kind.skip_binder()
+        if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
             && param_env_candidate_may_apply(kind.rebind(trait_pred))
         {
             if kind.rebind(trait_pred.trait_ref) == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id())) {
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 71d2380f234..43b63762ba3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1201,7 +1201,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         DefIdOrName::Name("type parameter")
                     };
                     param_env.caller_bounds().iter().find_map(|pred| {
-                        if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = pred.kind().skip_binder()
+                        if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
                         && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
                         && proj.projection_ty.self_ty() == found
                         // args tuple will always be substs[1]
@@ -2001,7 +2001,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = cause
             && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
             && let Some(pred) = predicates.predicates.get(*idx)
-            && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = pred.kind().skip_binder()
+            && let ty::ClauseKind::Trait(trait_pred) = pred.kind().skip_binder()
             && self.tcx.is_fn_trait(trait_pred.def_id())
         {
             let expected_self =
@@ -2015,7 +2015,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             let other_pred = predicates.into_iter()
                 .enumerate()
                 .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() {
-                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))
+                    ty::ClauseKind::Trait(trait_pred)
                         if self.tcx.is_fn_trait(trait_pred.def_id())
                             && other_idx != idx
                             // Make sure that the self type matches
@@ -3526,7 +3526,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs)
                 && let Some(where_pred) = where_clauses.predicates.get(*idx)
             {
-                if let Some(where_pred) = where_pred.to_opt_poly_trait_pred()
+                if let Some(where_pred) = where_pred.as_trait_clause()
                     && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
                 {
                     let where_pred = self.instantiate_binder_with_placeholders(where_pred);
@@ -3549,7 +3549,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             }
                         })
                     };
-                } else if let Some(where_pred) = where_pred.to_opt_poly_projection_pred()
+                } else if let Some(where_pred) = where_pred.as_projection_clause()
                     && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred()
                     && let Some(found) = failed_pred.skip_binder().term.ty()
                 {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index a5481714e3e..ae76651c336 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -114,11 +114,11 @@ pub fn predicates_for_generics<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     generic_bounds: ty::InstantiatedPredicates<'tcx>,
 ) -> impl Iterator<Item = PredicateObligation<'tcx>> {
-    generic_bounds.into_iter().enumerate().map(move |(idx, (predicate, span))| Obligation {
+    generic_bounds.into_iter().enumerate().map(move |(idx, (clause, span))| Obligation {
         cause: cause(idx, span),
         recursion_depth: 0,
         param_env,
-        predicate,
+        predicate: clause.as_predicate(),
     })
 }
 
@@ -185,8 +185,8 @@ fn do_normalize_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     cause: ObligationCause<'tcx>,
     elaborated_env: ty::ParamEnv<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> Result<Vec<ty::Predicate<'tcx>>, ErrorGuaranteed> {
+    predicates: Vec<ty::Clause<'tcx>>,
+) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed> {
     let span = cause.span;
     // FIXME. We should really... do something with these region
     // obligations. But this call just continues the older
@@ -330,7 +330,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
 
     let elaborated_env = ty::ParamEnv::new(
-        tcx.mk_predicates(&predicates),
+        tcx.mk_clauses(&predicates),
         unnormalized_env.reveal(),
         unnormalized_env.constness(),
     );
@@ -355,10 +355,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     // TypeOutlives predicates - these are normally used by regionck.
     let outlives_predicates: Vec<_> = predicates
         .extract_if(|predicate| {
-            matches!(
-                predicate.kind().skip_binder(),
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
-            )
+            matches!(predicate.kind().skip_binder(), ty::ClauseKind::TypeOutlives(..))
         })
         .collect();
 
@@ -384,7 +381,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     // predicates here anyway. Keeping them here anyway because it seems safer.
     let outlives_env = non_outlives_predicates.iter().chain(&outlives_predicates).cloned();
     let outlives_env = ty::ParamEnv::new(
-        tcx.mk_predicates_from_iter(outlives_env),
+        tcx.mk_clauses_from_iter(outlives_env),
         unnormalized_env.reveal(),
         unnormalized_env.constness(),
     );
@@ -404,7 +401,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     predicates.extend(outlives_predicates);
     debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
     ty::ParamEnv::new(
-        tcx.mk_predicates(&predicates),
+        tcx.mk_clauses(&predicates),
         unnormalized_env.reveal(),
         unnormalized_env.constness(),
     )
@@ -439,10 +436,7 @@ where
 /// Normalizes the predicates and checks whether they hold in an empty environment. If this
 /// returns true, then either normalize encountered an error or one of the predicates did not
 /// hold. Used when creating vtables to check for unsatisfiable methods.
-pub fn impossible_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> bool {
+pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool {
     debug!("impossible_predicates(predicates={:?})", predicates);
 
     let infcx = tcx.infer_ctxt().build();
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index df93c4d45dc..178cd3d65a2 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -271,22 +271,22 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
         .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Type)
         .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied())
-        .filter_map(|(clause, span)| predicate_references_self(tcx, (clause.as_predicate(), span)))
+        .filter_map(|c| predicate_references_self(tcx, c))
         .collect()
 }
 
 fn predicate_references_self<'tcx>(
     tcx: TyCtxt<'tcx>,
-    (predicate, sp): (ty::Predicate<'tcx>, Span),
+    (predicate, sp): (ty::Clause<'tcx>, Span),
 ) -> Option<Span> {
     let self_ty = tcx.types.self_param;
     let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk().any(|arg| arg == self_ty.into());
     match predicate.kind().skip_binder() {
-        ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref data)) => {
+        ty::ClauseKind::Trait(ref data) => {
             // In the case of a trait predicate, we can skip the "self" type.
             data.trait_ref.substs[1..].iter().any(has_self_ty).then_some(sp)
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::Projection(ref data)) => {
+        ty::ClauseKind::Projection(ref data) => {
             // And similarly for projections. This should be redundant with
             // the previous check because any projection should have a
             // matching `Trait` predicate with the same inputs, but we do
@@ -304,24 +304,13 @@ fn predicate_references_self<'tcx>(
             // possible alternatives.
             data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp)
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(_ct, ty)) => {
-            has_self_ty(&ty.into()).then_some(sp)
-        }
-
-        ty::PredicateKind::AliasRelate(..) => bug!("`AliasRelate` not allowed as assumption"),
+        ty::ClauseKind::ConstArgHasType(_ct, ty) => has_self_ty(&ty.into()).then_some(sp),
 
-        ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
-        | ty::PredicateKind::ObjectSafe(..)
-        | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
-        | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
-        | ty::PredicateKind::ClosureKind(..)
-        | ty::PredicateKind::Subtype(..)
-        | ty::PredicateKind::Coerce(..)
+        ty::ClauseKind::WellFormed(..)
+        | ty::ClauseKind::TypeOutlives(..)
+        | ty::ClauseKind::RegionOutlives(..)
         // FIXME(generic_const_exprs): this can mention `Self`
-        | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-        | ty::PredicateKind::ConstEquate(..)
-        | ty::PredicateKind::Ambiguous
-        | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
+        | ty::ClauseKind::ConstEvaluatable(..) => None,
     }
 }
 
@@ -353,23 +342,15 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     let predicates = tcx.predicates_of(def_id);
     let predicates = predicates.instantiate_identity(tcx).predicates;
     elaborate(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() {
-        ty::PredicateKind::Clause(ty::ClauseKind::Trait(ref trait_pred)) => {
+        ty::ClauseKind::Trait(ref trait_pred) => {
             trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
-        | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
-        | ty::PredicateKind::Subtype(..)
-        | ty::PredicateKind::Coerce(..)
-        | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
-        | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
-        | ty::PredicateKind::ObjectSafe(..)
-        | ty::PredicateKind::ClosureKind(..)
-        | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
-        | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-        | ty::PredicateKind::ConstEquate(..)
-        | ty::PredicateKind::AliasRelate(..)
-        | ty::PredicateKind::Ambiguous
-        | ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
+        ty::ClauseKind::RegionOutlives(_)
+        | ty::ClauseKind::TypeOutlives(_)
+        | ty::ClauseKind::Projection(_)
+        | ty::ClauseKind::ConstArgHasType(_, _)
+        | ty::ClauseKind::WellFormed(_)
+        | ty::ClauseKind::ConstEvaluatable(_) => false,
     })
 }
 
@@ -575,7 +556,7 @@ fn virtual_call_violation_for_method<'tcx>(
         // because a trait object can't claim to live longer than the concrete
         // type. If the lifetime bound holds on dyn Trait then it's guaranteed
         // to hold as well on the concrete type.
-        if pred.to_opt_type_outlives().is_some() {
+        if pred.as_type_outlives_clause().is_some() {
             return false;
         }
 
@@ -592,11 +573,11 @@ fn virtual_call_violation_for_method<'tcx>(
         // only if the autotrait is one of the trait object's trait bounds, like
         // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
         // implement auto traits if the underlying type does as well.
-        if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
+        if let ty::ClauseKind::Trait(ty::TraitPredicate {
             trait_ref: pred_trait_ref,
             constness: ty::BoundConstness::NotConst,
             polarity: ty::ImplPolarity::Positive,
-        })) = pred.kind().skip_binder()
+        }) = pred.kind().skip_binder()
             && pred_trait_ref.self_ty() == tcx.types.self_param
             && tcx.trait_is_auto(pred_trait_ref.def_id)
         {
@@ -764,7 +745,6 @@ fn receiver_is_dispatchable<'tcx>(
         // Self: Unsize<U>
         let unsize_predicate =
             ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty])
-                .without_const()
                 .to_predicate(tcx);
 
         // U: Trait<Arg1, ..., ArgN>
@@ -781,7 +761,7 @@ fn receiver_is_dispatchable<'tcx>(
             param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
 
         ty::ParamEnv::new(
-            tcx.mk_predicates_from_iter(caller_bounds),
+            tcx.mk_clauses_from_iter(caller_bounds),
             param_env.reveal(),
             param_env.constness(),
         )
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 2a78c5befa4..c84c75cecdf 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1585,7 +1585,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
         obligation,
         candidate_set,
         ProjectionCandidate::TraitDef,
-        bounds.iter().map(|clause| clause.as_predicate()),
+        bounds.iter(),
         true,
     );
 }
@@ -1648,15 +1648,13 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
     ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionCandidate<'tcx>,
-    env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
+    env_predicates: impl Iterator<Item = ty::Clause<'tcx>>,
     potentially_unnormalized_candidates: bool,
 ) {
     let infcx = selcx.infcx;
     for predicate in env_predicates {
         let bound_predicate = predicate.kind();
-        if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) =
-            predicate.kind().skip_binder()
-        {
+        if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() {
             let data = bound_predicate.rebind(data);
             if data.projection_def_id() != obligation.predicate.def_id {
                 continue;
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 57ca14aa492..9559f5002f6 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -50,12 +50,12 @@ impl<'tcx> Normalizable<'tcx> for Ty<'tcx> {
     }
 }
 
-impl<'tcx> Normalizable<'tcx> for ty::Predicate<'tcx> {
+impl<'tcx> Normalizable<'tcx> for ty::Clause<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
         canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
-        tcx.type_op_normalize_predicate(canonicalized)
+        tcx.type_op_normalize_clause(canonicalized)
     }
 }
 
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 8eef7d5d63f..412b601c966 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -181,7 +181,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .caller_bounds()
             .iter()
             .filter(|p| !p.references_error())
-            .filter_map(|p| p.to_opt_poly_trait_pred());
+            .filter_map(|p| p.as_trait_clause());
 
         // Micro-optimization: filter out predicates relating to different traits.
         let matching_bounds =
@@ -402,7 +402,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         };
 
         for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
-            let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
+            let ty::ClauseKind::Trait(pred)
                 = predicate.kind().skip_binder() else { continue };
             if fn_ptr_trait != pred.trait_ref.def_id {
                 continue;
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index a50af417a44..c94fddc124f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -1108,12 +1108,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     obligation.cause.span,
                     [source],
                 );
-                nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
+                nested.push(predicate_to_obligation(tr.to_predicate(tcx)));
 
                 // If the type is `Foo + 'a`, ensure that the type
                 // being cast to `Foo + 'a` outlives `'a`:
                 let outlives = ty::OutlivesPredicate(source, r);
-                nested.push(predicate_to_obligation(ty::Binder::dummy(outlives).to_predicate(tcx)));
+                nested.push(predicate_to_obligation(
+                    ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx),
+                ));
             }
 
             // `[T; n]` -> `[T]`
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 0a8b7b688e7..5bc8fa45879 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2657,7 +2657,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                         }))
                     })
                 };
-            let predicate = normalize_with_depth_to(
+            let clause = normalize_with_depth_to(
                 self,
                 param_env,
                 cause.clone(),
@@ -2665,7 +2665,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 predicate,
                 &mut obligations,
             );
-            obligations.push(Obligation { cause, recursion_depth, param_env, predicate });
+            obligations.push(Obligation {
+                cause,
+                recursion_depth,
+                param_env,
+                predicate: clause.as_predicate(),
+            });
         }
 
         obligations
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 68ba8ceaa43..fee38aed0e2 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -508,22 +508,14 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
         Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
 
     for (mut p, _) in predicates {
-        if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() {
+        if let Some(poly_trait_ref) = p.as_trait_clause() {
             if Some(poly_trait_ref.def_id()) == sized_trait {
                 types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder());
                 continue;
             }
 
             if ty::BoundConstness::ConstIfConst == poly_trait_ref.skip_binder().constness {
-                let new_trait_pred = poly_trait_ref.map_bound(|mut trait_pred| {
-                    trait_pred.constness = ty::BoundConstness::NotConst;
-                    trait_pred
-                });
-
-                p = tcx.mk_predicate(
-                    new_trait_pred
-                        .map_bound(|p| ty::PredicateKind::Clause(ty::ClauseKind::Trait(p))),
-                )
+                p = p.without_const(tcx);
             }
         }
         pretty_predicates.push(p.to_string());
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 05a7f3e3b02..72adf3106ab 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -125,7 +125,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
 
         let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
             pred.subst_supertrait(tcx, &trait_ref)
-                .to_opt_poly_trait_pred()
+                .as_trait_clause()
                 .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
         });
         debug!("expand_trait_aliases: items={:?}", items.clone().collect::<Vec<_>>());
@@ -182,7 +182,7 @@ impl Iterator for SupertraitDefIds<'_> {
             predicates
                 .predicates
                 .iter()
-                .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred())
+                .filter_map(|(pred, _)| pred.as_trait_clause())
                 .map(|trait_ref| trait_ref.def_id())
                 .filter(|&super_def_id| visited.insert(super_def_id)),
         );
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 96b8e0b82b6..c05d557b774 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -115,7 +115,7 @@ pub fn prepare_vtable_segments<'tcx, T>(
                     .predicates
                     .into_iter()
                     .filter_map(move |(pred, _)| {
-                        pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
+                        pred.subst_supertrait(tcx, &inner_most_trait_ref).as_trait_clause()
                     });
 
                 'diving_in_skip_visited_traits: loop {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index e96e89ce73c..50c72947c26 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -976,7 +976,7 @@ pub fn object_region_bounds<'tcx>(
 pub(crate) fn required_region_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     erased_self_ty: Ty<'tcx>,
-    predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
+    predicates: impl Iterator<Item = ty::Clause<'tcx>>,
 ) -> Vec<ty::Region<'tcx>> {
     assert!(!erased_self_ty.has_escaping_bound_vars());
 
@@ -984,24 +984,7 @@ pub(crate) fn required_region_bounds<'tcx>(
         .filter_map(|pred| {
             debug!(?pred);
             match pred.kind().skip_binder() {
-                ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
-                | ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
-                | ty::PredicateKind::Subtype(..)
-                | ty::PredicateKind::Coerce(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
-                | ty::PredicateKind::ObjectSafe(..)
-                | ty::PredicateKind::ClosureKind(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-                | ty::PredicateKind::ConstEquate(..)
-                | ty::PredicateKind::Ambiguous
-                | ty::PredicateKind::AliasRelate(..)
-                | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
-                    ref t,
-                    ref r,
-                ))) => {
+                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
                     // Search for a bound of the form `erased_self_ty
                     // : 'a`, but be wary of something like `for<'a>
                     // erased_self_ty : 'a` (we interpret a
@@ -1017,6 +1000,12 @@ pub(crate) fn required_region_bounds<'tcx>(
                         None
                     }
                 }
+                ty::ClauseKind::Trait(_)
+                | ty::ClauseKind::RegionOutlives(_)
+                | ty::ClauseKind::Projection(_)
+                | ty::ClauseKind::ConstArgHasType(_, _)
+                | ty::ClauseKind::WellFormed(_)
+                | ty::ClauseKind::ConstEvaluatable(_) => None,
             }
         })
         .collect()
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 7e64cbdf54a..6948151c644 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -42,7 +42,7 @@ impl<'tcx> RustIrDatabase<'tcx> {
             .tcx
             .predicates_defined_on(def_id)
             .instantiate_own(self.interner.tcx, bound_vars)
-            .filter_map(|(wc, _)| LowerInto::lower_into(wc, self.interner))
+            .filter_map(|(wc, _)| LowerInto::lower_into(wc.as_predicate(), self.interner))
             .collect()
     }
 
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index aefe57e0ddf..7deb165271a 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -93,36 +93,29 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
             let (predicate, binders, _named_regions) =
                 collect_bound_vars(interner, interner.tcx, predicate.kind());
             let consequence = match predicate {
-                ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
+                // TODO: FIXME
+                /*ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
                     chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner)))
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
-                    chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Trait(
-                        predicate.trait_ref.lower_into(interner),
-                    ))
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => {
-                    chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::LifetimeOutlives(
-                        chalk_ir::LifetimeOutlives {
-                            a: predicate.0.lower_into(interner),
-                            b: predicate.1.lower_into(interner),
-                        },
-                    ))
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => {
-                    chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::TypeOutlives(
-                        chalk_ir::TypeOutlives {
-                            ty: predicate.0.lower_into(interner),
-                            lifetime: predicate.1.lower_into(interner),
-                        },
-                    ))
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
-                    chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::AliasEq(
-                        predicate.lower_into(interner),
-                    ))
-                }
-                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => match arg.unpack() {
+                }*/
+                ty::ClauseKind::Trait(predicate) => chalk_ir::DomainGoal::FromEnv(
+                    chalk_ir::FromEnv::Trait(predicate.trait_ref.lower_into(interner)),
+                ),
+                ty::ClauseKind::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
+                    chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
+                        a: predicate.0.lower_into(interner),
+                        b: predicate.1.lower_into(interner),
+                    }),
+                ),
+                ty::ClauseKind::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
+                    chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
+                        ty: predicate.0.lower_into(interner),
+                        lifetime: predicate.1.lower_into(interner),
+                    }),
+                ),
+                ty::ClauseKind::Projection(predicate) => chalk_ir::DomainGoal::Holds(
+                    chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
+                ),
+                ty::ClauseKind::WellFormed(arg) => match arg.unpack() {
                     ty::GenericArgKind::Type(ty) => chalk_ir::DomainGoal::WellFormed(
                         chalk_ir::WellFormed::Ty(ty.lower_into(interner)),
                     ),
@@ -131,15 +124,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
                         interner.tcx.types.unit.lower_into(interner),
                     )),
                 },
-                ty::PredicateKind::ObjectSafe(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
-                | ty::PredicateKind::AliasRelate(..)
-                | ty::PredicateKind::ClosureKind(..)
-                | ty::PredicateKind::Subtype(..)
-                | ty::PredicateKind::Coerce(..)
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-                | ty::PredicateKind::Ambiguous
-                | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
+                ty::ClauseKind::ConstArgHasType(..) | ty::ClauseKind::ConstEvaluatable(_) => {
+                    bug!("unexpected predicate {}", predicate)
+                }
             };
             let value = chalk_ir::ProgramClauseImplication {
                 consequence,
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 98d814d54f2..01b9a5640b8 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -2,8 +2,8 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::query::NoSolution;
+use rustc_middle::ty::{Clause, ParamEnvAnd};
 use rustc_middle::ty::{FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
-use rustc_middle::ty::{ParamEnvAnd, Predicate};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{
@@ -23,7 +23,7 @@ pub(crate) fn provide(p: &mut Providers) {
         type_op_prove_predicate,
         type_op_subtype,
         type_op_normalize_ty,
-        type_op_normalize_predicate,
+        type_op_normalize_clause,
         type_op_normalize_fn_sig,
         type_op_normalize_poly_fn_sig,
         ..*p
@@ -70,10 +70,10 @@ fn type_op_normalize_ty<'tcx>(
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
 }
 
-fn type_op_normalize_predicate<'tcx>(
+fn type_op_normalize_clause<'tcx>(
     tcx: TyCtxt<'tcx>,
-    canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Predicate<'tcx>>>>,
-) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Predicate<'tcx>>>, NoSolution> {
+    canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Clause<'tcx>>>>,
+) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Clause<'tcx>>>, NoSolution> {
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
 }
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index fe2d1fba7fe..44a253b6539 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -4,8 +4,8 @@ use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{
-    self, Binder, EarlyBinder, ImplTraitInTraitData, Predicate, PredicateKind, ToPredicate, Ty,
-    TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    self, EarlyBinder, ImplTraitInTraitData, ToPredicate, Ty, TyCtxt, TypeSuperVisitable,
+    TypeVisitable, TypeVisitor,
 };
 use rustc_session::config::TraitSolver;
 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
@@ -245,7 +245,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     };
 
     let unnormalized_env =
-        ty::ParamEnv::new(tcx.mk_predicates(&predicates), traits::Reveal::UserFacing, constness);
+        ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing, constness);
 
     let body_id = local_did.unwrap_or(CRATE_DEF_ID);
     let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
@@ -258,7 +258,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
 /// its corresponding opaque within the body of a default-body trait method.
 struct ImplTraitInTraitFinder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    predicates: &'a mut Vec<Predicate<'tcx>>,
+    predicates: &'a mut Vec<ty::Clause<'tcx>>,
     fn_def_id: DefId,
     bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
     seen: FxHashSet<DefId>,
@@ -340,9 +340,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
 /// that are assumed to be well-formed (because they come from the environment).
 ///
 /// Used only in chalk mode.
-fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predicate<'_>> {
+fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<ty::Clause<'_>> {
     use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
-    use rustc_middle::ty::subst::GenericArgKind;
 
     debug!("environment(def_id = {:?})", def_id);
 
@@ -428,8 +427,9 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predica
 
         NodeKind::Other => (),
     }
-    let input_clauses = inputs.into_iter().filter_map(|arg| {
-        match arg.unpack() {
+    let input_clauses = inputs.into_iter().filter_map(|_arg| {
+        // TODO: FIXME
+        /*match arg.unpack() {
             GenericArgKind::Type(ty) => {
                 let binder = Binder::dummy(PredicateKind::TypeWellFormedFromEnv(ty));
                 Some(tcx.mk_predicate(binder))
@@ -440,10 +440,11 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predica
 
             // FIXME(eddyb) support const generics in Chalk
             GenericArgKind::Const(_) => None,
-        }
+        }*/
+        None
     });
 
-    tcx.mk_predicates_from_iter(clauses.chain(input_clauses))
+    tcx.mk_clauses_from_iter(clauses.chain(input_clauses))
 }
 
 fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 492b0b79557..92bae551644 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -317,14 +317,14 @@ where
         lifetime_predicates
     }
 
-    fn extract_for_generics(&self, pred: ty::Predicate<'tcx>) -> FxHashSet<GenericParamDef> {
+    fn extract_for_generics(&self, pred: ty::Clause<'tcx>) -> FxHashSet<GenericParamDef> {
         let bound_predicate = pred.kind();
         let tcx = self.cx.tcx;
         let regions = match bound_predicate.skip_binder() {
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_pred)) => {
+            ty::ClauseKind::Trait(poly_trait_pred) => {
                 tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_trait_pred))
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::Projection(poly_proj_pred)) => {
+            ty::ClauseKind::Projection(poly_proj_pred) => {
                 tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_proj_pred))
             }
             _ => return FxHashSet::default(),
@@ -449,9 +449,7 @@ where
             .filter(|p| {
                 !orig_bounds.contains(p)
                     || match p.kind().skip_binder() {
-                        ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
-                            pred.def_id() == sized_trait
-                        }
+                        ty::ClauseKind::Trait(pred) => pred.def_id() == sized_trait,
                         _ => false,
                     }
             })
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 6bf4ac90753..c041df64b8d 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -326,36 +326,24 @@ fn clean_where_predicate<'tcx>(
 }
 
 pub(crate) fn clean_predicate<'tcx>(
-    predicate: ty::Predicate<'tcx>,
+    predicate: ty::Clause<'tcx>,
     cx: &mut DocContext<'tcx>,
 ) -> Option<WherePredicate> {
     let bound_predicate = predicate.kind();
     match bound_predicate.skip_binder() {
-        ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
-            clean_poly_trait_predicate(bound_predicate.rebind(pred), cx)
-        }
-        ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(pred)) => {
-            clean_region_outlives_predicate(pred)
-        }
-        ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(pred)) => {
+        ty::ClauseKind::Trait(pred) => clean_poly_trait_predicate(bound_predicate.rebind(pred), cx),
+        ty::ClauseKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred),
+        ty::ClauseKind::TypeOutlives(pred) => {
             clean_type_outlives_predicate(bound_predicate.rebind(pred), cx)
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
+        ty::ClauseKind::Projection(pred) => {
             Some(clean_projection_predicate(bound_predicate.rebind(pred), cx))
         }
         // FIXME(generic_const_exprs): should this do something?
-        ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => None,
-        ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => None,
-        ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => None,
-
-        ty::PredicateKind::Subtype(..)
-        | ty::PredicateKind::AliasRelate(..)
-        | ty::PredicateKind::Coerce(..)
-        | ty::PredicateKind::ObjectSafe(..)
-        | ty::PredicateKind::ClosureKind(..)
-        | ty::PredicateKind::ConstEquate(..)
-        | ty::PredicateKind::Ambiguous
-        | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
+        ty::ClauseKind::ConstEvaluatable(..)
+        | ty::ClauseKind::WellFormed(..)
+        | ty::ClauseKind::ConstArgHasType(..)
+        | ty::ClauseKind::TypeWellFormedFromEnv(..) => None,
     }
 }
 
@@ -805,19 +793,17 @@ fn clean_ty_generics<'tcx>(
             let param_idx = (|| {
                 let bound_p = p.kind();
                 match bound_p.skip_binder() {
-                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
+                    ty::ClauseKind::Trait(pred) => {
                         if let ty::Param(param) = pred.self_ty().kind() {
                             return Some(param.index);
                         }
                     }
-                    ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
-                        ty::OutlivesPredicate(ty, _reg),
-                    )) => {
+                    ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
                         if let ty::Param(param) = ty.kind() {
                             return Some(param.index);
                         }
                     }
-                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => {
+                    ty::ClauseKind::Projection(p) => {
                         if let ty::Param(param) = p.projection_ty.self_ty().kind() {
                             projection = Some(bound_p.rebind(p));
                             return Some(param.index);
@@ -1354,10 +1340,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
 
             let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
             if let ty::TraitContainer = assoc_item.container {
-                let bounds = tcx
-                    .explicit_item_bounds(assoc_item.def_id)
-                    .subst_identity_iter_copied()
-                    .map(|(c, s)| (c.as_predicate(), s));
+                let bounds =
+                    tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied();
                 predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
             }
             let mut generics = clean_ty_generics(
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index a8221cc9449..65b1b72adc1 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -128,9 +128,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId)
         .predicates
         .iter()
         .filter_map(|(pred, _)| {
-            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
-                pred.kind().skip_binder()
-            {
+            if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() {
                 if pred.trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None }
             } else {
                 None
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index ee6aef71980..1ecaa1a123c 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -27,7 +27,7 @@ use rustc_middle::mir::{Rvalue, StatementKind};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{
     self, Binder, BoundVariableKind, ClauseKind, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy,
-    PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
+    ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
 };
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{symbol::sym, Span, Symbol};
@@ -1133,7 +1133,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
     let projection_predicates = predicates
         .iter()
         .filter_map(|predicate| {
-            if let PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) = predicate.kind().skip_binder() {
+            if let ClauseKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
                 Some(projection_predicate)
             } else {
                 None
@@ -1147,7 +1147,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
     if predicates
         .iter()
         .filter_map(|predicate| {
-            if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder()
+            if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
                 && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx)
             {
                 Some(trait_predicate.trait_ref.def_id)
@@ -1209,7 +1209,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
         }
 
         predicates.iter().all(|predicate| {
-            if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder()
+            if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
                 && cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id)
                 && let ty::Param(param_ty) = trait_predicate.self_ty().kind()
                 && let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack()
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 8d84e756ff8..10a2f0cb1e7 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::{
-    self, Binder, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind,
-    TraitPredicate, Ty, TyCtxt,
+    self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv,
+    ToPredicate, TraitPredicate, Ty, TyCtxt,
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
@@ -503,7 +503,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
 
     let ty_predicates = tcx.predicates_of(did).predicates;
     for (p, _) in ty_predicates {
-        if let PredicateKind::Clause(ClauseKind::Trait(p)) = p.kind().skip_binder()
+        if let ClauseKind::Trait(p) = p.kind().skip_binder()
             && p.trait_ref.def_id == eq_trait_id
             && let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
             && p.constness == BoundConstness::NotConst
@@ -514,13 +514,13 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
     }
 
     ParamEnv::new(
-        tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain(
+        tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain(
             params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
-                tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
+                ClauseKind::Trait(TraitPredicate {
                     trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]),
                     constness: BoundConstness::NotConst,
                     polarity: ImplPolarity::Positive,
-                }))))
+                }).to_predicate(tcx)
             }),
         )),
         Reveal::UserFacing,
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index cf85d3174db..0699997d0d2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -16,7 +16,7 @@ use rustc_hir::{
 };
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty};
+use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol};
 
@@ -175,7 +175,7 @@ fn check_collect_into_intoiterator<'tcx>(
                 .caller_bounds()
                 .into_iter()
                 .filter_map(|p| {
-                    if let PredicateKind::Clause(ClauseKind::Trait(t)) = p.kind().skip_binder()
+                    if let ClauseKind::Trait(t) = p.kind().skip_binder()
                             && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) {
                                 Some(t.self_ty())
                             } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 06fa95cd657..80eb00a1b42 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -14,7 +14,7 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty};
+use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, ProjectionPredicate, TraitPredicate, Ty};
 use rustc_span::{sym, Symbol};
 use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
 
@@ -345,12 +345,12 @@ fn get_input_traits_and_projections<'tcx>(
     let mut projection_predicates = Vec::new();
     for predicate in cx.tcx.param_env(callee_def_id).caller_bounds() {
         match predicate.kind().skip_binder() {
-            PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) => {
+            ClauseKind::Trait(trait_predicate) => {
                 if trait_predicate.trait_ref.self_ty() == input {
                     trait_predicates.push(trait_predicate);
                 }
             },
-            PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) => {
+            ClauseKind::Projection(projection_predicate) => {
                 if projection_predicate.projection_ty.self_ty() == input {
                     projection_predicates.push(projection_predicate);
                 }
@@ -407,7 +407,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
 
                         let mut trait_predicates = cx.tcx.param_env(callee_def_id)
                             .caller_bounds().iter().filter(|predicate| {
-                            if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate))
+                            if let ClauseKind::Trait(trait_predicate)
                                     = predicate.kind().skip_binder()
                                 && trait_predicate.trait_ref.self_ty() == *param_ty
                             {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 3773975e955..c0970048cdf 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
             .filter_map(|pred| {
                 // Note that we do not want to deal with qualified predicates here.
                 match pred.kind().no_bound_vars() {
-                    Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) if pred.def_id() != sized_trait => {
+                    Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => {
                         Some(pred)
                     },
                     _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index a375e5d5b4c..99a1d197678 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{Closure, Expr, ExprKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
-use rustc_middle::ty::{ClauseKind, GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate};
+use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, BytePos, Span};
 
@@ -45,7 +45,7 @@ fn get_trait_predicates_for_trait_id<'tcx>(
     let mut preds = Vec::new();
     for (pred, _) in generics.predicates {
         if_chain! {
-            if let PredicateKind::Clause(ClauseKind::Trait(poly_trait_pred)) = pred.kind().skip_binder();
+            if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder();
             let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred));
             if let Some(trait_def_id) = trait_id;
             if trait_def_id == trait_pred.trait_ref.def_id;
@@ -63,7 +63,7 @@ fn get_projection_pred<'tcx>(
     trait_pred: TraitPredicate<'tcx>,
 ) -> Option<ProjectionPredicate<'tcx>> {
     generics.predicates.iter().find_map(|(proj_pred, _)| {
-        if let ty::PredicateKind::Clause(ClauseKind::Projection(pred)) = proj_pred.kind().skip_binder() {
+        if let ClauseKind::Projection(pred) = proj_pred.kind().skip_binder() {
             let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred));
             if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs {
                 return Some(projection_pred);
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index a42b2ccee88..659c693f87a 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -15,7 +15,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, PredicateKind};
+use rustc_middle::ty;
 use rustc_span::{sym, Symbol};
 use std::cmp;
 use std::ops;
@@ -73,7 +73,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
             .flat_map(|v| v.fields.iter())
             .any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_)))
             && all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() {
-                PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker,
+                ty::ClauseKind::Trait(pred) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker,
                 _ => true,
             })
             && subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_)))
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index a10eb8646af..b7e83ce6caa 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -21,35 +21,6 @@ type McfResult = Result<(), (Span, Cow<'static, str>)>;
 
 pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) -> McfResult {
     let def_id = body.source.def_id();
-    let mut current = def_id;
-    loop {
-        let predicates = tcx.predicates_of(current);
-        for (predicate, _) in predicates.predicates {
-            match predicate.kind().skip_binder() {
-                ty::PredicateKind::Clause(
-                    ty::ClauseKind::RegionOutlives(_)
-                    | ty::ClauseKind::TypeOutlives(_)
-                    | ty::ClauseKind::Projection(_)
-                    | ty::ClauseKind::Trait(..)
-                    | ty::ClauseKind::ConstArgHasType(..),
-                )
-                | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
-                | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-                | ty::PredicateKind::ConstEquate(..)
-                | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
-                ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"),
-                ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
-                ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
-                ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
-                ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"),
-                ty::PredicateKind::Ambiguous => panic!("ambiguous predicate on function: {predicate:#?}"),
-            }
-        }
-        match predicates.parent {
-            Some(parent) => current = parent,
-            None => break,
-        }
-    }
 
     for local in &body.local_decls {
         check_ty(tcx, local.ty, local.source_info.span)?;
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 2b185943c59..8d3aecd4785 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -17,7 +17,7 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::{
     self, layout::ValidityRequirement, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, IntTy, List, ParamEnv,
-    Predicate, PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+    Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
     TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr,
 };
 use rustc_middle::ty::{GenericArg, GenericArgKind};
@@ -563,7 +563,7 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t
 }
 
 /// Gets an iterator over all predicates which apply to the given item.
-pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator<Item = &(Predicate<'_>, Span)> {
+pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator<Item = &(ty::Clause<'_>, Span)> {
     let mut next_id = Some(id);
     iter::from_fn(move || {
         next_id.take().map(|id| {
@@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
         ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => sig_from_bounds(
             cx,
             ty,
-            cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()),
+            cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs),
             cx.tcx.opt_parent(def_id),
         ),
         ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
@@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
 fn sig_from_bounds<'tcx>(
     cx: &LateContext<'tcx>,
     ty: Ty<'tcx>,
-    predicates: impl IntoIterator<Item = Predicate<'tcx>>,
+    predicates: impl IntoIterator<Item = ty::Clause<'tcx>>,
     predicates_id: Option<DefId>,
 ) -> Option<ExprFnSig<'tcx>> {
     let mut inputs = None;
@@ -707,7 +707,7 @@ fn sig_from_bounds<'tcx>(
 
     for pred in predicates {
         match pred.kind().skip_binder() {
-            PredicateKind::Clause(ty::ClauseKind::Trait(p))
+            ty::ClauseKind::Trait(p)
                 if (lang_items.fn_trait() == Some(p.def_id())
                     || lang_items.fn_mut_trait() == Some(p.def_id())
                     || lang_items.fn_once_trait() == Some(p.def_id()))
@@ -720,7 +720,7 @@ fn sig_from_bounds<'tcx>(
                 }
                 inputs = Some(i);
             },
-            PredicateKind::Clause(ty::ClauseKind::Projection(p))
+            ty::ClauseKind::Projection(p)
                 if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty =>
             {
                 if output.is_some() {
@@ -937,7 +937,7 @@ pub fn adt_and_variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<
 }
 
 /// Checks if the type is a type parameter implementing `FnOnce`, but not `FnMut`.
-pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [Predicate<'_>]) -> bool {
+pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [ty::Clause<'_>]) -> bool {
     let ty::Param(ty) = *ty.kind() else {
         return false;
     };
@@ -950,7 +950,7 @@ pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tc
     predicates
         .iter()
         .try_fold(false, |found, p| {
-            if let PredicateKind::Clause(ty::ClauseKind::Trait(p)) = p.kind().skip_binder()
+            if let ty::ClauseKind::Trait(p) = p.kind().skip_binder()
             && let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
             && ty.index == self_ty.index
         {
diff --git a/tests/ui/chalkify/recursive_where_clause_on_type.stderr b/tests/ui/chalkify/recursive_where_clause_on_type.stderr
index cead5adeaaa..2d70cff841f 100644
--- a/tests/ui/chalkify/recursive_where_clause_on_type.stderr
+++ b/tests/ui/chalkify/recursive_where_clause_on_type.stderr
@@ -1,14 +1,21 @@
-error: the type `S` is not well-formed
-  --> $DIR/recursive_where_clause_on_type.rs:28:11
+error[E0277]: the trait bound `S: Bar` is not satisfied
+  --> $DIR/recursive_where_clause_on_type.rs:14:14
+   |
+LL | impl Foo for S {
+   |              ^ the trait `Bar` is not implemented for `S`
+   |
+note: required by a bound in `Foo`
+  --> $DIR/recursive_where_clause_on_type.rs:10:12
    |
-LL |     foo::<S>()
-   |           ^
+LL | trait Foo: Bar { }
+   |            ^^^ required by this bound in `Foo`
 
 error: the type `S` is not well-formed
-  --> $DIR/recursive_where_clause_on_type.rs:28:5
+  --> $DIR/recursive_where_clause_on_type.rs:14:14
    |
-LL |     foo::<S>()
-   |     ^^^^^^^^
+LL | impl Foo for S {
+   |              ^
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0277`.