about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-10-06 22:42:28 -0400
committerMichael Goulet <michael@errs.io>2024-10-07 05:29:13 -0400
commitda71dfbc516ec6fb7aa18e23c393ba6d1d2fb523 (patch)
tree4ee2df4e87502aa2172346644d2b44f31af3f7e2 /compiler
parent690332a251329e603d1a38bc70a4f6a45ac30bc2 (diff)
downloadrust-da71dfbc516ec6fb7aa18e23c393ba6d1d2fb523.tar.gz
rust-da71dfbc516ec6fb7aa18e23c393ba6d1d2fb523.zip
Inline CombineFields
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_infer/src/infer/at.rs89
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs96
-rw-r--r--compiler/rustc_infer/src/infer/relate/lattice.rs96
-rw-r--r--compiler/rustc_infer/src/infer/relate/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/type_relating.rs106
6 files changed, 174 insertions, 218 deletions
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 183973af4f9..ecef90c5ca2 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -25,12 +25,13 @@
 //! sometimes useful when the types of `c` and `d` are not traceable
 //! things. (That system should probably be refactored.)
 
+use relate::lattice::{LatticeOp, LatticeOpKind};
 use rustc_middle::bug;
 use rustc_middle::ty::{Const, ImplSubject};
 
 use super::*;
+use crate::infer::relate::type_relating::TypeRelating;
 use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation};
-use crate::traits::Obligation;
 
 /// Whether we should define opaque types or just treat them opaquely.
 ///
@@ -108,14 +109,16 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        let mut fields = CombineFields::new(
+        let mut op = TypeRelating::new(
             self.infcx,
             ToTrace::to_trace(self.cause, expected, actual),
             self.param_env,
             define_opaque_types,
+            StructurallyRelateAliases::No,
+            ty::Contravariant,
         );
-        fields.sup().relate(expected, actual)?;
-        Ok(InferOk { value: (), obligations: fields.into_obligations() })
+        op.relate(expected, actual)?;
+        Ok(InferOk { value: (), obligations: op.into_obligations() })
     }
 
     /// Makes `expected <: actual`.
@@ -128,14 +131,16 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        let mut fields = CombineFields::new(
+        let mut op = TypeRelating::new(
             self.infcx,
             ToTrace::to_trace(self.cause, expected, actual),
             self.param_env,
             define_opaque_types,
+            StructurallyRelateAliases::No,
+            ty::Covariant,
         );
-        fields.sub().relate(expected, actual)?;
-        Ok(InferOk { value: (), obligations: fields.into_obligations() })
+        op.relate(expected, actual)?;
+        Ok(InferOk { value: (), obligations: op.into_obligations() })
     }
 
     /// Makes `expected == actual`.
@@ -167,23 +172,16 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: Relate<TyCtxt<'tcx>>,
     {
-        let mut fields = CombineFields::new(self.infcx, trace, self.param_env, define_opaque_types);
-        fields.equate(StructurallyRelateAliases::No).relate(expected, actual)?;
-        Ok(InferOk {
-            value: (),
-            obligations: fields
-                .goals
-                .into_iter()
-                .map(|goal| {
-                    Obligation::new(
-                        self.infcx.tcx,
-                        fields.trace.cause.clone(),
-                        goal.param_env,
-                        goal.predicate,
-                    )
-                })
-                .collect(),
-        })
+        let mut op = TypeRelating::new(
+            self.infcx,
+            trace,
+            self.param_env,
+            define_opaque_types,
+            StructurallyRelateAliases::No,
+            ty::Invariant,
+        );
+        op.relate(expected, actual)?;
+        Ok(InferOk { value: (), obligations: op.into_obligations() })
     }
 
     /// Equates `expected` and `found` while structurally relating aliases.
@@ -198,14 +196,16 @@ impl<'a, 'tcx> At<'a, 'tcx> {
         T: ToTrace<'tcx>,
     {
         assert!(self.infcx.next_trait_solver());
-        let mut fields = CombineFields::new(
+        let mut op = TypeRelating::new(
             self.infcx,
             ToTrace::to_trace(self.cause, expected, actual),
             self.param_env,
             DefineOpaqueTypes::Yes,
+            StructurallyRelateAliases::Yes,
+            ty::Invariant,
         );
-        fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?;
-        Ok(InferOk { value: (), obligations: fields.into_obligations() })
+        op.relate(expected, actual)?;
+        Ok(InferOk { value: (), obligations: op.into_obligations() })
     }
 
     pub fn relate<T>(
@@ -242,19 +242,16 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: Relate<TyCtxt<'tcx>>,
     {
-        let mut fields = CombineFields::new(
+        let mut op = TypeRelating::new(
             self.infcx,
             TypeTrace::dummy(self.cause),
             self.param_env,
             DefineOpaqueTypes::Yes,
-        );
-        fields.sub().relate_with_variance(
+            StructurallyRelateAliases::No,
             variance,
-            ty::VarianceDiagInfo::default(),
-            expected,
-            actual,
-        )?;
-        Ok(fields.goals)
+        );
+        op.relate(expected, actual)?;
+        Ok(op.into_obligations().into_iter().map(|o| o.into()).collect())
     }
 
     /// Used in the new solver since we don't care about tracking an `ObligationCause`.
@@ -266,14 +263,16 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: Relate<TyCtxt<'tcx>>,
     {
-        let mut fields = CombineFields::new(
+        let mut op = TypeRelating::new(
             self.infcx,
             TypeTrace::dummy(self.cause),
             self.param_env,
             DefineOpaqueTypes::Yes,
+            StructurallyRelateAliases::Yes,
+            ty::Invariant,
         );
-        fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?;
-        Ok(fields.goals)
+        op.relate(expected, actual)?;
+        Ok(op.into_obligations().into_iter().map(|o| o.into()).collect())
     }
 
     /// Computes the least-upper-bound, or mutual supertype, of two
@@ -290,14 +289,15 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        let mut fields = CombineFields::new(
+        let mut op = LatticeOp::new(
             self.infcx,
             ToTrace::to_trace(self.cause, expected, actual),
             self.param_env,
             define_opaque_types,
+            LatticeOpKind::Lub,
         );
-        let value = fields.lub().relate(expected, actual)?;
-        Ok(InferOk { value, obligations: fields.into_obligations() })
+        let value = op.relate(expected, actual)?;
+        Ok(InferOk { value, obligations: op.into_obligations() })
     }
 
     /// Computes the greatest-lower-bound, or mutual subtype, of two
@@ -312,14 +312,15 @@ impl<'a, 'tcx> At<'a, 'tcx> {
     where
         T: ToTrace<'tcx>,
     {
-        let mut fields = CombineFields::new(
+        let mut op = LatticeOp::new(
             self.infcx,
             ToTrace::to_trace(self.cause, expected, actual),
             self.param_env,
             define_opaque_types,
+            LatticeOpKind::Glb,
         );
-        let value = fields.glb().relate(expected, actual)?;
-        Ok(InferOk { value, obligations: fields.into_obligations() })
+        let value = op.relate(expected, actual)?;
+        Ok(InferOk { value, obligations: op.into_obligations() })
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 89dfa019253..c179c1dcfe1 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -14,7 +14,6 @@ use region_constraints::{
     GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound,
 };
 pub use relate::StructurallyRelateAliases;
-use relate::combine::CombineFields;
 pub use relate::combine::PredicateEmittingRelation;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 450437f2176..c4f5a85a8be 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -1,4 +1,4 @@
-//! There are four type combiners: [TypeRelating], `Lub`, and `Glb`,
+//! There are four type combiners: `TypeRelating`, `Lub`, and `Glb`,
 //! and `NllTypeRelating` in rustc_borrowck, which is only used for NLL.
 //!
 //! Each implements the trait [TypeRelation] and contains methods for
@@ -20,56 +20,13 @@
 
 use rustc_middle::bug;
 use rustc_middle::infer::unify_key::EffectVarValue;
-use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, InferConst, IntType, Ty, TyCtxt, TypeVisitableExt, UintType, Upcast};
+use rustc_middle::ty::{self, InferConst, IntType, Ty, TypeVisitableExt, UintType};
 pub use rustc_next_trait_solver::relate::combine::*;
 use tracing::debug;
 
-use super::lattice::{LatticeOp, LatticeOpKind};
-use super::type_relating::TypeRelating;
 use super::{RelateResult, StructurallyRelateAliases};
-use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace, relate};
-use crate::traits::{Obligation, PredicateObligation};
-
-#[derive(Clone)]
-pub(crate) struct CombineFields<'infcx, 'tcx> {
-    pub infcx: &'infcx InferCtxt<'tcx>,
-    // Immutable fields
-    pub trace: TypeTrace<'tcx>,
-    pub param_env: ty::ParamEnv<'tcx>,
-    pub define_opaque_types: DefineOpaqueTypes,
-    // Mutable fields
-    //
-    // Adding any additional field likely requires
-    // changes to the cache of `TypeRelating`.
-    pub goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
-}
-
-impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
-    pub(crate) fn new(
-        infcx: &'infcx InferCtxt<'tcx>,
-        trace: TypeTrace<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        define_opaque_types: DefineOpaqueTypes,
-    ) -> Self {
-        Self { infcx, trace, param_env, define_opaque_types, goals: vec![] }
-    }
-
-    pub(crate) fn into_obligations(self) -> Vec<PredicateObligation<'tcx>> {
-        self.goals
-            .into_iter()
-            .map(|goal| {
-                Obligation::new(
-                    self.infcx.tcx,
-                    self.trace.cause.clone(),
-                    goal.param_env,
-                    goal.predicate,
-                )
-            })
-            .collect()
-    }
-}
+use crate::infer::{InferCtxt, relate};
 
 impl<'tcx> InferCtxt<'tcx> {
     pub fn super_combine_tys<R>(
@@ -281,50 +238,3 @@ impl<'tcx> InferCtxt<'tcx> {
         val
     }
 }
-
-impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
-    pub(crate) fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    pub(crate) fn equate<'a>(
-        &'a mut self,
-        structurally_relate_aliases: StructurallyRelateAliases,
-    ) -> TypeRelating<'a, 'infcx, 'tcx> {
-        TypeRelating::new(self, structurally_relate_aliases, ty::Invariant)
-    }
-
-    pub(crate) fn sub<'a>(&'a mut self) -> TypeRelating<'a, 'infcx, 'tcx> {
-        TypeRelating::new(self, StructurallyRelateAliases::No, ty::Covariant)
-    }
-
-    pub(crate) fn sup<'a>(&'a mut self) -> TypeRelating<'a, 'infcx, 'tcx> {
-        TypeRelating::new(self, StructurallyRelateAliases::No, ty::Contravariant)
-    }
-
-    pub(crate) fn lub<'a>(&'a mut self) -> LatticeOp<'a, 'infcx, 'tcx> {
-        LatticeOp::new(self, LatticeOpKind::Lub)
-    }
-
-    pub(crate) fn glb<'a>(&'a mut self) -> LatticeOp<'a, 'infcx, 'tcx> {
-        LatticeOp::new(self, LatticeOpKind::Glb)
-    }
-
-    pub(crate) fn register_obligations(
-        &mut self,
-        obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
-    ) {
-        self.goals.extend(obligations);
-    }
-
-    pub(crate) fn register_predicates(
-        &mut self,
-        obligations: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
-    ) {
-        self.goals.extend(
-            obligations
-                .into_iter()
-                .map(|to_pred| Goal::new(self.infcx.tcx, self.param_env, to_pred)),
-        )
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index 9564baa6ab2..877cb713c1e 100644
--- a/compiler/rustc_infer/src/infer/relate/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -24,8 +24,9 @@ use rustc_span::Span;
 use tracing::{debug, instrument};
 
 use super::StructurallyRelateAliases;
-use super::combine::{CombineFields, PredicateEmittingRelation};
-use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
+use super::combine::PredicateEmittingRelation;
+use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace};
+use crate::traits::{Obligation, PredicateObligation};
 
 #[derive(Clone, Copy)]
 pub(crate) enum LatticeOpKind {
@@ -43,23 +44,36 @@ impl LatticeOpKind {
 }
 
 /// A greatest lower bound" (common subtype) or least upper bound (common supertype).
-pub(crate) struct LatticeOp<'combine, 'infcx, 'tcx> {
-    fields: &'combine mut CombineFields<'infcx, 'tcx>,
+pub(crate) struct LatticeOp<'infcx, 'tcx> {
+    infcx: &'infcx InferCtxt<'tcx>,
+    // Immutable fields
+    trace: TypeTrace<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    define_opaque_types: DefineOpaqueTypes,
+    // Mutable fields
     kind: LatticeOpKind,
+    obligations: Vec<PredicateObligation<'tcx>>,
 }
 
-impl<'combine, 'infcx, 'tcx> LatticeOp<'combine, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> {
     pub(crate) fn new(
-        fields: &'combine mut CombineFields<'infcx, 'tcx>,
+        infcx: &'infcx InferCtxt<'tcx>,
+        trace: TypeTrace<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        define_opaque_types: DefineOpaqueTypes,
         kind: LatticeOpKind,
-    ) -> LatticeOp<'combine, 'infcx, 'tcx> {
-        LatticeOp { fields, kind }
+    ) -> LatticeOp<'infcx, 'tcx> {
+        LatticeOp { infcx, trace, param_env, define_opaque_types, kind, obligations: vec![] }
+    }
+
+    pub(crate) fn into_obligations(self) -> Vec<PredicateObligation<'tcx>> {
+        self.obligations
     }
 }
 
-impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
     fn cx(&self) -> TyCtxt<'tcx> {
-        self.fields.tcx()
+        self.infcx.tcx
     }
 
     fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
@@ -70,7 +84,15 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
         b: T,
     ) -> RelateResult<'tcx, T> {
         match variance {
-            ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b),
+            ty::Invariant => {
+                self.obligations.extend(
+                    self.infcx
+                        .at(&self.trace.cause, self.param_env)
+                        .eq_trace(self.define_opaque_types, self.trace.clone(), a, b)?
+                        .into_obligations(),
+                );
+                Ok(a)
+            }
             ty::Covariant => self.relate(a, b),
             // FIXME(#41044) -- not correct, need test
             ty::Bivariant => Ok(a),
@@ -90,7 +112,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
             return Ok(a);
         }
 
-        let infcx = self.fields.infcx;
+        let infcx = self.infcx;
 
         let a = infcx.shallow_resolve(a);
         let b = infcx.shallow_resolve(b);
@@ -115,12 +137,12 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
             // iterate on the subtype obligations that are returned, but I
             // think this suffices. -nmatsakis
             (&ty::Infer(TyVar(..)), _) => {
-                let v = infcx.next_ty_var(self.fields.trace.cause.span);
+                let v = infcx.next_ty_var(self.trace.cause.span);
                 self.relate_bound(v, b, a)?;
                 Ok(v)
             }
             (_, &ty::Infer(TyVar(..))) => {
-                let v = infcx.next_ty_var(self.fields.trace.cause.span);
+                let v = infcx.next_ty_var(self.trace.cause.span);
                 self.relate_bound(v, a, b)?;
                 Ok(v)
             }
@@ -132,7 +154,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
 
             (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
             | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
-                if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
+                if self.define_opaque_types == DefineOpaqueTypes::Yes
                     && def_id.is_local()
                     && !infcx.next_trait_solver() =>
             {
@@ -155,8 +177,8 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
-        let mut inner = self.fields.infcx.inner.borrow_mut();
+        let origin = SubregionOrigin::Subtype(Box::new(self.trace.clone()));
+        let mut inner = self.infcx.inner.borrow_mut();
         let mut constraints = inner.unwrap_region_constraints();
         Ok(match self.kind {
             // GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8
@@ -173,7 +195,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
         a: ty::Const<'tcx>,
         b: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        self.fields.infcx.super_combine_consts(self, a, b)
+        self.infcx.super_combine_consts(self, a, b)
     }
 
     fn binders<T>(
@@ -202,7 +224,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
     }
 }
 
-impl<'combine, 'infcx, 'tcx> LatticeOp<'combine, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> {
     // Relates the type `v` to `a` and `b` such that `v` represents
     // the LUB/GLB of `a` and `b` as appropriate.
     //
@@ -210,24 +232,24 @@ impl<'combine, 'infcx, 'tcx> LatticeOp<'combine, 'infcx, 'tcx> {
     // relates `v` to `a` first, which may help us to avoid unnecessary
     // type variable obligations. See caller for details.
     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
-        let mut sub = self.fields.sub();
+        let at = self.infcx.at(&self.trace.cause, self.param_env);
         match self.kind {
             LatticeOpKind::Glb => {
-                sub.relate(v, a)?;
-                sub.relate(v, b)?;
+                self.obligations.extend(at.sub(self.define_opaque_types, v, a)?.into_obligations());
+                self.obligations.extend(at.sub(self.define_opaque_types, v, b)?.into_obligations());
             }
             LatticeOpKind::Lub => {
-                sub.relate(a, v)?;
-                sub.relate(b, v)?;
+                self.obligations.extend(at.sub(self.define_opaque_types, a, v)?.into_obligations());
+                self.obligations.extend(at.sub(self.define_opaque_types, b, v)?.into_obligations());
             }
         }
         Ok(())
     }
 }
 
-impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
+impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
     fn span(&self) -> Span {
-        self.fields.trace.span()
+        self.trace.span()
     }
 
     fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
@@ -235,21 +257,27 @@ impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx
     }
 
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.fields.param_env
+        self.param_env
     }
 
     fn register_predicates(
         &mut self,
-        obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
+        preds: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
     ) {
-        self.fields.register_predicates(obligations);
+        self.obligations.extend(preds.into_iter().map(|pred| {
+            Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred)
+        }))
     }
 
-    fn register_goals(
-        &mut self,
-        obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
-    ) {
-        self.fields.register_obligations(obligations);
+    fn register_goals(&mut self, goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>) {
+        self.obligations.extend(goals.into_iter().map(|goal| {
+            Obligation::new(
+                self.infcx.tcx,
+                self.trace.cause.clone(),
+                goal.param_env,
+                goal.predicate,
+            )
+        }))
     }
 
     fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs
index 85158faa65d..baab5bb274a 100644
--- a/compiler/rustc_infer/src/infer/relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/relate/mod.rs
@@ -11,5 +11,5 @@ pub use self::combine::PredicateEmittingRelation;
 pub(super) mod combine;
 mod generalize;
 mod higher_ranked;
-mod lattice;
-mod type_relating;
+pub(super) mod lattice;
+pub(super) mod type_relating;
diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs
index 7537ceec307..4b4b13e919c 100644
--- a/compiler/rustc_infer/src/infer/relate/type_relating.rs
+++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs
@@ -7,29 +7,31 @@ use rustc_span::Span;
 use rustc_type_ir::data_structures::DelayedSet;
 use tracing::{debug, instrument};
 
-use super::combine::CombineFields;
 use crate::infer::BoundRegionConversionTime::HigherRankedType;
 use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases};
-use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
+use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace};
+use crate::traits::{Obligation, PredicateObligation};
 
 /// Enforce that `a` is equal to or a subtype of `b`.
-pub(crate) struct TypeRelating<'combine, 'a, 'tcx> {
-    // Immutable except for the `InferCtxt` and the
-    // resulting nested `goals`.
-    fields: &'combine mut CombineFields<'a, 'tcx>,
+pub(crate) struct TypeRelating<'infcx, 'tcx> {
+    infcx: &'infcx InferCtxt<'tcx>,
 
-    // Immutable field.
+    // Immutable fields
+    trace: TypeTrace<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    define_opaque_types: DefineOpaqueTypes,
     structurally_relate_aliases: StructurallyRelateAliases,
-    // Mutable field.
-    ambient_variance: ty::Variance,
 
+    // Mutable fields.
+    ambient_variance: ty::Variance,
+    obligations: Vec<PredicateObligation<'tcx>>,
     /// The cache only tracks the `ambient_variance` as it's the
     /// only field which is mutable and which meaningfully changes
     /// the result when relating types.
     ///
     /// The cache does not track whether the state of the
     /// `InferCtxt` has been changed or whether we've added any
-    /// obligations to `self.fields.goals`. Whether a goal is added
+    /// obligations to `self.goals`. Whether a goal is added
     /// once or multiple times is not really meaningful.
     ///
     /// Changes in the inference state may delay some type inference to
@@ -48,24 +50,35 @@ pub(crate) struct TypeRelating<'combine, 'a, 'tcx> {
     cache: DelayedSet<(ty::Variance, Ty<'tcx>, Ty<'tcx>)>,
 }
 
-impl<'combine, 'infcx, 'tcx> TypeRelating<'combine, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> {
     pub(crate) fn new(
-        f: &'combine mut CombineFields<'infcx, 'tcx>,
+        infcx: &'infcx InferCtxt<'tcx>,
+        trace: TypeTrace<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        define_opaque_types: DefineOpaqueTypes,
         structurally_relate_aliases: StructurallyRelateAliases,
         ambient_variance: ty::Variance,
-    ) -> TypeRelating<'combine, 'infcx, 'tcx> {
+    ) -> TypeRelating<'infcx, 'tcx> {
         TypeRelating {
-            fields: f,
+            infcx,
+            trace,
+            param_env,
+            define_opaque_types,
             structurally_relate_aliases,
             ambient_variance,
+            obligations: vec![],
             cache: Default::default(),
         }
     }
+
+    pub(crate) fn into_obligations(self) -> Vec<PredicateObligation<'tcx>> {
+        self.obligations
+    }
 }
 
-impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
     fn cx(&self) -> TyCtxt<'tcx> {
-        self.fields.infcx.tcx
+        self.infcx.tcx
     }
 
     fn relate_item_args(
@@ -109,7 +122,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
             return Ok(a);
         }
 
-        let infcx = self.fields.infcx;
+        let infcx = self.infcx;
         let a = infcx.shallow_resolve(a);
         let b = infcx.shallow_resolve(b);
 
@@ -123,9 +136,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
                     ty::Covariant => {
                         // can't make progress on `A <: B` if both A and B are
                         // type variables, so record an obligation.
-                        self.fields.goals.push(Goal::new(
+                        self.obligations.push(Obligation::new(
                             self.cx(),
-                            self.fields.param_env,
+                            self.trace.cause.clone(),
+                            self.param_env,
                             ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
                                 a_is_expected: true,
                                 a,
@@ -136,9 +150,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
                     ty::Contravariant => {
                         // can't make progress on `B <: A` if both A and B are
                         // type variables, so record an obligation.
-                        self.fields.goals.push(Goal::new(
+                        self.obligations.push(Obligation::new(
                             self.cx(),
-                            self.fields.param_env,
+                            self.trace.cause.clone(),
+                            self.param_env,
                             ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
                                 a_is_expected: false,
                                 a: b,
@@ -182,14 +197,14 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
 
             (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
             | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
-                if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
+                if self.define_opaque_types == DefineOpaqueTypes::Yes
                     && def_id.is_local()
                     && !infcx.next_trait_solver() =>
             {
-                self.fields.goals.extend(infcx.handle_opaque_type(
+                self.register_goals(infcx.handle_opaque_type(
                     a,
                     b,
-                    self.fields.trace.cause.span,
+                    self.trace.cause.span,
                     self.param_env(),
                 )?);
             }
@@ -210,13 +225,12 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
+        let origin = SubregionOrigin::Subtype(Box::new(self.trace.clone()));
 
         match self.ambient_variance {
             // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
             ty::Covariant => {
-                self.fields
-                    .infcx
+                self.infcx
                     .inner
                     .borrow_mut()
                     .unwrap_region_constraints()
@@ -224,16 +238,14 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
             }
             // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
             ty::Contravariant => {
-                self.fields
-                    .infcx
+                self.infcx
                     .inner
                     .borrow_mut()
                     .unwrap_region_constraints()
                     .make_subregion(origin, a, b);
             }
             ty::Invariant => {
-                self.fields
-                    .infcx
+                self.infcx
                     .inner
                     .borrow_mut()
                     .unwrap_region_constraints()
@@ -253,7 +265,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
         a: ty::Const<'tcx>,
         b: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        self.fields.infcx.super_combine_consts(self, a, b)
+        self.infcx.super_combine_consts(self, a, b)
     }
 
     fn binders<T>(
@@ -271,8 +283,8 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
         {
             self.relate(a, b)?;
         } else {
-            let span = self.fields.trace.cause.span;
-            let infcx = self.fields.infcx;
+            let span = self.trace.cause.span;
+            let infcx = self.infcx;
 
             match self.ambient_variance {
                 // Checks whether `for<..> sub <: for<..> sup` holds.
@@ -335,13 +347,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
+impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
     fn span(&self) -> Span {
-        self.fields.trace.span()
+        self.trace.span()
     }
 
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.fields.param_env
+        self.param_env
     }
 
     fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
@@ -350,16 +362,22 @@ impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, '_, '
 
     fn register_predicates(
         &mut self,
-        obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
+        preds: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
     ) {
-        self.fields.register_predicates(obligations);
+        self.obligations.extend(preds.into_iter().map(|pred| {
+            Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred)
+        }))
     }
 
-    fn register_goals(
-        &mut self,
-        obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
-    ) {
-        self.fields.register_obligations(obligations);
+    fn register_goals(&mut self, goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>) {
+        self.obligations.extend(goals.into_iter().map(|goal| {
+            Obligation::new(
+                self.infcx.tcx,
+                self.trace.cause.clone(),
+                goal.param_env,
+                goal.predicate,
+            )
+        }))
     }
 
     fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {