about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-06-17 11:58:38 -0400
committerMichael Goulet <michael@errs.io>2024-06-18 10:40:30 -0400
commitbaf94bddf0503bb97376534d10883dbf678bfc6a (patch)
tree9e597c5045942f9229841fd5932258c217dfbd6f
parente7d2d95e5a6353e6cf0321c812c556130954302c (diff)
downloadrust-baf94bddf0503bb97376534d10883dbf678bfc6a.tar.gz
rust-baf94bddf0503bb97376534d10883dbf678bfc6a.zip
SolverDelegate
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs151
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs11
-rw-r--r--compiler/rustc_next_trait_solver/src/infcx.rs (renamed from compiler/rustc_type_ir/src/infcx.rs)10
-rw-r--r--compiler/rustc_next_trait_solver/src/lib.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/resolve.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/alias_relate.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs58
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs15
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs8
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs38
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs13
-rw-r--r--compiler/rustc_trait_selection/src/solve/infcx.rs178
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/build.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs58
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph.rs8
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs58
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
24 files changed, 363 insertions, 310 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 8412912b9f3..0125098e41f 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -10,7 +10,7 @@ pub use BoundRegionConversionTime::*;
 pub use RegionVariableOrigin::*;
 pub use SubregionOrigin::*;
 
-use crate::infer::relate::{Relate, RelateResult};
+use crate::infer::relate::RelateResult;
 use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
 use error_reporting::TypeErrCtxt;
 use free_regions::RegionRelations;
@@ -44,7 +44,7 @@ use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
 use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Symbol;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use snapshot::undo_log::InferCtxtUndoLogs;
 use std::cell::{Cell, RefCell};
 use std::fmt;
@@ -334,149 +334,6 @@ pub struct InferCtxt<'tcx> {
     pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
 }
 
-impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
-    type Interner = TyCtxt<'tcx>;
-
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn universe_of_ty(&self, vid: TyVid) -> Option<ty::UniverseIndex> {
-        // FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
-        // ty infers will give you the universe of the var it resolved to not the universe
-        // it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
-        // try to print out `?0.1` it will just print `?0`.
-        match self.probe_ty_var(vid) {
-            Err(universe) => Some(universe),
-            Ok(_) => None,
-        }
-    }
-
-    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
-        match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
-            Err(universe) => Some(universe),
-            Ok(_) => None,
-        }
-    }
-
-    fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
-        // Same issue as with `universe_of_ty`
-        match self.probe_const_var(ct) {
-            Err(universe) => Some(universe),
-            Ok(_) => None,
-        }
-    }
-
-    fn root_ty_var(&self, var: TyVid) -> TyVid {
-        self.root_var(var)
-    }
-
-    fn root_const_var(&self, var: ConstVid) -> ConstVid {
-        self.root_const_var(var)
-    }
-
-    fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> Ty<'tcx> {
-        match self.probe_ty_var(vid) {
-            Ok(ty) => ty,
-            Err(_) => Ty::new_var(self.tcx, self.root_var(vid)),
-        }
-    }
-
-    fn opportunistic_resolve_int_var(&self, vid: IntVid) -> Ty<'tcx> {
-        self.opportunistic_resolve_int_var(vid)
-    }
-
-    fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> Ty<'tcx> {
-        self.opportunistic_resolve_float_var(vid)
-    }
-
-    fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> ty::Const<'tcx> {
-        match self.probe_const_var(vid) {
-            Ok(ct) => ct,
-            Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid)),
-        }
-    }
-
-    fn opportunistic_resolve_effect_var(&self, vid: EffectVid) -> ty::Const<'tcx> {
-        match self.probe_effect_var(vid) {
-            Some(ct) => ct,
-            None => {
-                ty::Const::new_infer(self.tcx, InferConst::EffectVar(self.root_effect_var(vid)))
-            }
-        }
-    }
-
-    fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
-        self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
-    }
-
-    fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
-        self.defining_opaque_types
-    }
-
-    fn next_ty_infer(&self) -> Ty<'tcx> {
-        self.next_ty_var(DUMMY_SP)
-    }
-
-    fn next_const_infer(&self) -> ty::Const<'tcx> {
-        self.next_const_var(DUMMY_SP)
-    }
-
-    fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
-        self.fresh_args_for_item(DUMMY_SP, def_id)
-    }
-
-    fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
-        &self,
-        value: ty::Binder<'tcx, T>,
-    ) -> T {
-        self.instantiate_binder_with_fresh_vars(
-            DUMMY_SP,
-            BoundRegionConversionTime::HigherRankedType,
-            value,
-        )
-    }
-
-    fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
-        &self,
-        value: ty::Binder<'tcx, T>,
-        f: impl FnOnce(T) -> U,
-    ) -> U {
-        self.enter_forall(value, f)
-    }
-
-    fn relate<T: Relate<TyCtxt<'tcx>>>(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        lhs: T,
-        variance: ty::Variance,
-        rhs: T,
-    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
-        self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs)
-    }
-
-    fn eq_structurally_relating_aliases<T: Relate<TyCtxt<'tcx>>>(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        lhs: T,
-        rhs: T,
-    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
-        self.at(&ObligationCause::dummy(), param_env)
-            .eq_structurally_relating_aliases_no_trace(lhs, rhs)
-    }
-
-    fn resolve_vars_if_possible<T>(&self, value: T) -> T
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>,
-    {
-        self.resolve_vars_if_possible(value)
-    }
-
-    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
-        self.probe(|_| probe())
-    }
-}
-
 /// See the `error_reporting` module for more details.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
 pub enum ValuePairs<'tcx> {
@@ -830,6 +687,10 @@ impl<'tcx> InferCtxt<'tcx> {
         self.tcx.dcx()
     }
 
+    pub fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
+        self.defining_opaque_types
+    }
+
     pub fn next_trait_solver(&self) -> bool {
         self.next_trait_solver
     }
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index f22e24ef654..a81fd03d034 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -4,10 +4,11 @@ use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::visit::TypeVisitableExt;
 use rustc_type_ir::{
-    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, InferCtxtLike,
-    Interner,
+    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Interner,
 };
 
+use crate::infcx::SolverDelegate;
+
 /// Whether we're canonicalizing a query input or the query response.
 ///
 /// When canonicalizing an input we're in the context of the caller
@@ -37,7 +38,7 @@ pub enum CanonicalizeMode {
     },
 }
 
-pub struct Canonicalizer<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
+pub struct Canonicalizer<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> {
     infcx: &'a Infcx,
     canonicalize_mode: CanonicalizeMode,
 
@@ -46,7 +47,7 @@ pub struct Canonicalizer<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
     binder_index: ty::DebruijnIndex,
 }
 
-impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> Canonicalizer<'a, Infcx, I> {
+impl<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, Infcx, I> {
     pub fn canonicalize<T: TypeFoldable<I>>(
         infcx: &'a Infcx,
         canonicalize_mode: CanonicalizeMode,
@@ -210,7 +211,7 @@ impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> Canonicalizer<'a, Infc
     }
 }
 
-impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
+impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I>
     for Canonicalizer<'_, Infcx, I>
 {
     fn interner(&self) -> I {
diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_next_trait_solver/src/infcx.rs
index 4a5f34e3542..cb46d8f8f73 100644
--- a/compiler/rustc_type_ir/src/infcx.rs
+++ b/compiler/rustc_next_trait_solver/src/infcx.rs
@@ -1,9 +1,9 @@
-use crate::fold::TypeFoldable;
-use crate::relate::Relate;
-use crate::solve::{Goal, NoSolution};
-use crate::{self as ty, Interner};
+use rustc_type_ir::fold::TypeFoldable;
+use rustc_type_ir::relate::Relate;
+use rustc_type_ir::solve::{Goal, NoSolution};
+use rustc_type_ir::{self as ty, Interner};
 
-pub trait InferCtxtLike: Sized {
+pub trait SolverDelegate: Sized {
     type Interner: Interner;
 
     fn interner(&self) -> Self::Interner;
diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs
index 144caf36ee5..ea3e18872fa 100644
--- a/compiler/rustc_next_trait_solver/src/lib.rs
+++ b/compiler/rustc_next_trait_solver/src/lib.rs
@@ -5,5 +5,6 @@
 //! So if you got to this crate from the old solver, it's totally normal.
 
 pub mod canonicalizer;
+pub mod infcx;
 pub mod resolve;
 pub mod solve;
diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs
index 5c00b6978d6..3d8d957eaae 100644
--- a/compiler/rustc_next_trait_solver/src/resolve.rs
+++ b/compiler/rustc_next_trait_solver/src/resolve.rs
@@ -1,27 +1,28 @@
+use crate::infcx::SolverDelegate;
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::visit::TypeVisitableExt;
-use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
+use rustc_type_ir::{self as ty, Interner};
 
 ///////////////////////////////////////////////////////////////////////////
 // EAGER RESOLUTION
 
 /// Resolves ty, region, and const vars to their inferred values or their root vars.
-pub struct EagerResolver<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
+pub struct EagerResolver<'a, Infcx, I = <Infcx as SolverDelegate>::Interner>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     infcx: &'a Infcx,
 }
 
-impl<'a, Infcx: InferCtxtLike> EagerResolver<'a, Infcx> {
+impl<'a, Infcx: SolverDelegate> EagerResolver<'a, Infcx> {
     pub fn new(infcx: &'a Infcx) -> Self {
         EagerResolver { infcx }
     }
 }
 
-impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, Infcx> {
+impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, Infcx> {
     fn interner(&self) -> I {
         self.infcx.interner()
     }
diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
index 4e52caa5a5b..722e86f5b84 100644
--- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs
+++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
@@ -15,12 +15,12 @@
 //! (3.) Otherwise, if we end with two rigid (non-projection) or infer types,
 //! relate them structurally.
 
+use super::infcx::SolverDelegate;
 use super::EvalCtxt;
-use rustc_infer::infer::InferCtxt;
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::ty;
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn compute_alias_relate_goal(
         &mut self,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 1cdbf082078..45d21285ff1 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -1,9 +1,9 @@
 //! Code shared by trait and projection goals for candidate assembly.
 
+use crate::solve::infcx::SolverDelegate;
 use derivative::Derivative;
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
-use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::util::supertraits;
 use rustc_middle::bug;
@@ -51,18 +51,18 @@ pub(super) trait GoalKind<'tcx>:
     /// work, then produce a response (typically by executing
     /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
     fn probe_and_match_goal_against_assumption(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         source: CandidateSource<TyCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
-        then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
+        then: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>) -> QueryResult<'tcx>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// Consider a clause, which consists of a "assumption" and some "requirements",
     /// to satisfy a goal. If the requirements hold, then attempt to satisfy our
     /// goal by equating it with the assumption.
     fn probe_and_consider_implied_clause(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         parent_source: CandidateSource<TyCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
@@ -80,7 +80,7 @@ pub(super) trait GoalKind<'tcx>:
     /// additionally checking all of the supertraits and object bounds to hold,
     /// since they're not implied by the well-formedness of the object type.
     fn probe_and_consider_object_bound_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         source: CandidateSource<TyCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
@@ -104,7 +104,7 @@ pub(super) trait GoalKind<'tcx>:
     }
 
     fn consider_impl_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
         impl_def_id: DefId,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
@@ -116,7 +116,7 @@ pub(super) trait GoalKind<'tcx>:
     /// Trait goals always hold while projection goals never do. This is a bit arbitrary
     /// but prevents incorrect normalization while hiding any trait errors.
     fn consider_error_guaranteed_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         guar: ErrorGuaranteed,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
@@ -125,13 +125,13 @@ pub(super) trait GoalKind<'tcx>:
     /// These components are given by built-in rules from
     /// [`structural_traits::instantiate_constituent_tys_for_auto_trait`].
     fn consider_auto_trait_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A trait alias holds if the RHS traits and `where` clauses hold.
     fn consider_trait_alias_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
@@ -140,7 +140,7 @@ pub(super) trait GoalKind<'tcx>:
     /// These components are given by built-in rules from
     /// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
     fn consider_builtin_sized_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
@@ -149,27 +149,27 @@ pub(super) trait GoalKind<'tcx>:
     /// These components are given by built-in rules from
     /// [`structural_traits::instantiate_constituent_tys_for_copy_clone_trait`].
     fn consider_builtin_copy_clone_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A type is `PointerLike` if we can compute its layout, and that layout
     /// matches the layout of `usize`.
     fn consider_builtin_pointer_like_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A type is a `FnPtr` if it is of `FnPtr` type.
     fn consider_builtin_fn_ptr_trait_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
     /// family of traits where `A` is given by the signature of the type.
     fn consider_builtin_fn_trait_candidates(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
         kind: ty::ClosureKind,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
@@ -177,7 +177,7 @@ pub(super) trait GoalKind<'tcx>:
     /// An async closure is known to implement the `AsyncFn<A>` family of traits
     /// where `A` is given by the signature of the type.
     fn consider_builtin_async_fn_trait_candidates(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
         kind: ty::ClosureKind,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
@@ -186,13 +186,13 @@ pub(super) trait GoalKind<'tcx>:
     /// is used internally to delay computation for async closures until after
     /// upvar analysis is performed in HIR typeck.
     fn consider_builtin_async_fn_kind_helper_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// `Tuple` is implemented if the `Self` type is a tuple.
     fn consider_builtin_tuple_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
@@ -202,7 +202,7 @@ pub(super) trait GoalKind<'tcx>:
     /// the built-in types. For structs, the metadata type is given by the struct
     /// tail.
     fn consider_builtin_pointee_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
@@ -210,7 +210,7 @@ pub(super) trait GoalKind<'tcx>:
     /// `Future<Output = O>`, where `O` is given by the coroutine's return type
     /// that was computed during type-checking.
     fn consider_builtin_future_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
@@ -218,19 +218,19 @@ pub(super) trait GoalKind<'tcx>:
     /// `Iterator<Item = O>`, where `O` is given by the generator's yield type
     /// that was computed during type-checking.
     fn consider_builtin_iterator_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A coroutine (that comes from a `gen` desugaring) is known to implement
     /// `FusedIterator`
     fn consider_builtin_fused_iterator_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_async_iterator_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
@@ -238,27 +238,27 @@ pub(super) trait GoalKind<'tcx>:
     /// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
     /// and return types of the coroutine computed during type-checking.
     fn consider_builtin_coroutine_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_discriminant_kind_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_async_destruct_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_destruct_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_transmute_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
@@ -270,12 +270,12 @@ pub(super) trait GoalKind<'tcx>:
     /// otherwise recompute this for codegen. This is a bit of a mess but the
     /// easiest way to maintain the existing behavior for now.
     fn consider_structural_builtin_unsize_candidates(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Vec<Candidate<TyCtxt<'tcx>>>;
 }
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
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 d6074617caf..496be3af573 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -3,11 +3,12 @@
 
 use rustc_ast_ir::{Movability, Mutability};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_next_trait_solver::infcx::SolverDelegate;
 use rustc_next_trait_solver::solve::{Goal, NoSolution};
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
-use rustc_type_ir::{self as ty, InferCtxtLike, Interner, Upcast};
+use rustc_type_ir::{self as ty, Interner, Upcast};
 use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 
 use crate::solve::EvalCtxt;
@@ -22,7 +23,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<Infcx, I>(
     ty: I::Ty,
 ) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     let tcx = ecx.interner();
@@ -108,7 +109,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<Infcx, I>(
     ty: I::Ty,
 ) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     match ty.kind() {
@@ -176,7 +177,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<Infcx,
     ty: I::Ty,
 ) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     match ty.kind() {
@@ -663,7 +664,7 @@ pub(in crate::solve) fn predicates_for_object_candidate<Infcx, I>(
     object_bounds: I::BoundExistentialPredicates,
 ) -> Vec<Goal<I, I::Predicate>>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     let tcx = ecx.interner();
@@ -712,14 +713,14 @@ where
         .collect()
 }
 
-struct ReplaceProjectionWith<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
+struct ReplaceProjectionWith<'a, Infcx: SolverDelegate<Interner = I>, I: Interner> {
     ecx: &'a EvalCtxt<'a, Infcx>,
     param_env: I::ParamEnv,
     mapping: FxHashMap<I::DefId, ty::Binder<I, ty::ProjectionPredicate<I>>>,
     nested: Vec<Goal<I, I::Predicate>>,
 }
 
-impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
+impl<Infcx: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I>
     for ReplaceProjectionWith<'_, Infcx, I>
 {
     fn interner(&self) -> I {
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index b5753d60f59..3ba17a0dcf9 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -10,6 +10,7 @@
 //! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
 use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
 use crate::solve::eval_ctxt::NestedGoals;
+use crate::solve::infcx::SolverDelegate;
 use crate::solve::{
     inspect, response_no_constraints_raw, CanonicalResponse, QueryResult, Response,
 };
@@ -29,10 +30,11 @@ use rustc_middle::traits::solve::{
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
 use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer};
+use rustc_next_trait_solver::infcx::SolverDelegate as IrSolverDelegate;
 use rustc_next_trait_solver::resolve::EagerResolver;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_type_ir::CanonicalVarValues;
-use rustc_type_ir::{InferCtxtLike, Interner};
+use rustc_type_ir::Interner;
 use std::assert_matches::assert_matches;
 use std::iter;
 use std::ops::Deref;
@@ -53,7 +55,7 @@ impl<'tcx, T> ResponseT<'tcx> for inspect::State<TyCtxt<'tcx>, T> {
     }
 }
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     /// Canonicalizes the goal remembering the original values
     /// for each bound variable.
     pub(super) fn canonicalize_goal<T: TypeFoldable<TyCtxt<'tcx>>>(
@@ -410,7 +412,7 @@ pub(in crate::solve) fn make_canonical_state<Infcx, T, I>(
     data: T,
 ) -> inspect::CanonicalState<I, T>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: IrSolverDelegate<Interner = I>,
     I: Interner,
     T: TypeFoldable<I>,
 {
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 74938d2bbd7..c1fca092a08 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -11,9 +11,8 @@ use rustc_middle::traits::solve::{
 };
 use rustc_middle::ty::AliasRelationDirection;
 use rustc_middle::ty::TypeFolder;
-use rustc_middle::ty::{
-    self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
-};
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
+use rustc_next_trait_solver::infcx::SolverDelegate as IrSolverDelegate;
 use rustc_span::DUMMY_SP;
 use rustc_type_ir::fold::TypeSuperFoldable;
 use rustc_type_ir::inherent::*;
@@ -23,6 +22,7 @@ use rustc_type_ir::{self as ir, CanonicalVarValues, Interner};
 use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 use std::ops::ControlFlow;
 
+use crate::solve::infcx::SolverDelegate;
 use crate::traits::coherence;
 
 use super::inspect::ProofTreeBuilder;
@@ -33,9 +33,9 @@ use super::{GoalSource, SolverMode};
 pub(super) mod canonical;
 mod probe;
 
-pub struct EvalCtxt<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
+pub struct EvalCtxt<'a, Infcx, I = <Infcx as IrSolverDelegate>::Interner>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: IrSolverDelegate<Interner = I>,
     I: Interner,
 {
     /// The inference context that backs (mostly) inference and placeholder terms
@@ -152,7 +152,7 @@ impl<'tcx> InferCtxt<'tcx> {
     }
 }
 
-impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
+impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> {
     pub(super) fn solver_mode(&self) -> SolverMode {
         self.search_graph.solver_mode()
     }
@@ -167,13 +167,13 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
     pub(super) fn enter_root<R>(
         infcx: &InferCtxt<'tcx>,
         generate_proof_tree: GenerateProofTree,
-        f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> R,
+        f: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>) -> R,
     ) -> (R, Option<inspect::GoalEvaluation<TyCtxt<'tcx>>>) {
         let mode = if infcx.intercrate { SolverMode::Coherence } else { SolverMode::Normal };
         let mut search_graph = search_graph::SearchGraph::new(mode);
 
         let mut ecx = EvalCtxt {
-            infcx,
+            infcx: <&SolverDelegate<'tcx>>::from(infcx),
             search_graph: &mut search_graph,
             nested_goals: NestedGoals::new(),
             inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree),
@@ -213,8 +213,8 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
         tcx: TyCtxt<'tcx>,
         search_graph: &'a mut search_graph::SearchGraph<TyCtxt<'tcx>>,
         canonical_input: CanonicalInput<'tcx>,
-        canonical_goal_evaluation: &mut ProofTreeBuilder<InferCtxt<'tcx>>,
-        f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>, Goal<'tcx, ty::Predicate<'tcx>>) -> R,
+        canonical_goal_evaluation: &mut ProofTreeBuilder<SolverDelegate<'tcx>>,
+        f: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>, Goal<'tcx, ty::Predicate<'tcx>>) -> R,
     ) -> R {
         let intercrate = match search_graph.solver_mode() {
             SolverMode::Normal => false,
@@ -227,7 +227,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
             .build_with_canonical(DUMMY_SP, &canonical_input);
 
         let mut ecx = EvalCtxt {
-            infcx,
+            infcx: <&SolverDelegate<'tcx>>::from(infcx),
             variables: canonical_input.variables,
             var_values,
             is_normalizes_to_goal: false,
@@ -275,7 +275,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
         tcx: TyCtxt<'tcx>,
         search_graph: &'a mut search_graph::SearchGraph<TyCtxt<'tcx>>,
         canonical_input: CanonicalInput<'tcx>,
-        goal_evaluation: &mut ProofTreeBuilder<InferCtxt<'tcx>>,
+        goal_evaluation: &mut ProofTreeBuilder<SolverDelegate<'tcx>>,
     ) -> QueryResult<'tcx> {
         let mut canonical_goal_evaluation =
             goal_evaluation.new_canonical_goal_evaluation(canonical_input);
@@ -570,7 +570,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
     }
 }
 
-impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> EvalCtxt<'_, Infcx> {
+impl<Infcx: IrSolverDelegate<Interner = I>, I: Interner> EvalCtxt<'_, Infcx> {
     pub(super) fn interner(&self) -> I {
         self.infcx.interner()
     }
@@ -658,13 +658,13 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> EvalCtxt<'_, Infcx> {
             }
         };
 
-        struct ContainsTermOrNotNameable<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
+        struct ContainsTermOrNotNameable<'a, Infcx: IrSolverDelegate<Interner = I>, I: Interner> {
             term: I::Term,
             universe_of_term: ir::UniverseIndex,
             infcx: &'a Infcx,
         }
 
-        impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, Infcx, I> {
+        impl<Infcx: IrSolverDelegate<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, Infcx, I> {
             fn check_nameable(&self, universe: ir::UniverseIndex) -> ControlFlow<()> {
                 if self.universe_of_term.can_name(universe) {
                     ControlFlow::Continue(())
@@ -674,7 +674,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> EvalCtxt<'_, Infcx> {
             }
         }
 
-        impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeVisitor<I>
+        impl<Infcx: IrSolverDelegate<Interner = I>, I: Interner> TypeVisitor<I>
             for ContainsTermOrNotNameable<'_, Infcx, I>
         {
             type Result = ControlFlow<()>;
@@ -865,7 +865,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> EvalCtxt<'_, Infcx> {
     }
 }
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) {
         self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy());
     }
@@ -1030,7 +1030,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
 /// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs.
 struct ReplaceAliasWithInfer<'me, 'a, Infcx, I>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: IrSolverDelegate<Interner = I>,
     I: Interner,
 {
     ecx: &'me mut EvalCtxt<'a, Infcx>,
@@ -1039,7 +1039,7 @@ where
 
 impl<Infcx, I> TypeFolder<I> for ReplaceAliasWithInfer<'_, '_, Infcx, I>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: IrSolverDelegate<Interner = I>,
     I: Interner,
 {
     fn interner(&self) -> I {
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
index ad6fdd2707d..00fe237735b 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
@@ -1,15 +1,16 @@
 use crate::solve::assembly::Candidate;
 
 use super::EvalCtxt;
+use rustc_next_trait_solver::infcx::SolverDelegate;
 use rustc_next_trait_solver::solve::{
     inspect, BuiltinImplSource, CandidateSource, NoSolution, QueryResult,
 };
-use rustc_type_ir::{InferCtxtLike, Interner};
+use rustc_type_ir::Interner;
 use std::marker::PhantomData;
 
 pub(in crate::solve) struct ProbeCtxt<'me, 'a, Infcx, I, F, T>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     ecx: &'me mut EvalCtxt<'a, Infcx, I>,
@@ -20,7 +21,7 @@ where
 impl<Infcx, I, F, T> ProbeCtxt<'_, '_, Infcx, I, F, T>
 where
     F: FnOnce(&T) -> inspect::ProbeKind<I>,
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> T) -> T {
@@ -56,7 +57,7 @@ where
 
 pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, Infcx, I, F>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     cx: ProbeCtxt<'me, 'a, Infcx, I, F, QueryResult<I>>,
@@ -65,7 +66,7 @@ where
 
 impl<Infcx, I, F> TraitProbeCtxt<'_, '_, Infcx, I, F>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
     F: FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>,
 {
@@ -80,7 +81,7 @@ where
 
 impl<'a, Infcx, I> EvalCtxt<'a, Infcx, I>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     /// `probe_kind` is only called when proof tree building is enabled so it can be
diff --git a/compiler/rustc_trait_selection/src/solve/infcx.rs b/compiler/rustc_trait_selection/src/solve/infcx.rs
new file mode 100644
index 00000000000..c73c49aa9b8
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/infcx.rs
@@ -0,0 +1,178 @@
+use std::ops::Deref;
+
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt};
+use rustc_infer::traits::solve::Goal;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::ty::fold::TypeFoldable;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::DUMMY_SP;
+use rustc_type_ir::relate::Relate;
+use rustc_type_ir::solve::NoSolution;
+
+#[repr(transparent)]
+pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>);
+
+impl<'a, 'tcx> From<&'a InferCtxt<'tcx>> for &'a SolverDelegate<'tcx> {
+    fn from(infcx: &'a InferCtxt<'tcx>) -> Self {
+        // SAFETY: `repr(transparent)`
+        unsafe { std::mem::transmute(infcx) }
+    }
+}
+
+impl<'tcx> Deref for SolverDelegate<'tcx> {
+    type Target = InferCtxt<'tcx>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<'tcx> rustc_next_trait_solver::infcx::SolverDelegate for SolverDelegate<'tcx> {
+    type Interner = TyCtxt<'tcx>;
+
+    fn interner(&self) -> TyCtxt<'tcx> {
+        (**self).tcx
+    }
+
+    fn universe_of_ty(&self, vid: ty::TyVid) -> Option<ty::UniverseIndex> {
+        // FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
+        // ty infers will give you the universe of the var it resolved to not the universe
+        // it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
+        // try to print out `?0.1` it will just print `?0`.
+        match (**self).probe_ty_var(vid) {
+            Err(universe) => Some(universe),
+            Ok(_) => None,
+        }
+    }
+
+    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
+        match (**self).inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
+            Err(universe) => Some(universe),
+            Ok(_) => None,
+        }
+    }
+
+    fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex> {
+        // Same issue as with `universe_of_ty`
+        match (**self).probe_const_var(ct) {
+            Err(universe) => Some(universe),
+            Ok(_) => None,
+        }
+    }
+
+    fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid {
+        (**self).root_var(var)
+    }
+
+    fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
+        (**self).root_const_var(var)
+    }
+
+    fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> Ty<'tcx> {
+        match (**self).probe_ty_var(vid) {
+            Ok(ty) => ty,
+            Err(_) => Ty::new_var((**self).tcx, (**self).root_var(vid)),
+        }
+    }
+
+    fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
+        (**self).opportunistic_resolve_int_var(vid)
+    }
+
+    fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
+        (**self).opportunistic_resolve_float_var(vid)
+    }
+
+    fn opportunistic_resolve_ct_var(&self, vid: ty::ConstVid) -> ty::Const<'tcx> {
+        match (**self).probe_const_var(vid) {
+            Ok(ct) => ct,
+            Err(_) => ty::Const::new_var((**self).tcx, (**self).root_const_var(vid)),
+        }
+    }
+
+    fn opportunistic_resolve_effect_var(&self, vid: ty::EffectVid) -> ty::Const<'tcx> {
+        match (**self).probe_effect_var(vid) {
+            Some(ct) => ct,
+            None => ty::Const::new_infer(
+                (**self).tcx,
+                ty::InferConst::EffectVar((**self).root_effect_var(vid)),
+            ),
+        }
+    }
+
+    fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
+        (**self)
+            .inner
+            .borrow_mut()
+            .unwrap_region_constraints()
+            .opportunistic_resolve_var((**self).tcx, vid)
+    }
+
+    fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
+        (**self).defining_opaque_types()
+    }
+
+    fn next_ty_infer(&self) -> Ty<'tcx> {
+        (**self).next_ty_var(DUMMY_SP)
+    }
+
+    fn next_const_infer(&self) -> ty::Const<'tcx> {
+        (**self).next_const_var(DUMMY_SP)
+    }
+
+    fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
+        (**self).fresh_args_for_item(DUMMY_SP, def_id)
+    }
+
+    fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
+        &self,
+        value: ty::Binder<'tcx, T>,
+    ) -> T {
+        (**self).instantiate_binder_with_fresh_vars(
+            DUMMY_SP,
+            BoundRegionConversionTime::HigherRankedType,
+            value,
+        )
+    }
+
+    fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
+        &self,
+        value: ty::Binder<'tcx, T>,
+        f: impl FnOnce(T) -> U,
+    ) -> U {
+        (**self).enter_forall(value, f)
+    }
+
+    fn relate<T: Relate<TyCtxt<'tcx>>>(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        lhs: T,
+        variance: ty::Variance,
+        rhs: T,
+    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
+        (**self).at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs)
+    }
+
+    fn eq_structurally_relating_aliases<T: Relate<TyCtxt<'tcx>>>(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        lhs: T,
+        rhs: T,
+    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
+        (**self)
+            .at(&ObligationCause::dummy(), param_env)
+            .eq_structurally_relating_aliases_no_trace(lhs, rhs)
+    }
+
+    fn resolve_vars_if_possible<T>(&self, value: T) -> T
+    where
+        T: TypeFoldable<TyCtxt<'tcx>>,
+    {
+        (**self).resolve_vars_if_possible(value)
+    }
+
+    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
+        (**self).probe(|_| probe())
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 464c188b6e3..db8f15118e1 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -23,6 +23,7 @@ use rustc_next_trait_solver::resolve::EagerResolver;
 use rustc_span::{Span, DUMMY_SP};
 
 use crate::solve::eval_ctxt::canonical;
+use crate::solve::infcx::SolverDelegate;
 use crate::solve::{EvalCtxt, GoalEvaluationKind, GoalSource};
 use crate::solve::{GenerateProofTree, InferCtxtEvalExt};
 use crate::traits::ObligationCtxt;
@@ -199,8 +200,9 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
             let _ = term_hack.constrain(infcx, span, param_env);
         }
 
-        let opt_impl_args =
-            opt_impl_args.map(|impl_args| impl_args.fold_with(&mut EagerResolver::new(infcx)));
+        let opt_impl_args = opt_impl_args.map(|impl_args| {
+            impl_args.fold_with(&mut EagerResolver::new(<&SolverDelegate<'tcx>>::from(infcx)))
+        });
 
         let goals = instantiated_goals
             .into_iter()
@@ -403,7 +405,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
             infcx,
             depth,
             orig_values,
-            goal: uncanonicalized_goal.fold_with(&mut EagerResolver::new(infcx)),
+            goal: uncanonicalized_goal
+                .fold_with(&mut EagerResolver::new(<&SolverDelegate<'tcx>>::from(infcx))),
             result,
             evaluation_kind: evaluation.kind,
             normalizes_to_term_hack,
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
index 35750598bc7..d750cd963de 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
@@ -9,10 +9,11 @@ use std::mem;
 use crate::solve::eval_ctxt::canonical;
 use crate::solve::{self, inspect, GenerateProofTree};
 use rustc_middle::bug;
+use rustc_next_trait_solver::infcx::SolverDelegate;
 use rustc_next_trait_solver::solve::{
     CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult,
 };
-use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
+use rustc_type_ir::{self as ty, Interner};
 
 /// The core data structure when building proof trees.
 ///
@@ -34,9 +35,9 @@ use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
 /// trees. At the end of trait solving `ProofTreeBuilder::finalize`
 /// is called to recursively convert the whole structure to a
 /// finished proof tree.
-pub(in crate::solve) struct ProofTreeBuilder<Infcx, I = <Infcx as InferCtxtLike>::Interner>
+pub(in crate::solve) struct ProofTreeBuilder<Infcx, I = <Infcx as SolverDelegate>::Interner>
 where
-    Infcx: InferCtxtLike<Interner = I>,
+    Infcx: SolverDelegate<Interner = I>,
     I: Interner,
 {
     _infcx: PhantomData<Infcx>,
@@ -232,7 +233,7 @@ impl<I: Interner> WipProbeStep<I> {
     }
 }
 
-impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> {
+impl<Infcx: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<Infcx> {
     fn new(state: impl Into<DebugSolver<I>>) -> ProofTreeBuilder<Infcx> {
         ProofTreeBuilder { state: Some(Box::new(state.into())), _infcx: PhantomData }
     }
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 7b6e525370c..3b43c0e3e70 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -13,9 +13,10 @@
 //!
 //! FIXME(@lcnr): Write that section. If you read this before then ask me
 //! about it on zulip.
+
+use self::infcx::SolverDelegate;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::Canonical;
-use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_macros::extension;
 use rustc_middle::bug;
@@ -33,6 +34,7 @@ mod alias_relate;
 mod assembly;
 mod eval_ctxt;
 mod fulfill;
+mod infcx;
 pub mod inspect;
 mod normalize;
 mod normalizes_to;
@@ -73,7 +75,7 @@ impl<'tcx> Canonical<'tcx, Response<TyCtxt<'tcx>>> {
     }
 }
 
-impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
+impl<'a, 'tcx> EvalCtxt<'a, SolverDelegate<'tcx>> {
     #[instrument(level = "trace", skip(self))]
     fn compute_type_outlives_goal(
         &mut self,
@@ -224,7 +226,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
     }
 }
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     /// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`.
     ///
     /// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`.
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
index a6e4b6ff4a8..064018e89b8 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs
@@ -1,9 +1,9 @@
+use crate::solve::infcx::SolverDelegate;
 use crate::solve::EvalCtxt;
-use rustc_infer::infer::InferCtxt;
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::ty;
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn normalize_anon_const(
         &mut self,
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs
index 41b2b9cd4d2..48d45fe510d 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/inherent.rs
@@ -4,13 +4,14 @@
 //! 1. instantiate generic parameters,
 //! 2. equate the self type, and
 //! 3. instantiate and register where clauses.
-use rustc_infer::infer::InferCtxt;
+
+use crate::solve::infcx::SolverDelegate;
 use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult};
 use rustc_middle::ty;
 
 use crate::solve::EvalCtxt;
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     pub(super) fn normalize_inherent_associated_type(
         &mut self,
         goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index 5c5923e9d39..0aa10afbee7 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -2,10 +2,10 @@ use crate::traits::specialization_graph::{self, LeafDef, Node};
 
 use super::assembly::structural_traits::AsyncCallableRelevantTypes;
 use super::assembly::{self, structural_traits, Candidate};
+use super::infcx::SolverDelegate;
 use super::{EvalCtxt, GoalSource};
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
-use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::solve::inspect::ProbeKind;
 use rustc_infer::traits::solve::MaybeCause;
@@ -24,7 +24,7 @@ mod inherent;
 mod opaque_types;
 mod weak_types;
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn compute_normalizes_to_goal(
         &mut self,
@@ -98,11 +98,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn probe_and_match_goal_against_assumption(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         source: CandidateSource<'tcx>,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
-        then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
+        then: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>) -> QueryResult<'tcx>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if let Some(projection_pred) = assumption.as_projection_clause() {
             if projection_pred.projection_def_id() == goal.predicate.def_id() {
@@ -137,7 +137,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_impl_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, NormalizesTo<'tcx>>,
         impl_def_id: DefId,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
@@ -198,7 +198,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                 return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
             };
 
-            let error_response = |ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, reason| {
+            let error_response = |ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>, reason| {
                 let guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason);
                 let error_term = match goal.predicate.alias.kind(tcx) {
                     ty::AliasTermKind::ProjectionTy => Ty::new_error(tcx, guar).into(),
@@ -263,14 +263,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     /// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error`
     /// and succeed. Can experiment with this to figure out what results in better error messages.
     fn consider_error_guaranteed_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         _guar: ErrorGuaranteed,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         Err(NoSolution)
     }
 
     fn consider_auto_trait_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         ecx.interner().dcx().span_delayed_bug(
@@ -281,42 +281,42 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_trait_alias_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("trait aliases do not have associated types: {:?}", goal);
     }
 
     fn consider_builtin_sized_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`Sized` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_copy_clone_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_pointer_like_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`PointerLike` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_fn_ptr_trait_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`FnPtr` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_fn_trait_candidates(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
@@ -359,7 +359,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_async_fn_trait_candidates(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
@@ -450,7 +450,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_async_fn_kind_helper_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let [
@@ -497,14 +497,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_tuple_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`Tuple` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_pointee_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = ecx.interner();
@@ -586,7 +586,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_future_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
@@ -622,7 +622,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_iterator_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
@@ -658,14 +658,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_fused_iterator_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`FusedIterator` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_async_iterator_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
@@ -701,7 +701,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_coroutine_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
@@ -748,14 +748,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_structural_builtin_unsize_candidates(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Vec<Candidate<TyCtxt<'tcx>>> {
         bug!("`Unsize` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_discriminant_kind_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
@@ -807,7 +807,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_async_destruct_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
@@ -860,21 +860,21 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     }
 
     fn consider_builtin_destruct_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`Destruct` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_transmute_candidate(
-        _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        _ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
     }
 }
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     fn translate_args(
         &mut self,
         assoc_def: &LeafDef,
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs
index 82464470b2a..f7423c367b5 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs
@@ -1,7 +1,8 @@
 //! Computes a normalizes-to (projection) goal for opaque types. This goal
 //! behaves differently depending on the param-env's reveal mode and whether
 //! the opaque is in a defining scope.
-use rustc_infer::infer::InferCtxt;
+
+use crate::solve::infcx::SolverDelegate;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::traits::Reveal;
@@ -10,7 +11,7 @@ use rustc_middle::ty::util::NotUniqueParam;
 
 use crate::solve::{EvalCtxt, SolverMode};
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     pub(super) fn normalize_opaque_type(
         &mut self,
         goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs
index 5442b9ccffc..26d60ffb321 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/weak_types.rs
@@ -3,13 +3,14 @@
 //!
 //! Since a weak alias is never ambiguous, this just computes the `type_of` of
 //! the alias and registers the where-clauses of the type alias.
-use rustc_infer::infer::InferCtxt;
+
+use crate::solve::infcx::SolverDelegate;
 use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, QueryResult};
 use rustc_middle::ty;
 
 use crate::solve::EvalCtxt;
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     pub(super) fn normalize_weak_type(
         &mut self,
         goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index cae73cc2d07..839db73a8b3 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -1,11 +1,11 @@
 use crate::solve::GoalSource;
 
+use super::infcx::SolverDelegate;
 use super::EvalCtxt;
-use rustc_infer::infer::InferCtxt;
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::ty::{self, ProjectionPredicate};
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn compute_projection_goal(
         &mut self,
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs
index 681061c25aa..055540d122f 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs
@@ -3,11 +3,11 @@ use std::mem;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_index::Idx;
 use rustc_index::IndexVec;
+use rustc_next_trait_solver::infcx::SolverDelegate;
 use rustc_next_trait_solver::solve::CacheData;
 use rustc_next_trait_solver::solve::{CanonicalInput, Certainty, QueryResult};
 use rustc_session::Limit;
 use rustc_type_ir::inherent::*;
-use rustc_type_ir::InferCtxtLike;
 use rustc_type_ir::Interner;
 
 use super::inspect;
@@ -250,7 +250,7 @@ impl<I: Interner> SearchGraph<I> {
     ///
     /// Given some goal which is proven via the `prove_goal` closure, this
     /// handles caching, overflow, and coinductive cycles.
-    pub(super) fn with_new_goal<Infcx: InferCtxtLike<Interner = I>>(
+    pub(super) fn with_new_goal<Infcx: SolverDelegate<Interner = I>>(
         &mut self,
         tcx: I,
         input: CanonicalInput<I>,
@@ -411,7 +411,7 @@ impl<I: Interner> SearchGraph<I> {
     /// Try to fetch a previously computed result from the global cache,
     /// making sure to only do so if it would match the result of reevaluating
     /// this goal.
-    fn lookup_global_cache<Infcx: InferCtxtLike<Interner = I>>(
+    fn lookup_global_cache<Infcx: SolverDelegate<Interner = I>>(
         &mut self,
         tcx: I,
         input: CanonicalInput<I>,
@@ -468,7 +468,7 @@ impl<I: Interner> SearchGraph<I> {
         prove_goal: &mut F,
     ) -> StepResult<I>
     where
-        Infcx: InferCtxtLike<Interner = I>,
+        Infcx: SolverDelegate<Interner = I>,
         F: FnMut(&mut Self, &mut ProofTreeBuilder<Infcx>) -> QueryResult<I>,
     {
         let result = prove_goal(self, inspect);
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index bcb2ea18f78..0aace43f333 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -2,11 +2,11 @@
 
 use super::assembly::structural_traits::AsyncCallableRelevantTypes;
 use super::assembly::{self, structural_traits, Candidate};
+use super::infcx::SolverDelegate;
 use super::{EvalCtxt, GoalSource, SolverMode};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{LangItem, Movability};
-use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::solve::MaybeCause;
 use rustc_infer::traits::util::supertraits;
@@ -37,7 +37,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_impl_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, TraitPredicate<'tcx>>,
         impl_def_id: DefId,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
@@ -93,7 +93,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_error_guaranteed_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         _guar: ErrorGuaranteed,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         // FIXME: don't need to enter a probe here.
@@ -102,11 +102,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn probe_and_match_goal_against_assumption(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         source: CandidateSource<'tcx>,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
-        then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
+        then: impl FnOnce(&mut EvalCtxt<'_, SolverDelegate<'tcx>>) -> QueryResult<'tcx>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if let Some(trait_clause) = assumption.as_trait_clause() {
             if trait_clause.def_id() == goal.predicate.def_id()
@@ -130,7 +130,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_auto_trait_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -173,7 +173,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_trait_alias_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -196,7 +196,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_sized_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -211,7 +211,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_copy_clone_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -226,7 +226,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_pointer_like_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -256,7 +256,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_fn_ptr_trait_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
@@ -287,7 +287,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_fn_trait_candidates(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
@@ -328,7 +328,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_async_fn_trait_candidates(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
@@ -379,7 +379,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_async_fn_kind_helper_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else {
@@ -406,7 +406,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     /// impl Tuple for (T1, .., Tn) {}
     /// ```
     fn consider_builtin_tuple_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -422,7 +422,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_pointee_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -434,7 +434,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_future_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -460,7 +460,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_iterator_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -486,7 +486,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_fused_iterator_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -510,7 +510,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_async_iterator_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -536,7 +536,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_coroutine_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -568,7 +568,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_discriminant_kind_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -581,7 +581,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_async_destruct_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -594,7 +594,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_destruct_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -610,7 +610,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 
     fn consider_builtin_transmute_candidate(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -651,7 +651,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     /// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {}
     /// ```
     fn consider_structural_builtin_unsize_candidates(
-        ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+        ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
         goal: Goal<'tcx, Self>,
     ) -> Vec<Candidate<TyCtxt<'tcx>>> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
@@ -722,7 +722,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     }
 }
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
+impl<'tcx> EvalCtxt<'_, SolverDelegate<'tcx>> {
     /// Trait upcasting allows for coercions between trait objects:
     /// ```ignore (builtin impl example)
     /// trait Super {}
@@ -841,7 +841,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         // having any inference side-effects. We process obligations because
         // unification may initially succeed due to deferred projection equality.
         let projection_may_match =
-            |ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
+            |ecx: &mut EvalCtxt<'_, SolverDelegate<'tcx>>,
              source_projection: ty::PolyExistentialProjection<'tcx>,
              target_projection: ty::PolyExistentialProjection<'tcx>| {
                 source_projection.item_def_id() == target_projection.item_def_id()
@@ -1147,7 +1147,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         source: CandidateSource<'tcx>,
         goal: Goal<'tcx, TraitPredicate<'tcx>>,
         constituent_tys: impl Fn(
-            &EvalCtxt<'_, InferCtxt<'tcx>>,
+            &EvalCtxt<'_, SolverDelegate<'tcx>>,
             Ty<'tcx>,
         ) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution>,
     ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index ac9b2808804..130ea231bf7 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -45,7 +45,6 @@ mod canonical;
 mod const_kind;
 mod flags;
 mod generic_arg;
-mod infcx;
 mod interner;
 mod opaque_ty;
 mod predicate;
@@ -62,7 +61,6 @@ pub use codec::*;
 pub use const_kind::*;
 pub use flags::*;
 pub use generic_arg::*;
-pub use infcx::InferCtxtLike;
 pub use interner::*;
 pub use opaque_ty::*;
 pub use predicate::*;