about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBoxy <supbscripter@gmail.com>2023-02-10 14:29:28 +0000
committerBoxy <supbscripter@gmail.com>2023-02-10 14:33:13 +0000
commit1f89e2aef272e1222adc4bf95de2baf802c92a2d (patch)
tree2ced6bf98dd4d9865f4bfe748b75d5942f014663
parent23ab2464befc41d74e04cc2259366a439b346cb9 (diff)
downloadrust-1f89e2aef272e1222adc4bf95de2baf802c92a2d.tar.gz
rust-1f89e2aef272e1222adc4bf95de2baf802c92a2d.zip
emit `AliasEq` when relating type and const aliases
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs6
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs6
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs87
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs17
-rw-r--r--compiler/rustc_infer/src/infer/glb.rs22
-rw-r--r--compiler/rustc_infer/src/infer/lattice.rs11
-rw-r--r--compiler/rustc_infer/src/infer/lub.rs28
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs89
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs18
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs15
12 files changed, 157 insertions, 147 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index b2702eafd33..8dd06187877 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,4 +1,4 @@
-use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
+use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_infer::traits::PredicateObligations;
 use rustc_middle::mir::ConstraintCategory;
@@ -140,10 +140,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
         );
     }
 
-    fn normalization() -> NormalizationStrategy {
-        NormalizationStrategy::Eager
-    }
-
     fn forbid_inference_vars() -> bool {
         true
     }
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 7cc9e49b1b6..0c97217bd6a 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -12,7 +12,7 @@ use crate::infer::canonical::{
     Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
     QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
 };
-use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
+use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
 use crate::traits::query::{Fallible, NoSolution};
@@ -717,10 +717,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
         });
     }
 
-    fn normalization() -> NormalizationStrategy {
-        NormalizationStrategy::Eager
-    }
-
     fn forbid_inference_vars() -> bool {
         true
     }
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index a567b6acdbe..cb1e14aaeaf 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -38,8 +38,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{
-    self, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
-    TypeVisitable,
+    self, AliasKind, FallibleTypeFolder, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable,
+    TypeSuperFoldable, TypeVisitable,
 };
 use rustc_middle::ty::{IntType, UintType};
 use rustc_span::{Span, DUMMY_SP};
@@ -74,7 +74,7 @@ impl<'tcx> InferCtxt<'tcx> {
         b: Ty<'tcx>,
     ) -> RelateResult<'tcx, Ty<'tcx>>
     where
-        R: TypeRelation<'tcx>,
+        R: ObligationEmittingRelation<'tcx>,
     {
         let a_is_expected = relation.a_is_expected();
 
@@ -122,6 +122,15 @@ impl<'tcx> InferCtxt<'tcx> {
                 Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
             }
 
+            (ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => {
+                relation.register_type_equate_obligation(a.into(), b.into());
+                Ok(b)
+            }
+            (_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => {
+                relation.register_type_equate_obligation(b.into(), a.into());
+                Ok(a)
+            }
+
             _ => ty::relate::super_relate_tys(relation, a, b),
         }
     }
@@ -133,7 +142,7 @@ impl<'tcx> InferCtxt<'tcx> {
         b: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>>
     where
-        R: ConstEquateRelation<'tcx>,
+        R: ObligationEmittingRelation<'tcx>,
     {
         debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
         if a == b {
@@ -169,7 +178,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 // FIXME(#59490): Need to remove the leak check to accommodate
                 // escaping bound variables here.
                 if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
-                    relation.const_equate_obligation(a, b);
+                    relation.register_const_equate_obligation(a, b);
                 }
                 return Ok(b);
             }
@@ -177,7 +186,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 // FIXME(#59490): Need to remove the leak check to accommodate
                 // escaping bound variables here.
                 if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
-                    relation.const_equate_obligation(a, b);
+                    relation.register_const_equate_obligation(a, b);
                 }
                 return Ok(a);
             }
@@ -435,32 +444,21 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         Ok(Generalization { ty, needs_wf })
     }
 
-    pub fn add_const_equate_obligation(
+    pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+        self.obligations.extend(obligations.into_iter());
+    }
+
+    pub fn register_predicates(
         &mut self,
-        a_is_expected: bool,
-        a: ty::Const<'tcx>,
-        b: ty::Const<'tcx>,
+        obligations: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
     ) {
-        let predicate = if a_is_expected {
-            ty::PredicateKind::ConstEquate(a, b)
-        } else {
-            ty::PredicateKind::ConstEquate(b, a)
-        };
-        self.obligations.push(Obligation::new(
-            self.tcx(),
-            self.trace.cause.clone(),
-            self.param_env,
-            ty::Binder::dummy(predicate),
-        ));
+        self.obligations.extend(obligations.into_iter().map(|to_pred| {
+            Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, to_pred)
+        }))
     }
 
     pub fn mark_ambiguous(&mut self) {
-        self.obligations.push(Obligation::new(
-            self.tcx(),
-            self.trace.cause.clone(),
-            self.param_env,
-            ty::Binder::dummy(ty::PredicateKind::Ambiguous),
-        ));
+        self.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
     }
 }
 
@@ -775,11 +773,42 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     }
 }
 
-pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> {
+pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
+    /// Register obligations that must hold in order for this relation to hold
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
+
+    /// Register predicates that must hold in order for this relation to hold. Uses
+    /// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should
+    /// be used if control over the obligaton causes is required.
+    fn register_predicates(
+        &mut self,
+        obligations: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
+    );
+
     /// Register an obligation that both constants must be equal to each other.
     ///
     /// If they aren't equal then the relation doesn't hold.
-    fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
+    fn register_const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
+        let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
+
+        self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() {
+            ty::PredicateKind::AliasEq(a.into(), b.into())
+        } else {
+            ty::PredicateKind::ConstEquate(a, b)
+        })]);
+    }
+
+    /// Register an obligation that both types must be equal to each other.
+    ///
+    /// If they aren't equal then the relation doesn't hold.
+    fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
+        let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
+
+        self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasEq(
+            a.into(),
+            b.into(),
+        ))]);
+    }
 }
 
 fn int_unification_error<'tcx>(
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 7db4d92a177..742c01efff6 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -1,4 +1,6 @@
-use super::combine::{CombineFields, ConstEquateRelation, RelationDir};
+use crate::traits::PredicateObligations;
+
+use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir};
 use super::Subtype;
 
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -198,8 +200,15 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> {
-    fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
-        self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
+impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> {
+    fn register_predicates(
+        &mut self,
+        obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
+    ) {
+        self.fields.register_predicates(obligations);
+    }
+
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+        self.fields.register_obligations(obligations);
     }
 }
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs
index b92b162a978..74abca7bbea 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/glb.rs
@@ -1,12 +1,11 @@
 //! Greatest lower bound. See [`lattice`].
 
-use super::combine::CombineFields;
+use super::combine::{CombineFields, ObligationEmittingRelation};
 use super::lattice::{self, LatticeDir};
 use super::InferCtxt;
 use super::Subtype;
 
-use crate::infer::combine::ConstEquateRelation;
-use crate::traits::{ObligationCause, PredicateObligation};
+use crate::traits::{ObligationCause, PredicateObligations};
 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
@@ -136,10 +135,6 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
         &self.fields.trace.cause
     }
 
-    fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
-        self.fields.obligations.extend(obligations)
-    }
-
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
         let mut sub = self.fields.sub(self.a_is_expected);
         sub.relate(v, a)?;
@@ -152,8 +147,15 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
     }
 }
 
-impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> {
-    fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
-        self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
+impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
+    fn register_predicates(
+        &mut self,
+        obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
+    ) {
+        self.fields.register_predicates(obligations);
+    }
+
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+        self.fields.register_obligations(obligations);
     }
 }
diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs
index 4dbb4b4d7b4..f377ac1d19e 100644
--- a/compiler/rustc_infer/src/infer/lattice.rs
+++ b/compiler/rustc_infer/src/infer/lattice.rs
@@ -17,11 +17,12 @@
 //!
 //! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
 
+use super::combine::ObligationEmittingRelation;
 use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use super::InferCtxt;
 
-use crate::traits::{ObligationCause, PredicateObligation};
-use rustc_middle::ty::relate::{RelateResult, TypeRelation};
+use crate::traits::ObligationCause;
+use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::TyVar;
 use rustc_middle::ty::{self, Ty};
 
@@ -30,13 +31,11 @@ use rustc_middle::ty::{self, Ty};
 ///
 /// GLB moves "down" the lattice (to smaller values); LUB moves
 /// "up" the lattice (to bigger values).
-pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
+pub trait LatticeDir<'f, 'tcx>: ObligationEmittingRelation<'tcx> {
     fn infcx(&self) -> &'f InferCtxt<'tcx>;
 
     fn cause(&self) -> &ObligationCause<'tcx>;
 
-    fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
-
     fn define_opaque_types(&self) -> bool;
 
     // Relates the type `v` to `a` and `b` such that `v` represents
@@ -113,7 +112,7 @@ where
         | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
             if this.define_opaque_types() && def_id.is_local() =>
         {
-            this.add_obligations(
+            this.register_obligations(
                 infcx
                     .handle_opaque_type(a, b, this.a_is_expected(), this.cause(), this.param_env())?
                     .obligations,
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs
index f6e0554fd1f..f997171b97f 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/lub.rs
@@ -1,12 +1,11 @@
 //! Least upper bound. See [`lattice`].
 
-use super::combine::CombineFields;
+use super::combine::{CombineFields, ObligationEmittingRelation};
 use super::lattice::{self, LatticeDir};
 use super::InferCtxt;
 use super::Subtype;
 
-use crate::infer::combine::ConstEquateRelation;
-use crate::traits::{ObligationCause, PredicateObligation};
+use crate::traits::{ObligationCause, PredicateObligations};
 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
@@ -127,12 +126,6 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> {
-    fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
-        self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
-    }
-}
-
 impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
     fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
         self.fields.infcx
@@ -142,10 +135,6 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
         &self.fields.trace.cause
     }
 
-    fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
-        self.fields.obligations.extend(obligations)
-    }
-
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
         let mut sub = self.fields.sub(self.a_is_expected);
         sub.relate(a, v)?;
@@ -157,3 +146,16 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
         self.fields.define_opaque_types
     }
 }
+
+impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
+    fn register_predicates(
+        &mut self,
+        obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
+    ) {
+        self.fields.register_predicates(obligations);
+    }
+
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+        self.fields.register_obligations(obligations)
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 35918b8bae1..e77924900a0 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -4,6 +4,7 @@ pub use self::LateBoundRegionConversionTime::*;
 pub use self::RegionVariableOrigin::*;
 pub use self::SubregionOrigin::*;
 pub use self::ValuePairs::*;
+pub use combine::ObligationEmittingRelation;
 
 use self::opaque_types::OpaqueTypeStorage;
 pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index a2cfe8d8881..1dd5062acaf 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -21,11 +21,10 @@
 //!   thing we relate in chalk are basically domain goals and their
 //!   constituents)
 
-use crate::infer::combine::ConstEquateRelation;
 use crate::infer::InferCtxt;
 use crate::infer::{ConstVarValue, ConstVariableValue};
 use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::traits::{Obligation, PredicateObligation};
+use crate::traits::{Obligation, PredicateObligations};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::TypeError;
@@ -36,11 +35,7 @@ use rustc_span::Span;
 use std::fmt::Debug;
 use std::ops::ControlFlow;
 
-#[derive(PartialEq)]
-pub enum NormalizationStrategy {
-    Lazy,
-    Eager,
-}
+use super::combine::ObligationEmittingRelation;
 
 pub struct TypeRelating<'me, 'tcx, D>
 where
@@ -92,7 +87,7 @@ pub trait TypeRelatingDelegate<'tcx> {
         info: ty::VarianceDiagInfo<'tcx>,
     );
 
-    fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
 
     /// Creates a new universe index. Used when instantiating placeholders.
     fn create_next_universe(&mut self) -> ty::UniverseIndex;
@@ -125,9 +120,6 @@ pub trait TypeRelatingDelegate<'tcx> {
     /// relation stating that `'?0: 'a`).
     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
 
-    /// Define the normalization strategy to use, eager or lazy.
-    fn normalization() -> NormalizationStrategy;
-
     /// Enables some optimizations if we do not expect inference variables
     /// in the RHS of the relation.
     fn forbid_inference_vars() -> bool;
@@ -265,38 +257,6 @@ where
         self.delegate.push_outlives(sup, sub, info);
     }
 
-    /// Relate a projection type and some value type lazily. This will always
-    /// succeed, but we push an additional `ProjectionEq` goal depending
-    /// on the value type:
-    /// - if the value type is any type `T` which is not a projection, we push
-    ///   `ProjectionEq(projection = T)`.
-    /// - if the value type is another projection `other_projection`, we create
-    ///   a new inference variable `?U` and push the two goals
-    ///   `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`.
-    fn relate_projection_ty(
-        &mut self,
-        projection_ty: ty::AliasTy<'tcx>,
-        value_ty: Ty<'tcx>,
-    ) -> Ty<'tcx> {
-        use rustc_span::DUMMY_SP;
-
-        match *value_ty.kind() {
-            ty::Alias(ty::Projection, other_projection_ty) => {
-                let var = self.infcx.next_ty_var(TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
-                    span: DUMMY_SP,
-                });
-                // FIXME(lazy-normalization): This will always ICE, because the recursive
-                // call will end up in the _ arm below.
-                self.relate_projection_ty(projection_ty, var);
-                self.relate_projection_ty(other_projection_ty, var);
-                var
-            }
-
-            _ => bug!("should never be invoked with eager normalization"),
-        }
-    }
-
     /// Relate a type inference variable with a value type. This works
     /// by creating a "generalization" G of the value where all the
     /// lifetimes are replaced with fresh inference values. This
@@ -335,12 +295,6 @@ where
                 return Ok(value_ty);
             }
 
-            ty::Alias(ty::Projection, projection_ty)
-                if D::normalization() == NormalizationStrategy::Lazy =>
-            {
-                return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
-            }
-
             _ => (),
         }
 
@@ -627,18 +581,6 @@ where
                 self.relate_opaques(a, b)
             }
 
-            (&ty::Alias(ty::Projection, projection_ty), _)
-                if D::normalization() == NormalizationStrategy::Lazy =>
-            {
-                Ok(self.relate_projection_ty(projection_ty, b))
-            }
-
-            (_, &ty::Alias(ty::Projection, projection_ty))
-                if D::normalization() == NormalizationStrategy::Lazy =>
-            {
-                Ok(self.relate_projection_ty(projection_ty, a))
-            }
-
             _ => {
                 debug!(?a, ?b, ?self.ambient_variance);
 
@@ -813,17 +755,26 @@ where
     }
 }
 
-impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
+impl<'tcx, D> ObligationEmittingRelation<'tcx> for TypeRelating<'_, 'tcx, D>
 where
     D: TypeRelatingDelegate<'tcx>,
 {
-    fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
-        self.delegate.register_obligations(vec![Obligation::new(
-            self.tcx(),
-            ObligationCause::dummy(),
-            self.param_env(),
-            ty::Binder::dummy(ty::PredicateKind::ConstEquate(a, b)),
-        )]);
+    fn register_predicates(
+        &mut self,
+        obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
+    ) {
+        self.delegate.register_obligations(
+            obligations
+                .into_iter()
+                .map(|to_pred| {
+                    Obligation::new(self.tcx(), ObligationCause::dummy(), self.param_env(), to_pred)
+                })
+                .collect(),
+        );
+    }
+
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+        self.delegate.register_obligations(obligations);
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 532fbd0ffe4..bf1b3441547 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -1,8 +1,7 @@
 use super::combine::{CombineFields, RelationDir};
-use super::SubregionOrigin;
+use super::{ObligationEmittingRelation, SubregionOrigin};
 
-use crate::infer::combine::ConstEquateRelation;
-use crate::traits::Obligation;
+use crate::traits::{Obligation, PredicateObligations};
 use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::TyVar;
@@ -228,8 +227,15 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> ConstEquateRelation<'tcx> for Sub<'_, '_, 'tcx> {
-    fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
-        self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
+impl<'tcx> ObligationEmittingRelation<'tcx> for Sub<'_, '_, 'tcx> {
+    fn register_predicates(
+        &mut self,
+        obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
+    ) {
+        self.fields.register_predicates(obligations);
+    }
+
+    fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+        self.fields.register_obligations(obligations);
     }
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index d07d9190e01..bf36b3e5ada 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2230,6 +2230,10 @@ impl<'tcx> TyCtxt<'tcx> {
             })
         )
     }
+
+    pub fn trait_solver_next(self) -> bool {
+        self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
+    }
 }
 
 impl<'tcx> TyCtxtAt<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
index ba9ee57d409..9474c70cb53 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
@@ -1,5 +1,7 @@
 use crate::infer::InferCtxt;
 
+use rustc_infer::infer::ObligationEmittingRelation;
+use rustc_infer::traits::PredicateObligations;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -88,3 +90,16 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
         Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
     }
 }
+
+impl<'tcx> ObligationEmittingRelation<'tcx> for CollectAllMismatches<'_, 'tcx> {
+    fn register_obligations(&mut self, _obligations: PredicateObligations<'tcx>) {
+        // FIXME(deferred_projection_equality)
+    }
+
+    fn register_predicates(
+        &mut self,
+        _obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
+    ) {
+        // FIXME(deferred_projection_equality)
+    }
+}