about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_borrowck/src/facts.rs27
-rw-r--r--compiler/rustc_borrowck/src/polonius/mod.rs10
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs44
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs81
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs8
-rw-r--r--compiler/rustc_middle/src/ty/context.rs1
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs31
-rw-r--r--compiler/rustc_middle/src/ty/region.rs18
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs23
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs8
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs42
-rw-r--r--compiler/rustc_next_trait_solver/src/lib.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/resolve.rs83
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs2
-rw-r--r--compiler/rustc_type_ir/src/debug.rs32
-rw-r--r--compiler/rustc_type_ir/src/generic_arg.rs14
-rw-r--r--compiler/rustc_type_ir/src/infcx.rs44
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs15
-rw-r--r--compiler/rustc_type_ir/src/interner.rs5
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs27
25 files changed, 309 insertions, 238 deletions
diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs
index e7faec7bbac..51ea59e2092 100644
--- a/compiler/rustc_borrowck/src/facts.rs
+++ b/compiler/rustc_borrowck/src/facts.rs
@@ -15,8 +15,31 @@ use std::path::Path;
 #[derive(Copy, Clone, Debug)]
 pub struct RustcFacts;
 
+rustc_index::newtype_index! {
+    /// A (kinda) newtype of `RegionVid` so we can implement `Atom` on it.
+    #[orderable]
+    #[debug_format = "'?{}"]
+    pub struct PoloniusRegionVid {}
+}
+
+impl polonius_engine::Atom for PoloniusRegionVid {
+    fn index(self) -> usize {
+        self.as_usize()
+    }
+}
+impl From<RegionVid> for PoloniusRegionVid {
+    fn from(value: RegionVid) -> Self {
+        Self::from_usize(value.as_usize())
+    }
+}
+impl From<PoloniusRegionVid> for RegionVid {
+    fn from(value: PoloniusRegionVid) -> Self {
+        Self::from_usize(value.as_usize())
+    }
+}
+
 impl polonius_engine::FactTypes for RustcFacts {
-    type Origin = RegionVid;
+    type Origin = PoloniusRegionVid;
     type Loan = BorrowIndex;
     type Point = LocationIndex;
     type Variable = Local;
@@ -119,7 +142,7 @@ trait FactRow {
     ) -> Result<(), Box<dyn Error>>;
 }
 
-impl FactRow for RegionVid {
+impl FactRow for PoloniusRegionVid {
     fn write(
         &self,
         out: &mut dyn Write,
diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs
index 40126d50d57..9984f76e6d4 100644
--- a/compiler/rustc_borrowck/src/polonius/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/mod.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
 
 use crate::borrow_set::BorrowSet;
-use crate::facts::AllFacts;
+use crate::facts::{AllFacts, PoloniusRegionVid};
 use crate::location::LocationTable;
 use crate::type_check::free_region_relations::UniversalRegionRelations;
 use crate::universal_regions::UniversalRegions;
@@ -137,7 +137,9 @@ fn emit_universal_region_facts(
     //   the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
     //   added to the existing number of loans, as if they succeeded them in the set.
     //
-    all_facts.universal_region.extend(universal_regions.universal_regions());
+    all_facts
+        .universal_region
+        .extend(universal_regions.universal_regions().map(PoloniusRegionVid::from));
     let borrow_count = borrow_set.len();
     debug!(
         "emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
@@ -148,7 +150,7 @@ fn emit_universal_region_facts(
     for universal_region in universal_regions.universal_regions() {
         let universal_region_idx = universal_region.index();
         let placeholder_loan_idx = borrow_count + universal_region_idx;
-        all_facts.placeholder.push((universal_region, placeholder_loan_idx.into()));
+        all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
     }
 
     // 2: the universal region relations `outlives` constraints are emitted as
@@ -160,7 +162,7 @@ fn emit_universal_region_facts(
                      fr1={:?}, fr2={:?}",
                 fr1, fr2
             );
-            all_facts.known_placeholder_subset.push((fr1, fr2));
+            all_facts.known_placeholder_subset.push((fr1.into(), fr2.into()));
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 167ca7ba045..b57cf9066cf 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1506,7 +1506,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         subset_errors.sort();
         subset_errors.dedup();
 
-        for (longer_fr, shorter_fr) in subset_errors.into_iter() {
+        for &(longer_fr, shorter_fr) in subset_errors.into_iter() {
             debug!(
                 "check_polonius_subset_errors: subset_error longer_fr={:?},\
                  shorter_fr={:?}",
@@ -1514,14 +1514,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             );
 
             let propagated = self.try_propagate_universal_region_error(
-                *longer_fr,
-                *shorter_fr,
+                longer_fr.into(),
+                shorter_fr.into(),
                 &mut propagated_outlives_requirements,
             );
             if propagated == RegionRelationCheckResult::Error {
                 errors_buffer.push(RegionErrorKind::RegionError {
-                    longer_fr: *longer_fr,
-                    shorter_fr: *shorter_fr,
+                    longer_fr: longer_fr.into(),
+                    shorter_fr: shorter_fr.into(),
                     fr_origin: NllRegionVariableOrigin::FreeRegion,
                     is_reported: true,
                 });
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index 7f530227043..ccfa9f12ef4 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -117,7 +117,7 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
             let universal_regions = &typeck.borrowck_context.universal_regions;
             typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
                 let region_vid = universal_regions.to_region_vid(region);
-                facts.use_of_var_derefs_origin.push((local, region_vid));
+                facts.use_of_var_derefs_origin.push((local, region_vid.into()));
             });
         }
     }
@@ -136,7 +136,7 @@ pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
         let universal_regions = &typeck.borrowck_context.universal_regions;
         typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
             let region_vid = universal_regions.to_region_vid(drop_live_region);
-            facts.drop_of_var_derefs_origin.push((local, region_vid));
+            facts.drop_of_var_derefs_origin.push((local, region_vid.into()));
         });
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index e48130ebddf..4e46a0c62c7 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -260,16 +260,14 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
             |constraint: &OutlivesConstraint<'_>| {
                 if let Some(from_location) = constraint.locations.from_location() {
                     Either::Left(iter::once((
-                        constraint.sup,
-                        constraint.sub,
+                        constraint.sup.into(),
+                        constraint.sub.into(),
                         location_table.mid_index(from_location),
                     )))
                 } else {
-                    Either::Right(
-                        location_table
-                            .all_points()
-                            .map(move |location| (constraint.sup, constraint.sub, location)),
-                    )
+                    Either::Right(location_table.all_points().map(move |location| {
+                        (constraint.sup.into(), constraint.sub.into(), location)
+                    }))
                 }
             },
         ));
@@ -2545,7 +2543,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             if let Some(borrow_index) = borrow_set.get_index_of(&location) {
                 let region_vid = borrow_region.as_var();
                 all_facts.loan_issued_at.push((
-                    region_vid,
+                    region_vid.into(),
                     borrow_index,
                     location_table.mid_index(location),
                 ));
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 723f4c81ca5..8d4011421bd 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -369,33 +369,43 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
         }
     }
 
-    fn root_ty_var(&self, vid: TyVid) -> TyVid {
-        self.root_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 probe_ty_var(&self, vid: TyVid) -> Option<Ty<'tcx>> {
-        self.probe_ty_var(vid).ok()
+    fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
+        self.defining_opaque_types
     }
 
-    fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
-        let re = self
-            .inner
-            .borrow_mut()
-            .unwrap_region_constraints()
-            .opportunistic_resolve_var(self.tcx, vid);
-        if *re == ty::ReVar(vid) { None } else { Some(re) }
+    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 root_ct_var(&self, vid: ConstVid) -> ConstVid {
-        self.root_const_var(vid)
+    fn opportunistic_resolve_int_var(&self, vid: IntVid) -> Ty<'tcx> {
+        self.opportunistic_resolve_int_var(vid)
     }
 
-    fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
-        self.probe_const_var(vid).ok()
+    fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> Ty<'tcx> {
+        self.opportunistic_resolve_float_var(vid)
     }
 
-    fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
-        self.defining_opaque_types
+    fn opportunistic_resolve_ct_var(&self, vid: ConstVid, ty: Ty<'tcx>) -> ty::Const<'tcx> {
+        match self.probe_const_var(vid) {
+            Ok(ct) => ct,
+            Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid), ty),
+        }
+    }
+
+    fn opportunistic_resolve_effect_var(&self, vid: EffectVid, ty: Ty<'tcx>) -> 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)), ty)
+            }
+        }
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 61b13dd9a54..21ef2e89523 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -173,84 +173,3 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
         }
     }
 }
-
-///////////////////////////////////////////////////////////////////////////
-// EAGER RESOLUTION
-
-/// Resolves ty, region, and const vars to their inferred values or their root vars.
-pub struct EagerResolver<'a, 'tcx> {
-    infcx: &'a InferCtxt<'tcx>,
-}
-
-impl<'a, 'tcx> EagerResolver<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
-        EagerResolver { infcx }
-    }
-}
-
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> {
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        match *t.kind() {
-            ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
-                Ok(t) => t.fold_with(self),
-                Err(_) => Ty::new_var(self.infcx.tcx, self.infcx.root_var(vid)),
-            },
-            ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid),
-            ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid),
-            _ => {
-                if t.has_infer() {
-                    t.super_fold_with(self)
-                } else {
-                    t
-                }
-            }
-        }
-    }
-
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
-            ty::ReVar(vid) => self
-                .infcx
-                .inner
-                .borrow_mut()
-                .unwrap_region_constraints()
-                .opportunistic_resolve_var(self.infcx.tcx, vid),
-            _ => r,
-        }
-    }
-
-    fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match c.kind() {
-            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
-                // FIXME: we need to fold the ty too, I think.
-                match self.infcx.probe_const_var(vid) {
-                    Ok(c) => c.fold_with(self),
-                    Err(_) => {
-                        ty::Const::new_var(self.infcx.tcx, self.infcx.root_const_var(vid), c.ty())
-                    }
-                }
-            }
-            ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
-                debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool);
-                self.infcx.probe_effect_var(vid).unwrap_or_else(|| {
-                    ty::Const::new_infer(
-                        self.infcx.tcx,
-                        ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)),
-                        self.infcx.tcx.types.bool,
-                    )
-                })
-            }
-            _ => {
-                if c.has_infer() {
-                    c.super_fold_with(self)
-                } else {
-                    c
-                }
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 9dc30447f0e..f7cc055be11 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -175,6 +175,14 @@ impl<'tcx> Const<'tcx> {
 }
 
 impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
+    fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Self {
+        Const::new_infer(tcx, infer, ty)
+    }
+
+    fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid, ty: Ty<'tcx>) -> Self {
+        Const::new_var(tcx, vid, ty)
+    }
+
     fn new_anon_bound(
         tcx: TyCtxt<'tcx>,
         debruijn: ty::DebruijnIndex,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index d75f250275b..8185c99c2fd 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -134,7 +134,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type EarlyParamRegion = ty::EarlyParamRegion;
     type LateParamRegion = ty::LateParamRegion;
     type BoundRegion = ty::BoundRegion;
-    type InferRegion = ty::RegionVid;
     type PlaceholderRegion = ty::PlaceholderRegion;
 
     type ParamEnv = ty::ParamEnv<'tcx>;
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 38b2987399a..3d263e62de6 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -27,6 +27,7 @@ use std::ops::Deref;
 use std::ptr::NonNull;
 
 pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind<TyCtxt<'tcx>>;
+pub type TermKind<'tcx> = rustc_type_ir::TermKind<TyCtxt<'tcx>>;
 
 /// An entity in the Rust type system, which can be one of
 /// several kinds (types, lifetimes, and consts).
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 44f09b8ba21..8bb19bc85ac 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -28,7 +28,7 @@ use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::util::Discr;
 pub use adt::*;
 pub use assoc::*;
-pub use generic_args::{GenericArgKind, *};
+pub use generic_args::{GenericArgKind, TermKind, *};
 pub use generics::*;
 pub use intrinsic::IntrinsicDef;
 use rustc_ast as ast;
@@ -48,7 +48,8 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
 use rustc_index::IndexVec;
 use rustc_macros::{
-    Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
+    extension, Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable,
+    TypeVisitable,
 };
 use rustc_query_system::ich::StableHashingContext;
 use rustc_serialize::{Decodable, Encodable};
@@ -521,6 +522,14 @@ pub struct Term<'tcx> {
     marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
 }
 
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Term<'tcx> {
+    type Kind = TermKind<'tcx>;
+
+    fn kind(self) -> Self::Kind {
+        self.unpack()
+    }
+}
+
 #[cfg(parallel_compiler)]
 unsafe impl<'tcx> rustc_data_structures::sync::DynSend for Term<'tcx> where
     &'tcx (Ty<'tcx>, Const<'tcx>): rustc_data_structures::sync::DynSend
@@ -566,13 +575,19 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
-        Ok(self.unpack().try_fold_with(folder)?.pack())
+        match self.unpack() {
+            ty::TermKind::Ty(ty) => ty.try_fold_with(folder).map(Into::into),
+            ty::TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
+        }
     }
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
     fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
-        self.unpack().visit_with(visitor)
+        match self.unpack() {
+            ty::TermKind::Ty(ty) => ty.visit_with(visitor),
+            ty::TermKind::Const(ct) => ct.visit_with(visitor),
+        }
     }
 }
 
@@ -650,13 +665,7 @@ const TAG_MASK: usize = 0b11;
 const TYPE_TAG: usize = 0b00;
 const CONST_TAG: usize = 0b01;
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable)]
-pub enum TermKind<'tcx> {
-    Ty(Ty<'tcx>),
-    Const(Const<'tcx>),
-}
-
+#[extension(pub trait TermKindPackExt<'tcx>)]
 impl<'tcx> TermKind<'tcx> {
     #[inline]
     fn pack(self) -> Term<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index 7540f0ab83f..551e2ea2295 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -1,13 +1,12 @@
-use polonius_engine::Atom;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::MultiSpan;
 use rustc_hir::def_id::DefId;
-use rustc_index::Idx;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::symbol::sym;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{ErrorGuaranteed, DUMMY_SP};
 use rustc_type_ir::RegionKind as IrRegionKind;
+pub use rustc_type_ir::RegionVid;
 use std::ops::Deref;
 
 use crate::ty::{self, BoundVar, TyCtxt, TypeFlags};
@@ -348,21 +347,6 @@ impl std::fmt::Debug for EarlyParamRegion {
     }
 }
 
-rustc_index::newtype_index! {
-    /// A **region** (lifetime) **v**ariable **ID**.
-    #[derive(HashStable)]
-    #[encodable]
-    #[orderable]
-    #[debug_format = "'?{}"]
-    pub struct RegionVid {}
-}
-
-impl Atom for RegionVid {
-    fn index(self) -> usize {
-        Idx::index(self)
-    }
-}
-
 #[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)]
 #[derive(HashStable)]
 /// The parameter representation of late-bound function parameters, "some region
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7d24824d568..81d92a2a448 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -259,18 +259,6 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Region<'tcx> {
     }
 }
 
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::RegionVid {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        match this.infcx.universe_of_lt(*this.data) {
-            Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
-            None => write!(f, "{:?}", this.data),
-        }
-    }
-}
-
 impl<'tcx, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
     fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
         this: WithInfcx<'_, Infcx, &Self>,
@@ -383,13 +371,10 @@ impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> {
 impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Term<'a> {
     type Lifted = ty::Term<'tcx>;
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        Some(
-            match self.unpack() {
-                TermKind::Ty(ty) => TermKind::Ty(tcx.lift(ty)?),
-                TermKind::Const(c) => TermKind::Const(tcx.lift(c)?),
-            }
-            .pack(),
-        )
+        match self.unpack() {
+            TermKind::Ty(ty) => tcx.lift(ty).map(Into::into),
+            TermKind::Const(c) => tcx.lift(c).map(Into::into),
+        }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 7c41c5f512e..2d9d178449e 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1611,6 +1611,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
         tcx.types.bool
     }
 
+    fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Self {
+        Ty::new_infer(tcx, infer)
+    }
+
+    fn new_var(tcx: TyCtxt<'tcx>, vid: ty::TyVid) -> Self {
+        Ty::new_var(tcx, vid)
+    }
+
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
         Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
     }
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 755f5cfa5a3..696639e9c1b 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -268,7 +268,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             ty::ReVar(vid) => {
                 assert_eq!(
                     self.infcx.opportunistic_resolve_lt_var(vid),
-                    None,
+                    r,
                     "region vid should have been resolved fully before canonicalization"
                 );
                 match self.canonicalize_mode {
@@ -302,13 +302,8 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             ty::Infer(i) => match i {
                 ty::TyVar(vid) => {
                     assert_eq!(
-                        self.infcx.root_ty_var(vid),
-                        vid,
-                        "ty vid should have been resolved fully before canonicalization"
-                    );
-                    assert_eq!(
-                        self.infcx.probe_ty_var(vid),
-                        None,
+                        self.infcx.opportunistic_resolve_ty_var(vid),
+                        t,
                         "ty vid should have been resolved fully before canonicalization"
                     );
 
@@ -318,10 +313,24 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
                             .unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")),
                     ))
                 }
-                ty::IntVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Int),
-                ty::FloatVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Float),
+                ty::IntVar(vid) => {
+                    assert_eq!(
+                        self.infcx.opportunistic_resolve_int_var(vid),
+                        t,
+                        "ty vid should have been resolved fully before canonicalization"
+                    );
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+                }
+                ty::FloatVar(vid) => {
+                    assert_eq!(
+                        self.infcx.opportunistic_resolve_float_var(vid),
+                        t,
+                        "ty vid should have been resolved fully before canonicalization"
+                    );
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
+                }
                 ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
-                    todo!()
+                    panic!("fresh vars not expected in canonicalization")
                 }
             },
             ty::Placeholder(placeholder) => match self.canonicalize_mode {
@@ -387,14 +396,11 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
         let kind = match c.kind() {
             ty::ConstKind::Infer(i) => match i {
                 ty::InferConst::Var(vid) => {
+                    // We compare `kind`s here because we've folded the `ty` with `RegionsToStatic`
+                    // so we'll get a mismatch in types if it actually changed any regions.
                     assert_eq!(
-                        self.infcx.root_ct_var(vid),
-                        vid,
-                        "region vid should have been resolved fully before canonicalization"
-                    );
-                    assert_eq!(
-                        self.infcx.probe_ct_var(vid),
-                        None,
+                        self.infcx.opportunistic_resolve_ct_var(vid, ty).kind(),
+                        c.kind(),
                         "region vid should have been resolved fully before canonicalization"
                     );
                     CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty)
diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs
index 4202dc39fb2..b913a05095c 100644
--- a/compiler/rustc_next_trait_solver/src/lib.rs
+++ b/compiler/rustc_next_trait_solver/src/lib.rs
@@ -1,2 +1,3 @@
 pub mod canonicalizer;
+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
new file mode 100644
index 00000000000..1333b4aa7d8
--- /dev/null
+++ b/compiler/rustc_next_trait_solver/src/resolve.rs
@@ -0,0 +1,83 @@
+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};
+
+///////////////////////////////////////////////////////////////////////////
+// EAGER RESOLUTION
+
+/// Resolves ty, region, and const vars to their inferred values or their root vars.
+pub struct EagerResolver<
+    'a,
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner = <Infcx as InferCtxtLike>::Interner,
+> {
+    infcx: &'a Infcx,
+}
+
+impl<'a, Infcx: InferCtxtLike> EagerResolver<'a, Infcx> {
+    pub fn new(infcx: &'a Infcx) -> Self {
+        EagerResolver { infcx }
+    }
+}
+
+impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, Infcx> {
+    fn interner(&self) -> I {
+        self.infcx.interner()
+    }
+
+    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
+        match t.kind() {
+            ty::Infer(ty::TyVar(vid)) => {
+                let resolved = self.infcx.opportunistic_resolve_ty_var(vid);
+                if t != resolved && resolved.has_infer() {
+                    resolved.fold_with(self)
+                } else {
+                    resolved
+                }
+            }
+            ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid),
+            ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid),
+            _ => {
+                if t.has_infer() {
+                    t.super_fold_with(self)
+                } else {
+                    t
+                }
+            }
+        }
+    }
+
+    fn fold_region(&mut self, r: I::Region) -> I::Region {
+        match r.kind() {
+            ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid),
+            _ => r,
+        }
+    }
+
+    fn fold_const(&mut self, c: I::Const) -> I::Const {
+        match c.kind() {
+            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
+                let ty = c.ty().fold_with(self);
+                let resolved = self.infcx.opportunistic_resolve_ct_var(vid, ty);
+                if c != resolved && resolved.has_infer() {
+                    resolved.fold_with(self)
+                } else {
+                    resolved
+                }
+            }
+            ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
+                let bool = Ty::new_bool(self.infcx.interner());
+                debug_assert_eq!(c.ty(), bool);
+                self.infcx.opportunistic_resolve_effect_var(vid, bool)
+            }
+            _ => {
+                if c.has_infer() {
+                    c.super_fold_with(self)
+                } else {
+                    c
+                }
+            }
+        }
+    }
+}
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 a642d0c40fc..9590a82c067 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -18,7 +18,6 @@ use rustc_index::IndexVec;
 use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
-use rustc_infer::infer::resolve::EagerResolver;
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_infer::infer::{InferCtxt, InferOk};
 use rustc_infer::traits::solve::NestedNormalizationGoals;
@@ -31,6 +30,7 @@ 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::resolve::EagerResolver;
 use rustc_span::{Span, DUMMY_SP};
 use std::assert_matches::assert_matches;
 use std::iter;
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index e12c66b6928..737d03f73f0 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -11,7 +11,6 @@
 
 use rustc_ast_ir::try_visit;
 use rustc_ast_ir::visit::VisitorResult;
-use rustc_infer::infer::resolve::EagerResolver;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_macros::extension;
 use rustc_middle::traits::query::NoSolution;
@@ -20,6 +19,7 @@ use rustc_middle::traits::solve::{Certainty, Goal};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{TyCtxt, TypeFoldable};
 use rustc_middle::{bug, ty};
+use rustc_next_trait_solver::resolve::EagerResolver;
 use rustc_span::{Span, DUMMY_SP};
 
 use crate::solve::eval_ctxt::canonical;
diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs
index 9298360f749..4e8be1ee4c2 100644
--- a/compiler/rustc_type_ir/src/debug.rs
+++ b/compiler/rustc_type_ir/src/debug.rs
@@ -1,4 +1,6 @@
-use crate::{ConstVid, InferCtxtLike, Interner, TyVid, UniverseIndex};
+use crate::{
+    ConstVid, EffectVid, FloatVid, InferCtxtLike, IntVid, Interner, RegionVid, TyVid, UniverseIndex,
+};
 
 use core::fmt;
 use std::marker::PhantomData;
@@ -16,7 +18,7 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
         None
     }
 
-    fn universe_of_lt(&self, _lt: I::InferRegion) -> Option<UniverseIndex> {
+    fn universe_of_lt(&self, _lt: RegionVid) -> Option<UniverseIndex> {
         None
     }
 
@@ -24,27 +26,31 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
         None
     }
 
-    fn root_ty_var(&self, vid: TyVid) -> TyVid {
-        vid
+    fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> I::Ty {
+        panic!("cannot resolve {vid:?}")
     }
 
-    fn probe_ty_var(&self, _vid: TyVid) -> Option<I::Ty> {
-        None
+    fn opportunistic_resolve_int_var(&self, vid: IntVid) -> I::Ty {
+        panic!("cannot resolve {vid:?}")
     }
 
-    fn opportunistic_resolve_lt_var(&self, _vid: I::InferRegion) -> Option<I::Region> {
-        None
+    fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> I::Ty {
+        panic!("cannot resolve {vid:?}")
     }
 
-    fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
-        vid
+    fn opportunistic_resolve_ct_var(&self, vid: ConstVid, _: I::Ty) -> I::Const {
+        panic!("cannot resolve {vid:?}")
     }
 
-    fn probe_ct_var(&self, _vid: ConstVid) -> Option<I::Const> {
-        None
+    fn opportunistic_resolve_effect_var(&self, vid: EffectVid, _: I::Ty) -> I::Const {
+        panic!("cannot resolve {vid:?}")
+    }
+
+    fn opportunistic_resolve_lt_var(&self, vid: crate::RegionVid) -> I::Region {
+        panic!("cannot resolve {vid:?}")
     }
 
-    fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes {
+    fn defining_opaque_types(&self) -> I::DefiningOpaqueTypes {
         Default::default()
     }
 }
diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs
index 622a4080608..cc8c4444657 100644
--- a/compiler/rustc_type_ir/src/generic_arg.rs
+++ b/compiler/rustc_type_ir/src/generic_arg.rs
@@ -16,3 +16,17 @@ pub enum GenericArgKind<I: Interner> {
     Type(I::Ty),
     Const(I::Const),
 }
+
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Debug(bound = ""),
+    Eq(bound = ""),
+    PartialEq(bound = "")
+)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub enum TermKind<I: Interner> {
+    Ty(I::Ty),
+    Const(I::Const),
+}
diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs
index a53287c1987..bb5081fb335 100644
--- a/compiler/rustc_type_ir/src/infcx.rs
+++ b/compiler/rustc_type_ir/src/infcx.rs
@@ -1,4 +1,4 @@
-use crate::{ConstVid, Interner, TyVid, UniverseIndex};
+use crate::{ConstVid, EffectVid, FloatVid, IntVid, Interner, RegionVid, TyVid, UniverseIndex};
 
 pub trait InferCtxtLike {
     type Interner: Interner;
@@ -6,37 +6,23 @@ pub trait InferCtxtLike {
     fn interner(&self) -> Self::Interner;
 
     fn universe_of_ty(&self, ty: TyVid) -> Option<UniverseIndex>;
+    fn universe_of_lt(&self, lt: RegionVid) -> Option<UniverseIndex>;
+    fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
 
-    /// Resolve `TyVid` to its root `TyVid`.
-    fn root_ty_var(&self, vid: TyVid) -> TyVid;
-
-    /// Resolve `TyVid` to its inferred type, if it has been equated with a non-infer type.
-    fn probe_ty_var(&self, vid: TyVid) -> Option<<Self::Interner as Interner>::Ty>;
-
-    fn universe_of_lt(
+    fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> <Self::Interner as Interner>::Ty;
+    fn opportunistic_resolve_int_var(&self, vid: IntVid) -> <Self::Interner as Interner>::Ty;
+    fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> <Self::Interner as Interner>::Ty;
+    fn opportunistic_resolve_ct_var(
         &self,
-        lt: <Self::Interner as Interner>::InferRegion,
-    ) -> Option<UniverseIndex>;
-
-    /// Resolve `InferRegion` to its inferred region, if it has been equated with
-    /// a non-infer region.
-    ///
-    /// FIXME: This has slightly different semantics than `{probe,resolve}_{ty,ct}_var`,
-    /// that has to do with the fact unlike `Ty` or `Const` vars, in rustc, we may
-    /// not always be able to *name* the root region var from the universe of the
-    /// var we're trying to resolve. That's why it's called *opportunistic*.
-    fn opportunistic_resolve_lt_var(
+        vid: ConstVid,
+        ty: <Self::Interner as Interner>::Ty,
+    ) -> <Self::Interner as Interner>::Const;
+    fn opportunistic_resolve_effect_var(
         &self,
-        vid: <Self::Interner as Interner>::InferRegion,
-    ) -> Option<<Self::Interner as Interner>::Region>;
-
-    fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
-
-    /// Resolve `ConstVid` to its root `ConstVid`.
-    fn root_ct_var(&self, vid: ConstVid) -> ConstVid;
-
-    /// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type.
-    fn probe_ct_var(&self, vid: ConstVid) -> Option<<Self::Interner as Interner>::Const>;
+        vid: EffectVid,
+        ty: <Self::Interner as Interner>::Ty,
+    ) -> <Self::Interner as Interner>::Const;
+    fn opportunistic_resolve_lt_var(&self, vid: RegionVid) -> <Self::Interner as Interner>::Region;
 
     fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes;
 }
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 19c76fb165a..f66c6e722f7 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -7,11 +7,11 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::ops::Deref;
 
-use crate::fold::TypeSuperFoldable;
+use crate::fold::{TypeFoldable, TypeSuperFoldable};
 use crate::visit::{Flags, TypeSuperVisitable};
 use crate::{
-    AliasTy, AliasTyKind, BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind,
-    TyKind, UnevaluatedConst, UniverseIndex,
+    AliasTy, AliasTyKind, BoundVar, ConstKind, ConstVid, DebruijnIndex, DebugWithInfcx, InferConst,
+    InferTy, Interner, RegionKind, TyKind, TyVid, UnevaluatedConst, UniverseIndex,
 };
 
 pub trait Ty<I: Interner<Ty = Self>>:
@@ -28,6 +28,10 @@ pub trait Ty<I: Interner<Ty = Self>>:
 {
     fn new_bool(interner: I) -> Self;
 
+    fn new_infer(interner: I, var: InferTy) -> Self;
+
+    fn new_var(interner: I, var: TyVid) -> Self;
+
     fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
 
     fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy<I>) -> Self;
@@ -68,6 +72,10 @@ pub trait Const<I: Interner<Const = Self>>:
     + TypeSuperFoldable<I>
     + Flags
 {
+    fn new_infer(interner: I, var: InferConst, ty: I::Ty) -> Self;
+
+    fn new_var(interner: I, var: ConstVid, ty: I::Ty) -> Self;
+
     fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
 
     fn new_unevaluated(interner: I, uv: UnevaluatedConst<I>, ty: I::Ty) -> Self;
@@ -87,6 +95,7 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
     + IntoIterator<Item = I::GenericArg>
     + Deref<Target: Deref<Target = [I::GenericArg]>>
     + Default
+    + TypeFoldable<I>
 {
     fn type_at(self, i: usize) -> I::Ty;
 
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 0b51d2e75f4..6516d5b1645 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -10,7 +10,7 @@ use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
 use crate::{
     AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate,
     DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, FnSig, GenericArgKind,
-    NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
+    NormalizesTo, ProjectionPredicate, SubtypePredicate, TermKind, TraitPredicate, TraitRef,
 };
 
 pub trait Interner:
@@ -36,7 +36,7 @@ pub trait Interner:
     /// not including the args from the parent item (trait or impl).
     type OwnItemArgs: Copy + Debug + Hash + Eq;
     type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq + IntoKind<Kind = GenericArgKind<Self>>;
-    type Term: Copy + Debug + Hash + Eq;
+    type Term: Copy + Debug + Hash + Eq + IntoKind<Kind = TermKind<Self>>;
 
     type Binder<T: TypeVisitable<Self>>: BoundVars<Self> + TypeSuperVisitable<Self>;
     type BoundVars: IntoIterator<Item = Self::BoundVar>;
@@ -79,7 +79,6 @@ pub trait Interner:
     type EarlyParamRegion: Copy + Debug + Hash + Eq;
     type LateParamRegion: Copy + Debug + Hash + Eq;
     type BoundRegion: Copy + Debug + Hash + Eq + BoundVarLike<Self>;
-    type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Eq;
     type PlaceholderRegion: PlaceholderLike;
 
     // Predicates
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index eaae4ee0130..48ade273289 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -1,13 +1,35 @@
 #[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 #[cfg(feature = "nightly")]
-use rustc_macros::{TyDecodable, TyEncodable};
+use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
 use std::fmt;
 
 use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
 
 use self::RegionKind::*;
 
+rustc_index::newtype_index! {
+    /// A **region** **v**ariable **ID**.
+    #[encodable]
+    #[orderable]
+    #[debug_format = "'?{}"]
+    #[gate_rustc_only]
+    #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+    pub struct RegionVid {}
+}
+
+impl<I: Interner> DebugWithInfcx<I> for RegionVid {
+    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
+        this: WithInfcx<'_, Infcx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        match this.infcx.universe_of_lt(*this.data) {
+            Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
+            None => write!(f, "{:?}", this.data),
+        }
+    }
+}
+
 /// Representation of regions. Note that the NLL checker uses a distinct
 /// representation of regions. For this reason, it internally replaces all the
 /// regions with inference variables -- the index of the variable is then used
@@ -152,7 +174,7 @@ pub enum RegionKind<I: Interner> {
     ReStatic,
 
     /// A region variable. Should not exist outside of type inference.
-    ReVar(I::InferRegion),
+    ReVar(RegionVid),
 
     /// A placeholder region -- the higher-ranked version of `ReLateParam`.
     /// Should not exist outside of type inference.
@@ -251,7 +273,6 @@ where
     I::EarlyParamRegion: HashStable<CTX>,
     I::BoundRegion: HashStable<CTX>,
     I::LateParamRegion: HashStable<CTX>,
-    I::InferRegion: HashStable<CTX>,
     I::PlaceholderRegion: HashStable<CTX>,
 {
     #[inline]