about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMakai <m4kai410@gmail.com>2025-05-05 15:35:54 +0800
committerMakai <m4kai410@gmail.com>2025-07-04 01:33:17 +0000
commit663e2b7e2904d68fda6d5c23fd1b8ad9fbd7ee03 (patch)
tree099728c1ffc6a4f76fc3e653ee7c11407a26817a
parent0f6f68313d6d1b503c695bddd2f41dc09f6c1058 (diff)
downloadrust-663e2b7e2904d68fda6d5c23fd1b8ad9fbd7ee03.tar.gz
rust-663e2b7e2904d68fda6d5c23fd1b8ad9fbd7ee03.zip
refactor: move `convert` module to `stable_mir`
note that this commit delete `convert/error.rs`, we would use `SmirError::from_internal` instead.

**Unresolved questions:**
- There are still a few direct calls to rustc's internals scattered across `impl Stable`s, but most of them appear to be relatively stable, e.g., `mir::interpret::ConstAllocation::inner(self)` and `mir::syntax::SwitchTargets::otherwise(self)`.
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs11
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/error.rs25
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs78
-rw-r--r--compiler/rustc_smir/src/stable_mir/compiler_interface.rs1
-rw-r--r--compiler/rustc_smir/src/stable_mir/convert/internal.rs (renamed from compiler/rustc_smir/src/rustc_internal/internal.rs)458
-rw-r--r--compiler/rustc_smir/src/stable_mir/convert/mod.rs126
-rw-r--r--compiler/rustc_smir/src/stable_mir/convert/stable/abi.rs (renamed from compiler/rustc_smir/src/rustc_smir/convert/abi.rs)157
-rw-r--r--compiler/rustc_smir/src/stable_mir/convert/stable/mir.rs (renamed from compiler/rustc_smir/src/rustc_smir/convert/mir.rs)502
-rw-r--r--compiler/rustc_smir/src/stable_mir/convert/stable/mod.rs (renamed from compiler/rustc_smir/src/rustc_smir/convert/mod.rs)36
-rw-r--r--compiler/rustc_smir/src/stable_mir/convert/stable/ty.rs (renamed from compiler/rustc_smir/src/rustc_smir/convert/ty.rs)498
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs1
11 files changed, 1225 insertions, 668 deletions
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index c343242ddfc..5947a7a8440 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -17,13 +17,12 @@ use rustc_span::Span;
 use rustc_span::def_id::{CrateNum, DefId};
 use scoped_tls::scoped_thread_local;
 use stable_mir::Error;
+use stable_mir::convert::{RustcInternal, Stable};
 
 use crate::rustc_smir::context::SmirCtxt;
-use crate::rustc_smir::{Stable, Tables};
 use crate::rustc_smir::{Bridge, IndexedVal, SmirContainer, Tables};
 use crate::stable_mir;
 
-mod internal;
 pub mod pretty;
 
 /// Convert an internal Rust compiler item into its stable counterpart, if one exists.
@@ -340,11 +339,3 @@ impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V
         k
     }
 }
-
-/// Trait used to translate a stable construct to its rustc counterpart.
-///
-/// This is basically a mirror of [crate::rustc_smir::Stable].
-pub trait RustcInternal {
-    type T<'tcx>;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx>;
-}
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/error.rs b/compiler/rustc_smir/src/rustc_smir/convert/error.rs
deleted file mode 100644
index 2cde5542483..00000000000
--- a/compiler/rustc_smir/src/rustc_smir/convert/error.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//! Handle the conversion of different internal errors into a stable version.
-//!
-//! Currently we encode everything as [stable_mir::Error], which is represented as a string.
-
-use rustc_middle::mir::interpret::AllocError;
-use rustc_middle::ty::layout::LayoutError;
-
-use crate::rustc_smir::{Stable, Tables};
-use crate::stable_mir;
-
-impl<'tcx> Stable<'tcx> for LayoutError<'tcx> {
-    type T = stable_mir::Error;
-
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
-        stable_mir::Error::new(format!("{self:?}"))
-    }
-}
-
-impl<'tcx> Stable<'tcx> for AllocError {
-    type T = stable_mir::Error;
-
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
-        stable_mir::Error::new(format!("{self:?}"))
-    }
-}
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 4f6919d2724..b597189585b 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -7,7 +7,6 @@
 //!
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
-use std::marker::PointeeSized;
 use std::cell::RefCell;
 use std::fmt::Debug;
 
@@ -23,7 +22,6 @@ use crate::rustc_internal::IndexMap;
 pub mod alloc;
 mod builder;
 pub mod context;
-mod convert;
 
 /// A container which is used for TLS.
 pub struct SmirContainer<'tcx, B: Bridge> {
@@ -155,79 +153,3 @@ where
             .collect()
     }
 }
-
-/// Trait used to convert between an internal MIR type to a Stable MIR type.
-pub trait Stable<'cx>: PointeeSized {
-    /// The stable representation of the type implementing Stable.
-    type T;
-    /// Converts an object to the equivalent Stable MIR representation.
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T;
-}
-
-impl<'tcx, T> Stable<'tcx> for &T
-where
-    T: Stable<'tcx>,
-{
-    type T = T::T;
-
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        (*self).stable(tables)
-    }
-}
-
-impl<'tcx, T> Stable<'tcx> for Option<T>
-where
-    T: Stable<'tcx>,
-{
-    type T = Option<T::T>;
-
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        self.as_ref().map(|value| value.stable(tables))
-    }
-}
-
-impl<'tcx, T, E> Stable<'tcx> for Result<T, E>
-where
-    T: Stable<'tcx>,
-    E: Stable<'tcx>,
-{
-    type T = Result<T::T, E::T>;
-
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        match self {
-            Ok(val) => Ok(val.stable(tables)),
-            Err(error) => Err(error.stable(tables)),
-        }
-    }
-}
-
-impl<'tcx, T> Stable<'tcx> for &[T]
-where
-    T: Stable<'tcx>,
-{
-    type T = Vec<T::T>;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        self.iter().map(|e| e.stable(tables)).collect()
-    }
-}
-
-impl<'tcx, T, U> Stable<'tcx> for (T, U)
-where
-    T: Stable<'tcx>,
-    U: Stable<'tcx>,
-{
-    type T = (T::T, U::T);
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        (self.0.stable(tables), self.1.stable(tables))
-    }
-}
-
-impl<'tcx, T> Stable<'tcx> for RangeInclusive<T>
-where
-    T: Stable<'tcx>,
-{
-    type T = RangeInclusive<T::T>;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        RangeInclusive::new(self.start().stable(tables), self.end().stable(tables))
-    }
-}
diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
index 3be9d9db753..9d75f366416 100644
--- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
+++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
@@ -8,6 +8,7 @@ use std::cell::Cell;
 use rustc_hir::def::DefKind;
 use rustc_smir::{Bridge, SmirContainer, Tables};
 use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions};
+use stable_mir::convert::{RustcInternal, Stable};
 use stable_mir::crate_def::Attribute;
 use stable_mir::mir::alloc::{AllocId, GlobalAlloc};
 use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef};
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/stable_mir/convert/internal.rs
index f878b6e6b71..a8c5f108528 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/stable_mir/convert/internal.rs
@@ -5,93 +5,132 @@
 
 // Prefer importing stable_mir over internal rustc constructs to make this file more readable.
 
-use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy, TyCtxt};
+use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy};
+use rustc_smir::context::SmirCtxt;
+use rustc_smir::{IndexedVal, Tables};
 use rustc_span::Symbol;
 use stable_mir::abi::Layout;
+use stable_mir::compiler_interface::BridgeTys;
+use stable_mir::convert::RustcInternal;
 use stable_mir::mir::alloc::AllocId;
 use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
 use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp};
 use stable_mir::ty::{
     Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind,
     ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
-    GenericArgKind, GenericArgs, IndexedVal, IntTy, MirConst, Movability, Pattern, Region, RigidTy,
-    Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx,
+    GenericArgKind, GenericArgs, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span,
+    TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx,
 };
 use stable_mir::{CrateItem, CrateNum, DefId};
 
-use super::RustcInternal;
-use crate::rustc_smir::Tables;
-use crate::stable_mir;
+use crate::{rustc_smir, stable_mir};
 
 impl RustcInternal for CrateItem {
     type T<'tcx> = rustc_span::def_id::DefId;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        self.0.internal(tables, tcx)
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        self.0.internal(tables, cx)
     }
 }
 
 impl RustcInternal for CrateNum {
     type T<'tcx> = rustc_span::def_id::CrateNum;
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         rustc_span::def_id::CrateNum::from_usize(*self)
     }
 }
 
 impl RustcInternal for DefId {
     type T<'tcx> = rustc_span::def_id::DefId;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.lift(tables.def_ids[*self]).unwrap()
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.lift(tables.def_ids[*self]).unwrap()
     }
 }
 
 impl RustcInternal for GenericArgs {
     type T<'tcx> = rustc_ty::GenericArgsRef<'tcx>;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables, tcx)))
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables, cx)))
     }
 }
 
 impl RustcInternal for GenericArgKind {
     type T<'tcx> = rustc_ty::GenericArg<'tcx>;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         let arg: rustc_ty::GenericArg<'tcx> = match self {
-            GenericArgKind::Lifetime(reg) => reg.internal(tables, tcx).into(),
-            GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(),
-            GenericArgKind::Const(cnst) => cnst.internal(tables, tcx).into(),
+            GenericArgKind::Lifetime(reg) => reg.internal(tables, cx).into(),
+            GenericArgKind::Type(ty) => ty.internal(tables, cx).into(),
+            GenericArgKind::Const(cnst) => cnst.internal(tables, cx).into(),
         };
-        tcx.lift(arg).unwrap()
+        cx.lift(arg).unwrap()
     }
 }
 
 impl RustcInternal for Region {
     type T<'tcx> = rustc_ty::Region<'tcx>;
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         // Cannot recover region. Use erased for now.
-        tcx.lifetimes.re_erased
+        use rustc_smir::context::SmirRegion;
+        cx.lifetimes_re_erased()
     }
 }
 
 impl RustcInternal for Ty {
     type T<'tcx> = InternalTy<'tcx>;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.lift(tables.types[*self]).unwrap()
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.lift(tables.types[*self]).unwrap()
     }
 }
 
 impl RustcInternal for TyConst {
     type T<'tcx> = InternalConst<'tcx>;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.lift(tables.ty_consts[self.id]).unwrap()
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.lift(tables.ty_consts[self.id]).unwrap()
     }
 }
 
 impl RustcInternal for Pattern {
     type T<'tcx> = rustc_ty::Pattern<'tcx>;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.mk_pat(match self {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.mk_pat(match self {
             Pattern::Range { start, end, include_end: _ } => rustc_ty::PatternKind::Range {
-                start: start.as_ref().unwrap().internal(tables, tcx),
-                end: end.as_ref().unwrap().internal(tables, tcx),
+                start: start.as_ref().unwrap().internal(tables, cx),
+                end: end.as_ref().unwrap().internal(tables, cx),
             },
         })
     }
@@ -100,62 +139,66 @@ impl RustcInternal for Pattern {
 impl RustcInternal for RigidTy {
     type T<'tcx> = rustc_ty::TyKind<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             RigidTy::Bool => rustc_ty::TyKind::Bool,
             RigidTy::Char => rustc_ty::TyKind::Char,
-            RigidTy::Int(int_ty) => rustc_ty::TyKind::Int(int_ty.internal(tables, tcx)),
-            RigidTy::Uint(uint_ty) => rustc_ty::TyKind::Uint(uint_ty.internal(tables, tcx)),
-            RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables, tcx)),
+            RigidTy::Int(int_ty) => rustc_ty::TyKind::Int(int_ty.internal(tables, cx)),
+            RigidTy::Uint(uint_ty) => rustc_ty::TyKind::Uint(uint_ty.internal(tables, cx)),
+            RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables, cx)),
             RigidTy::Never => rustc_ty::TyKind::Never,
             RigidTy::Array(ty, cnst) => {
-                rustc_ty::TyKind::Array(ty.internal(tables, tcx), cnst.internal(tables, tcx))
+                rustc_ty::TyKind::Array(ty.internal(tables, cx), cnst.internal(tables, cx))
             }
             RigidTy::Pat(ty, pat) => {
-                rustc_ty::TyKind::Pat(ty.internal(tables, tcx), pat.internal(tables, tcx))
+                rustc_ty::TyKind::Pat(ty.internal(tables, cx), pat.internal(tables, cx))
             }
             RigidTy::Adt(def, args) => {
-                rustc_ty::TyKind::Adt(def.internal(tables, tcx), args.internal(tables, tcx))
+                rustc_ty::TyKind::Adt(def.internal(tables, cx), args.internal(tables, cx))
             }
             RigidTy::Str => rustc_ty::TyKind::Str,
-            RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables, tcx)),
+            RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables, cx)),
             RigidTy::RawPtr(ty, mutability) => {
-                rustc_ty::TyKind::RawPtr(ty.internal(tables, tcx), mutability.internal(tables, tcx))
+                rustc_ty::TyKind::RawPtr(ty.internal(tables, cx), mutability.internal(tables, cx))
             }
             RigidTy::Ref(region, ty, mutability) => rustc_ty::TyKind::Ref(
-                region.internal(tables, tcx),
-                ty.internal(tables, tcx),
-                mutability.internal(tables, tcx),
+                region.internal(tables, cx),
+                ty.internal(tables, cx),
+                mutability.internal(tables, cx),
             ),
-            RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables, tcx)),
+            RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables, cx)),
             RigidTy::FnDef(def, args) => {
-                rustc_ty::TyKind::FnDef(def.0.internal(tables, tcx), args.internal(tables, tcx))
+                rustc_ty::TyKind::FnDef(def.0.internal(tables, cx), args.internal(tables, cx))
             }
             RigidTy::FnPtr(sig) => {
-                let (sig_tys, hdr) = sig.internal(tables, tcx).split();
+                let (sig_tys, hdr) = sig.internal(tables, cx).split();
                 rustc_ty::TyKind::FnPtr(sig_tys, hdr)
             }
             RigidTy::Closure(def, args) => {
-                rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx))
+                rustc_ty::TyKind::Closure(def.0.internal(tables, cx), args.internal(tables, cx))
             }
             RigidTy::Coroutine(def, args, _mov) => {
-                rustc_ty::TyKind::Coroutine(def.0.internal(tables, tcx), args.internal(tables, tcx))
+                rustc_ty::TyKind::Coroutine(def.0.internal(tables, cx), args.internal(tables, cx))
             }
             RigidTy::CoroutineClosure(def, args) => rustc_ty::TyKind::CoroutineClosure(
-                def.0.internal(tables, tcx),
-                args.internal(tables, tcx),
+                def.0.internal(tables, cx),
+                args.internal(tables, cx),
             ),
             RigidTy::CoroutineWitness(def, args) => rustc_ty::TyKind::CoroutineWitness(
-                def.0.internal(tables, tcx),
-                args.internal(tables, tcx),
+                def.0.internal(tables, cx),
+                args.internal(tables, cx),
             ),
             RigidTy::Dynamic(predicate, region, dyn_kind) => rustc_ty::TyKind::Dynamic(
-                tcx.mk_poly_existential_predicates(&predicate.internal(tables, tcx)),
-                region.internal(tables, tcx),
-                dyn_kind.internal(tables, tcx),
+                cx.mk_poly_existential_predicates(&predicate.internal(tables, cx)),
+                region.internal(tables, cx),
+                dyn_kind.internal(tables, cx),
             ),
             RigidTy::Tuple(tys) => {
-                rustc_ty::TyKind::Tuple(tcx.mk_type_list(&tys.internal(tables, tcx)))
+                rustc_ty::TyKind::Tuple(cx.mk_type_list(&tys.internal(tables, cx)))
             }
         }
     }
@@ -164,7 +207,11 @@ impl RustcInternal for RigidTy {
 impl RustcInternal for IntTy {
     type T<'tcx> = rustc_ty::IntTy;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             IntTy::Isize => rustc_ty::IntTy::Isize,
             IntTy::I8 => rustc_ty::IntTy::I8,
@@ -179,7 +226,11 @@ impl RustcInternal for IntTy {
 impl RustcInternal for UintTy {
     type T<'tcx> = rustc_ty::UintTy;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             UintTy::Usize => rustc_ty::UintTy::Usize,
             UintTy::U8 => rustc_ty::UintTy::U8,
@@ -194,7 +245,11 @@ impl RustcInternal for UintTy {
 impl RustcInternal for FloatTy {
     type T<'tcx> = rustc_ty::FloatTy;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             FloatTy::F16 => rustc_ty::FloatTy::F16,
             FloatTy::F32 => rustc_ty::FloatTy::F32,
@@ -207,7 +262,11 @@ impl RustcInternal for FloatTy {
 impl RustcInternal for Mutability {
     type T<'tcx> = rustc_ty::Mutability;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             Mutability::Not => rustc_ty::Mutability::Not,
             Mutability::Mut => rustc_ty::Mutability::Mut,
@@ -218,7 +277,11 @@ impl RustcInternal for Mutability {
 impl RustcInternal for Movability {
     type T<'tcx> = rustc_ty::Movability;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             Movability::Static => rustc_ty::Movability::Static,
             Movability::Movable => rustc_ty::Movability::Movable,
@@ -229,7 +292,11 @@ impl RustcInternal for Movability {
 impl RustcInternal for RawPtrKind {
     type T<'tcx> = rustc_middle::mir::RawPtrKind;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             RawPtrKind::Mut => rustc_middle::mir::RawPtrKind::Mut,
             RawPtrKind::Const => rustc_middle::mir::RawPtrKind::Const,
@@ -241,12 +308,16 @@ impl RustcInternal for RawPtrKind {
 impl RustcInternal for FnSig {
     type T<'tcx> = rustc_ty::FnSig<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.lift(rustc_ty::FnSig {
-            inputs_and_output: tcx.mk_type_list(&self.inputs_and_output.internal(tables, tcx)),
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.lift(rustc_ty::FnSig {
+            inputs_and_output: cx.mk_type_list(&self.inputs_and_output.internal(tables, cx)),
             c_variadic: self.c_variadic,
-            safety: self.safety.internal(tables, tcx),
-            abi: self.abi.internal(tables, tcx),
+            safety: self.safety.internal(tables, cx),
+            abi: self.abi.internal(tables, cx),
         })
         .unwrap()
     }
@@ -255,7 +326,11 @@ impl RustcInternal for FnSig {
 impl RustcInternal for VariantIdx {
     type T<'tcx> = rustc_abi::VariantIdx;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         rustc_abi::VariantIdx::from(self.to_index())
     }
 }
@@ -263,27 +338,35 @@ impl RustcInternal for VariantIdx {
 impl RustcInternal for VariantDef {
     type T<'tcx> = &'tcx rustc_ty::VariantDef;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        self.adt_def.internal(tables, tcx).variant(self.idx.internal(tables, tcx))
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        self.adt_def.internal(tables, cx).variant(self.idx.internal(tables, cx))
     }
 }
 
 impl RustcInternal for MirConst {
     type T<'tcx> = rustc_middle::mir::Const<'tcx>;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         let constant = tables.mir_consts[self.id];
         match constant {
             rustc_middle::mir::Const::Ty(ty, ct) => {
-                rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap(), tcx.lift(ct).unwrap())
+                rustc_middle::mir::Const::Ty(cx.lift(ty).unwrap(), cx.lift(ct).unwrap())
             }
             rustc_middle::mir::Const::Unevaluated(uneval, ty) => {
                 rustc_middle::mir::Const::Unevaluated(
-                    tcx.lift(uneval).unwrap(),
-                    tcx.lift(ty).unwrap(),
+                    cx.lift(uneval).unwrap(),
+                    cx.lift(ty).unwrap(),
                 )
             }
             rustc_middle::mir::Const::Val(const_val, ty) => {
-                rustc_middle::mir::Const::Val(tcx.lift(const_val).unwrap(), tcx.lift(ty).unwrap())
+                rustc_middle::mir::Const::Val(cx.lift(const_val).unwrap(), cx.lift(ty).unwrap())
             }
         }
     }
@@ -292,11 +375,15 @@ impl RustcInternal for MirConst {
 impl RustcInternal for MonoItem {
     type T<'tcx> = rustc_middle::mir::mono::MonoItem<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         use rustc_middle::mir::mono as rustc_mono;
         match self {
-            MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables, tcx)),
-            MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables, tcx)),
+            MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables, cx)),
+            MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables, cx)),
             MonoItem::GlobalAsm(_) => {
                 unimplemented!()
             }
@@ -307,16 +394,24 @@ impl RustcInternal for MonoItem {
 impl RustcInternal for Instance {
     type T<'tcx> = rustc_ty::Instance<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.lift(tables.instances[self.def]).unwrap()
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.lift(tables.instances[self.def]).unwrap()
     }
 }
 
 impl RustcInternal for StaticDef {
     type T<'tcx> = rustc_span::def_id::DefId;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        self.0.internal(tables, tcx)
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        self.0.internal(tables, cx)
     }
 }
 
@@ -328,11 +423,15 @@ where
 {
     type T<'tcx> = rustc_ty::Binder<'tcx, T::T<'tcx>>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         rustc_ty::Binder::bind_with_vars(
-            self.value.internal(tables, tcx),
-            tcx.mk_bound_variable_kinds_from_iter(
-                self.bound_vars.iter().map(|bound| bound.internal(tables, tcx)),
+            self.value.internal(tables, cx),
+            cx.mk_bound_variable_kinds_from_iter(
+                self.bound_vars.iter().map(|bound| bound.internal(tables, cx)),
             ),
         )
     }
@@ -341,19 +440,22 @@ where
 impl RustcInternal for BoundVariableKind {
     type T<'tcx> = rustc_ty::BoundVariableKind;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             BoundVariableKind::Ty(kind) => rustc_ty::BoundVariableKind::Ty(match kind {
                 BoundTyKind::Anon => rustc_ty::BoundTyKind::Anon,
-                BoundTyKind::Param(def, symbol) => rustc_ty::BoundTyKind::Param(
-                    def.0.internal(tables, tcx),
-                    Symbol::intern(symbol),
-                ),
+                BoundTyKind::Param(def, symbol) => {
+                    rustc_ty::BoundTyKind::Param(def.0.internal(tables, cx), Symbol::intern(symbol))
+                }
             }),
             BoundVariableKind::Region(kind) => rustc_ty::BoundVariableKind::Region(match kind {
                 BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::Anon,
                 BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::Named(
-                    def.0.internal(tables, tcx),
+                    def.0.internal(tables, cx),
                     Symbol::intern(symbol),
                 ),
                 BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::ClosureEnv,
@@ -366,7 +468,11 @@ impl RustcInternal for BoundVariableKind {
 impl RustcInternal for DynKind {
     type T<'tcx> = rustc_ty::DynKind;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             DynKind::Dyn => rustc_ty::DynKind::Dyn,
         }
@@ -376,16 +482,20 @@ impl RustcInternal for DynKind {
 impl RustcInternal for ExistentialPredicate {
     type T<'tcx> = rustc_ty::ExistentialPredicate<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             ExistentialPredicate::Trait(trait_ref) => {
-                rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables, tcx))
+                rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables, cx))
             }
             ExistentialPredicate::Projection(proj) => {
-                rustc_ty::ExistentialPredicate::Projection(proj.internal(tables, tcx))
+                rustc_ty::ExistentialPredicate::Projection(proj.internal(tables, cx))
             }
             ExistentialPredicate::AutoTrait(trait_def) => {
-                rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables, tcx))
+                rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables, cx))
             }
         }
     }
@@ -394,12 +504,16 @@ impl RustcInternal for ExistentialPredicate {
 impl RustcInternal for ExistentialProjection {
     type T<'tcx> = rustc_ty::ExistentialProjection<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        rustc_ty::ExistentialProjection::new_from_args(
-            tcx,
-            self.def_id.0.internal(tables, tcx),
-            self.generic_args.internal(tables, tcx),
-            self.term.internal(tables, tcx),
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        use rustc_smir::context::SmirExistentialProjection;
+        cx.new_from_args(
+            self.def_id.0.internal(tables, cx),
+            self.generic_args.internal(tables, cx),
+            self.term.internal(tables, cx),
         )
     }
 }
@@ -407,10 +521,14 @@ impl RustcInternal for ExistentialProjection {
 impl RustcInternal for TermKind {
     type T<'tcx> = rustc_ty::Term<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
-            TermKind::Type(ty) => ty.internal(tables, tcx).into(),
-            TermKind::Const(cnst) => cnst.internal(tables, tcx).into(),
+            TermKind::Type(ty) => ty.internal(tables, cx).into(),
+            TermKind::Const(cnst) => cnst.internal(tables, cx).into(),
         }
     }
 }
@@ -418,38 +536,48 @@ impl RustcInternal for TermKind {
 impl RustcInternal for ExistentialTraitRef {
     type T<'tcx> = rustc_ty::ExistentialTraitRef<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        rustc_ty::ExistentialTraitRef::new_from_args(
-            tcx,
-            self.def_id.0.internal(tables, tcx),
-            self.generic_args.internal(tables, tcx),
-        )
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        use rustc_smir::context::SmirExistentialTraitRef;
+        cx.new_from_args(self.def_id.0.internal(tables, cx), self.generic_args.internal(tables, cx))
     }
 }
 
 impl RustcInternal for TraitRef {
     type T<'tcx> = rustc_ty::TraitRef<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        rustc_ty::TraitRef::new_from_args(
-            tcx,
-            self.def_id.0.internal(tables, tcx),
-            self.args().internal(tables, tcx),
-        )
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        use rustc_smir::context::SmirTraitRef;
+        cx.new_from_args(self.def_id.0.internal(tables, cx), self.args().internal(tables, cx))
     }
 }
 
 impl RustcInternal for AllocId {
     type T<'tcx> = rustc_middle::mir::interpret::AllocId;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.lift(tables.alloc_ids[*self]).unwrap()
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.lift(tables.alloc_ids[*self]).unwrap()
     }
 }
 
 impl RustcInternal for ClosureKind {
     type T<'tcx> = rustc_ty::ClosureKind;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             ClosureKind::Fn => rustc_ty::ClosureKind::Fn,
             ClosureKind::FnMut => rustc_ty::ClosureKind::FnMut,
@@ -460,15 +588,23 @@ impl RustcInternal for ClosureKind {
 
 impl RustcInternal for AdtDef {
     type T<'tcx> = rustc_ty::AdtDef<'tcx>;
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.adt_def(self.0.internal(tables, tcx))
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.adt_def(self.0.internal(tables, cx))
     }
 }
 
 impl RustcInternal for Abi {
     type T<'tcx> = rustc_abi::ExternAbi;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match *self {
             Abi::Rust => rustc_abi::ExternAbi::Rust,
             Abi::C { unwind } => rustc_abi::ExternAbi::C { unwind },
@@ -504,7 +640,11 @@ impl RustcInternal for Abi {
 impl RustcInternal for Safety {
     type T<'tcx> = rustc_hir::Safety;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             Safety::Unsafe => rustc_hir::Safety::Unsafe,
             Safety::Safe => rustc_hir::Safety::Safe,
@@ -514,26 +654,38 @@ impl RustcInternal for Safety {
 impl RustcInternal for Span {
     type T<'tcx> = rustc_span::Span;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tables[*self]
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        tables.spans[*self]
     }
 }
 
 impl RustcInternal for Layout {
     type T<'tcx> = rustc_abi::Layout<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        tcx.lift(tables.layouts[*self]).unwrap()
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        cx.lift(tables.layouts[*self]).unwrap()
     }
 }
 
 impl RustcInternal for Place {
     type T<'tcx> = rustc_middle::mir::Place<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         rustc_middle::mir::Place {
             local: rustc_middle::mir::Local::from_usize(self.local),
-            projection: tcx.mk_place_elems(&self.projection.internal(tables, tcx)),
+            projection: cx.mk_place_elems(&self.projection.internal(tables, cx)),
         }
     }
 }
@@ -541,11 +693,15 @@ impl RustcInternal for Place {
 impl RustcInternal for ProjectionElem {
     type T<'tcx> = rustc_middle::mir::PlaceElem<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             ProjectionElem::Deref => rustc_middle::mir::PlaceElem::Deref,
             ProjectionElem::Field(idx, ty) => {
-                rustc_middle::mir::PlaceElem::Field((*idx).into(), ty.internal(tables, tcx))
+                rustc_middle::mir::PlaceElem::Field((*idx).into(), ty.internal(tables, cx))
             }
             ProjectionElem::Index(idx) => rustc_middle::mir::PlaceElem::Index((*idx).into()),
             ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
@@ -559,13 +715,13 @@ impl RustcInternal for ProjectionElem {
                 rustc_middle::mir::PlaceElem::Subslice { from: *from, to: *to, from_end: *from_end }
             }
             ProjectionElem::Downcast(idx) => {
-                rustc_middle::mir::PlaceElem::Downcast(None, idx.internal(tables, tcx))
+                rustc_middle::mir::PlaceElem::Downcast(None, idx.internal(tables, cx))
             }
             ProjectionElem::OpaqueCast(ty) => {
-                rustc_middle::mir::PlaceElem::OpaqueCast(ty.internal(tables, tcx))
+                rustc_middle::mir::PlaceElem::OpaqueCast(ty.internal(tables, cx))
             }
             ProjectionElem::Subtype(ty) => {
-                rustc_middle::mir::PlaceElem::Subtype(ty.internal(tables, tcx))
+                rustc_middle::mir::PlaceElem::Subtype(ty.internal(tables, cx))
             }
         }
     }
@@ -574,7 +730,11 @@ impl RustcInternal for ProjectionElem {
 impl RustcInternal for BinOp {
     type T<'tcx> = rustc_middle::mir::BinOp;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             BinOp::Add => rustc_middle::mir::BinOp::Add,
             BinOp::AddUnchecked => rustc_middle::mir::BinOp::AddUnchecked,
@@ -606,7 +766,11 @@ impl RustcInternal for BinOp {
 impl RustcInternal for UnOp {
     type T<'tcx> = rustc_middle::mir::UnOp;
 
-    fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+    fn internal<'tcx>(
+        &self,
+        _tables: &mut Tables<'_, BridgeTys>,
+        _cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
         match self {
             UnOp::Not => rustc_middle::mir::UnOp::Not,
             UnOp::Neg => rustc_middle::mir::UnOp::Neg,
@@ -621,8 +785,12 @@ where
 {
     type T<'tcx> = T::T<'tcx>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        (*self).internal(tables, tcx)
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        (*self).internal(tables, cx)
     }
 }
 
@@ -632,8 +800,12 @@ where
 {
     type T<'tcx> = Option<T::T<'tcx>>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        self.as_ref().map(|inner| inner.internal(tables, tcx))
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        self.as_ref().map(|inner| inner.internal(tables, cx))
     }
 }
 
@@ -643,7 +815,11 @@ where
 {
     type T<'tcx> = Vec<T::T<'tcx>>;
 
-    fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
-        self.iter().map(|e| e.internal(tables, tcx)).collect()
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx> {
+        self.iter().map(|e| e.internal(tables, cx)).collect()
     }
 }
diff --git a/compiler/rustc_smir/src/stable_mir/convert/mod.rs b/compiler/rustc_smir/src/stable_mir/convert/mod.rs
new file mode 100644
index 00000000000..90ed67ed972
--- /dev/null
+++ b/compiler/rustc_smir/src/stable_mir/convert/mod.rs
@@ -0,0 +1,126 @@
+use std::ops::RangeInclusive;
+
+use rustc_smir::Tables;
+use rustc_smir::context::SmirCtxt;
+
+use super::compiler_interface::BridgeTys;
+use crate::rustc_smir;
+
+mod internal;
+mod stable;
+
+impl<'tcx, T> Stable<'tcx> for &T
+where
+    T: Stable<'tcx>,
+{
+    type T = T::T;
+
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        (*self).stable(tables, cx)
+    }
+}
+
+impl<'tcx, T> Stable<'tcx> for Option<T>
+where
+    T: Stable<'tcx>,
+{
+    type T = Option<T::T>;
+
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        self.as_ref().map(|value| value.stable(tables, cx))
+    }
+}
+
+impl<'tcx, T, E> Stable<'tcx> for Result<T, E>
+where
+    T: Stable<'tcx>,
+    E: Stable<'tcx>,
+{
+    type T = Result<T::T, E::T>;
+
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        match self {
+            Ok(val) => Ok(val.stable(tables, cx)),
+            Err(error) => Err(error.stable(tables, cx)),
+        }
+    }
+}
+
+impl<'tcx, T> Stable<'tcx> for &[T]
+where
+    T: Stable<'tcx>,
+{
+    type T = Vec<T::T>;
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        self.iter().map(|e| e.stable(tables, cx)).collect()
+    }
+}
+
+impl<'tcx, T, U> Stable<'tcx> for (T, U)
+where
+    T: Stable<'tcx>,
+    U: Stable<'tcx>,
+{
+    type T = (T::T, U::T);
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        (self.0.stable(tables, cx), self.1.stable(tables, cx))
+    }
+}
+
+impl<'tcx, T> Stable<'tcx> for RangeInclusive<T>
+where
+    T: Stable<'tcx>,
+{
+    type T = RangeInclusive<T::T>;
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        RangeInclusive::new(self.start().stable(tables, cx), self.end().stable(tables, cx))
+    }
+}
+
+/// Trait used to convert between an internal MIR type to a Stable MIR type.
+pub trait Stable<'tcx> {
+    /// The stable representation of the type implementing Stable.
+    type T;
+    /// Converts an object to the equivalent Stable MIR representation.
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T;
+}
+
+/// Trait used to translate a stable construct to its rustc counterpart.
+///
+/// This is basically a mirror of [Stable].
+pub trait RustcInternal {
+    type T<'tcx>;
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T<'tcx>;
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/stable_mir/convert/stable/abi.rs
index 35d5b7fb89a..b6f02e1bc8f 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/stable_mir/convert/stable/abi.rs
@@ -4,22 +4,25 @@
 
 use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
 use rustc_middle::ty;
+use rustc_smir::context::SmirCtxt;
+use rustc_smir::{IndexedVal, Tables};
 use rustc_target::callconv;
 use stable_mir::abi::{
     AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,
     IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar,
     TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange,
 };
+use stable_mir::compiler_interface::BridgeTys;
+use stable_mir::convert::Stable;
 use stable_mir::opaque;
 use stable_mir::target::MachineSize as Size;
-use stable_mir::ty::{Align, IndexedVal, VariantIdx};
+use stable_mir::ty::{Align, VariantIdx};
 
-use crate::rustc_smir::{Stable, Tables};
-use crate::stable_mir;
+use crate::{rustc_smir, stable_mir};
 
 impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx {
     type T = VariantIdx;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         VariantIdx::to_val(self.as_usize())
     }
 }
@@ -27,7 +30,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx {
 impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
     type T = stable_mir::target::Endian;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             rustc_abi::Endian::Little => stable_mir::target::Endian::Little,
             rustc_abi::Endian::Big => stable_mir::target::Endian::Big,
@@ -38,29 +41,41 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
 impl<'tcx> Stable<'tcx> for rustc_abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
     type T = TyAndLayout;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        TyAndLayout { ty: self.ty.stable(tables), layout: self.layout.stable(tables) }
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        TyAndLayout { ty: self.ty.stable(tables, cx), layout: self.layout.stable(tables, cx) }
     }
 }
 
 impl<'tcx> Stable<'tcx> for rustc_abi::Layout<'tcx> {
     type T = Layout;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        tables.layout_id(tables.tcx.lift(*self).unwrap())
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        tables.layout_id(cx.lift(*self).unwrap())
     }
 }
 
 impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
     type T = LayoutShape;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         LayoutShape {
-            fields: self.fields.stable(tables),
-            variants: self.variants.stable(tables),
-            abi: self.backend_repr.stable(tables),
-            abi_align: self.align.abi.stable(tables),
-            size: self.size.stable(tables),
+            fields: self.fields.stable(tables, cx),
+            variants: self.variants.stable(tables, cx),
+            abi: self.backend_repr.stable(tables, cx),
+            abi_align: self.align.abi.stable(tables, cx),
+            size: self.size.stable(tables, cx),
         }
     }
 }
@@ -68,14 +83,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi
 impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> {
     type T = FnAbi;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         assert!(self.args.len() >= self.fixed_count as usize);
         assert!(!self.c_variadic || matches!(self.conv, CanonAbi::C));
         FnAbi {
-            args: self.args.as_ref().stable(tables),
-            ret: self.ret.stable(tables),
+            args: self.args.as_ref().stable(tables, cx),
+            ret: self.ret.stable(tables, cx),
             fixed_count: self.fixed_count,
-            conv: self.conv.stable(tables),
+            conv: self.conv.stable(tables, cx),
             c_variadic: self.c_variadic,
         }
     }
@@ -84,11 +103,15 @@ impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> {
 impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> {
     type T = ArgAbi;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         ArgAbi {
-            ty: self.layout.ty.stable(tables),
-            layout: self.layout.layout.stable(tables),
-            mode: self.mode.stable(tables),
+            ty: self.layout.ty.stable(tables, cx),
+            layout: self.layout.layout.stable(tables, cx),
+            mode: self.mode.stable(tables, cx),
         }
     }
 }
@@ -96,7 +119,7 @@ impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> {
 impl<'tcx> Stable<'tcx> for CanonAbi {
     type T = CallConvention;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             CanonAbi::C => CallConvention::C,
             CanonAbi::Rust => CallConvention::Rust,
@@ -132,7 +155,7 @@ impl<'tcx> Stable<'tcx> for CanonAbi {
 impl<'tcx> Stable<'tcx> for callconv::PassMode {
     type T = PassMode;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             callconv::PassMode::Ignore => PassMode::Ignore,
             callconv::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)),
@@ -154,15 +177,19 @@ impl<'tcx> Stable<'tcx> for callconv::PassMode {
 impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> {
     type T = FieldsShape;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             rustc_abi::FieldsShape::Primitive => FieldsShape::Primitive,
             rustc_abi::FieldsShape::Union(count) => FieldsShape::Union(*count),
             rustc_abi::FieldsShape::Array { stride, count } => {
-                FieldsShape::Array { stride: stride.stable(tables), count: *count }
+                FieldsShape::Array { stride: stride.stable(tables, cx), count: *count }
             }
             rustc_abi::FieldsShape::Arbitrary { offsets, .. } => {
-                FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables) }
+                FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables, cx) }
             }
         }
     }
@@ -171,18 +198,22 @@ impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> {
 impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
     type T = VariantsShape;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             rustc_abi::Variants::Single { index } => {
-                VariantsShape::Single { index: index.stable(tables) }
+                VariantsShape::Single { index: index.stable(tables, cx) }
             }
             rustc_abi::Variants::Empty => VariantsShape::Empty,
             rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => {
                 VariantsShape::Multiple {
-                    tag: tag.stable(tables),
-                    tag_encoding: tag_encoding.stable(tables),
-                    tag_field: tag_field.stable(tables),
-                    variants: variants.iter().as_slice().stable(tables),
+                    tag: tag.stable(tables, cx),
+                    tag_encoding: tag_encoding.stable(tables, cx),
+                    tag_field: *tag_field,
+                    variants: variants.iter().as_slice().stable(tables, cx),
                 }
             }
         }
@@ -192,13 +223,17 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::
 impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
     type T = TagEncoding;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             rustc_abi::TagEncoding::Direct => TagEncoding::Direct,
             rustc_abi::TagEncoding::Niche { untagged_variant, niche_variants, niche_start } => {
                 TagEncoding::Niche {
-                    untagged_variant: untagged_variant.stable(tables),
-                    niche_variants: niche_variants.stable(tables),
+                    untagged_variant: untagged_variant.stable(tables, cx),
+                    niche_variants: niche_variants.stable(tables, cx),
                     niche_start: *niche_start,
                 }
             }
@@ -209,14 +244,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
 impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
     type T = ValueAbi;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match *self {
-            rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)),
+            rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables, cx)),
             rustc_abi::BackendRepr::ScalarPair(first, second) => {
-                ValueAbi::ScalarPair(first.stable(tables), second.stable(tables))
+                ValueAbi::ScalarPair(first.stable(tables, cx), second.stable(tables, cx))
             }
             rustc_abi::BackendRepr::SimdVector { element, count } => {
-                ValueAbi::Vector { element: element.stable(tables), count }
+                ValueAbi::Vector { element: element.stable(tables, cx), count }
             }
             rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized },
         }
@@ -226,7 +265,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
 impl<'tcx> Stable<'tcx> for rustc_abi::Size {
     type T = Size;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         Size::from_bits(self.bits_usize())
     }
 }
@@ -234,7 +273,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Size {
 impl<'tcx> Stable<'tcx> for rustc_abi::Align {
     type T = Align;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         self.bytes()
     }
 }
@@ -242,13 +281,17 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Align {
 impl<'tcx> Stable<'tcx> for rustc_abi::Scalar {
     type T = Scalar;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             rustc_abi::Scalar::Initialized { value, valid_range } => Scalar::Initialized {
-                value: value.stable(tables),
-                valid_range: valid_range.stable(tables),
+                value: value.stable(tables, cx),
+                valid_range: valid_range.stable(tables, cx),
             },
-            rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables) },
+            rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables, cx) },
         }
     }
 }
@@ -256,15 +299,19 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Scalar {
 impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
     type T = Primitive;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             rustc_abi::Primitive::Int(length, signed) => {
-                Primitive::Int { length: length.stable(tables), signed: *signed }
+                Primitive::Int { length: length.stable(tables, cx), signed: *signed }
             }
             rustc_abi::Primitive::Float(length) => {
-                Primitive::Float { length: length.stable(tables) }
+                Primitive::Float { length: length.stable(tables, cx) }
             }
-            rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables)),
+            rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables, cx)),
         }
     }
 }
@@ -272,7 +319,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
 impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace {
     type T = AddressSpace;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         AddressSpace(self.0)
     }
 }
@@ -280,7 +327,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace {
 impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
     type T = IntegerLength;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             rustc_abi::Integer::I8 => IntegerLength::I8,
             rustc_abi::Integer::I16 => IntegerLength::I16,
@@ -294,7 +341,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
 impl<'tcx> Stable<'tcx> for rustc_abi::Float {
     type T = FloatLength;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             rustc_abi::Float::F16 => FloatLength::F16,
             rustc_abi::Float::F32 => FloatLength::F32,
@@ -307,7 +354,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Float {
 impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
     type T = WrappingRange;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         WrappingRange { start: self.start, end: self.end }
     }
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/stable_mir/convert/stable/mir.rs
index daea4acc36c..f5ea17d1e55 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/stable_mir/convert/stable/mir.rs
@@ -1,56 +1,66 @@
 //! Conversion of internal Rust compiler `mir` items to stable ones.
 
-use rustc_middle::mir::interpret::alloc_range;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::{bug, mir};
+use rustc_smir::context::SmirCtxt;
+use rustc_smir::{SmirError, Tables};
+use stable_mir::compiler_interface::BridgeTys;
+use stable_mir::convert::Stable;
 use stable_mir::mir::alloc::GlobalAlloc;
 use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment};
 use stable_mir::ty::{Allocation, ConstantKind, MirConst};
-use stable_mir::{Error, opaque};
+use stable_mir::{Error, alloc, opaque};
 
-use crate::rustc_smir::{Stable, Tables, alloc};
-use crate::stable_mir;
+use crate::{rustc_smir, stable_mir};
 
 impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
     type T = stable_mir::mir::Body;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         stable_mir::mir::Body::new(
             self.basic_blocks
                 .iter()
                 .map(|block| stable_mir::mir::BasicBlock {
-                    terminator: block.terminator().stable(tables),
+                    terminator: block.terminator().stable(tables, cx),
                     statements: block
                         .statements
                         .iter()
-                        .map(|statement| statement.stable(tables))
+                        .map(|statement| statement.stable(tables, cx))
                         .collect(),
                 })
                 .collect(),
             self.local_decls
                 .iter()
                 .map(|decl| stable_mir::mir::LocalDecl {
-                    ty: decl.ty.stable(tables),
-                    span: decl.source_info.span.stable(tables),
-                    mutability: decl.mutability.stable(tables),
+                    ty: decl.ty.stable(tables, cx),
+                    span: decl.source_info.span.stable(tables, cx),
+                    mutability: decl.mutability.stable(tables, cx),
                 })
                 .collect(),
             self.arg_count,
-            self.var_debug_info.iter().map(|info| info.stable(tables)).collect(),
-            self.spread_arg.stable(tables),
-            self.span.stable(tables),
+            self.var_debug_info.iter().map(|info| info.stable(tables, cx)).collect(),
+            self.spread_arg.stable(tables, cx),
+            self.span.stable(tables, cx),
         )
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
     type T = stable_mir::mir::VarDebugInfo;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         stable_mir::mir::VarDebugInfo {
             name: self.name.to_string(),
-            source_info: self.source_info.stable(tables),
-            composite: self.composite.as_ref().map(|composite| composite.stable(tables)),
-            value: self.value.stable(tables),
+            source_info: self.source_info.stable(tables, cx),
+            composite: self.composite.as_ref().map(|composite| composite.stable(tables, cx)),
+            value: self.value.stable(tables, cx),
             argument_index: self.argument_index,
         }
     }
@@ -58,40 +68,59 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
 
 impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
     type T = stable_mir::mir::Statement;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        Statement {
+            kind: self.kind.stable(tables, cx),
+            span: self.source_info.span.stable(tables, cx),
+        }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::SourceInfo {
     type T = stable_mir::mir::SourceInfo;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        stable_mir::mir::SourceInfo { span: self.span.stable(tables), scope: self.scope.into() }
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        stable_mir::mir::SourceInfo { span: self.span.stable(tables, cx), scope: self.scope.into() }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
     type T = stable_mir::mir::VarDebugInfoFragment;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         VarDebugInfoFragment {
-            ty: self.ty.stable(tables),
-            projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
+            ty: self.ty.stable(tables, cx),
+            projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(),
         }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
     type T = stable_mir::mir::VarDebugInfoContents;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             mir::VarDebugInfoContents::Place(place) => {
-                stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables))
+                stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables, cx))
             }
             mir::VarDebugInfoContents::Const(const_operand) => {
                 let op = ConstOperand {
-                    span: const_operand.span.stable(tables),
+                    span: const_operand.span.stable(tables, cx),
                     user_ty: const_operand.user_ty.map(|index| index.as_usize()),
-                    const_: const_operand.const_.stable(tables),
+                    const_: const_operand.const_.stable(tables, cx),
                 };
                 stable_mir::mir::VarDebugInfoContents::Const(op)
             }
@@ -101,53 +130,58 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
 
 impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
     type T = stable_mir::mir::StatementKind;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign(
-                assign.0.stable(tables),
-                assign.1.stable(tables),
+                assign.0.stable(tables, cx),
+                assign.1.stable(tables, cx),
             ),
             mir::StatementKind::FakeRead(fake_read_place) => {
                 stable_mir::mir::StatementKind::FakeRead(
-                    fake_read_place.0.stable(tables),
-                    fake_read_place.1.stable(tables),
+                    fake_read_place.0.stable(tables, cx),
+                    fake_read_place.1.stable(tables, cx),
                 )
             }
             mir::StatementKind::SetDiscriminant { place, variant_index } => {
                 stable_mir::mir::StatementKind::SetDiscriminant {
-                    place: place.as_ref().stable(tables),
-                    variant_index: variant_index.stable(tables),
+                    place: place.as_ref().stable(tables, cx),
+                    variant_index: variant_index.stable(tables, cx),
                 }
             }
             mir::StatementKind::Deinit(place) => {
-                stable_mir::mir::StatementKind::Deinit(place.stable(tables))
+                stable_mir::mir::StatementKind::Deinit(place.stable(tables, cx))
             }
 
             mir::StatementKind::StorageLive(place) => {
-                stable_mir::mir::StatementKind::StorageLive(place.stable(tables))
+                stable_mir::mir::StatementKind::StorageLive(place.stable(tables, cx))
             }
 
             mir::StatementKind::StorageDead(place) => {
-                stable_mir::mir::StatementKind::StorageDead(place.stable(tables))
-            }
-            mir::StatementKind::Retag(retag, place) => {
-                stable_mir::mir::StatementKind::Retag(retag.stable(tables), place.stable(tables))
+                stable_mir::mir::StatementKind::StorageDead(place.stable(tables, cx))
             }
+            mir::StatementKind::Retag(retag, place) => stable_mir::mir::StatementKind::Retag(
+                retag.stable(tables, cx),
+                place.stable(tables, cx),
+            ),
             mir::StatementKind::PlaceMention(place) => {
-                stable_mir::mir::StatementKind::PlaceMention(place.stable(tables))
+                stable_mir::mir::StatementKind::PlaceMention(place.stable(tables, cx))
             }
             mir::StatementKind::AscribeUserType(place_projection, variance) => {
                 stable_mir::mir::StatementKind::AscribeUserType {
-                    place: place_projection.as_ref().0.stable(tables),
-                    projections: place_projection.as_ref().1.stable(tables),
-                    variance: variance.stable(tables),
+                    place: place_projection.as_ref().0.stable(tables, cx),
+                    projections: place_projection.as_ref().1.stable(tables, cx),
+                    variance: variance.stable(tables, cx),
                 }
             }
             mir::StatementKind::Coverage(coverage) => {
                 stable_mir::mir::StatementKind::Coverage(opaque(coverage))
             }
             mir::StatementKind::Intrinsic(intrinstic) => {
-                stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables))
+                stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables, cx))
             }
             mir::StatementKind::ConstEvalCounter => {
                 stable_mir::mir::StatementKind::ConstEvalCounter
@@ -163,61 +197,68 @@ impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
 
 impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
     type T = stable_mir::mir::Rvalue;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::Rvalue::*;
         match self {
-            Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
+            Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables, cx)),
             Repeat(op, len) => {
-                let len = len.stable(tables);
-                stable_mir::mir::Rvalue::Repeat(op.stable(tables), len)
+                let len = len.stable(tables, cx);
+                stable_mir::mir::Rvalue::Repeat(op.stable(tables, cx), len)
             }
             Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
-                region.stable(tables),
-                kind.stable(tables),
-                place.stable(tables),
+                region.stable(tables, cx),
+                kind.stable(tables, cx),
+                place.stable(tables, cx),
             ),
             ThreadLocalRef(def_id) => {
                 stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id))
             }
-            RawPtr(mutability, place) => {
-                stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables))
-            }
-            Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)),
+            RawPtr(mutability, place) => stable_mir::mir::Rvalue::AddressOf(
+                mutability.stable(tables, cx),
+                place.stable(tables, cx),
+            ),
+            Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables, cx)),
             Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast(
-                cast_kind.stable(tables),
-                op.stable(tables),
-                ty.stable(tables),
+                cast_kind.stable(tables, cx),
+                op.stable(tables, cx),
+                ty.stable(tables, cx),
             ),
             BinaryOp(bin_op, ops) => {
                 if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
                     stable_mir::mir::Rvalue::CheckedBinaryOp(
-                        bin_op.stable(tables),
-                        ops.0.stable(tables),
-                        ops.1.stable(tables),
+                        bin_op.stable(tables, cx),
+                        ops.0.stable(tables, cx),
+                        ops.1.stable(tables, cx),
                     )
                 } else {
                     stable_mir::mir::Rvalue::BinaryOp(
-                        bin_op.stable(tables),
-                        ops.0.stable(tables),
-                        ops.1.stable(tables),
+                        bin_op.stable(tables, cx),
+                        ops.0.stable(tables, cx),
+                        ops.1.stable(tables, cx),
                     )
                 }
             }
-            NullaryOp(null_op, ty) => {
-                stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), ty.stable(tables))
-            }
+            NullaryOp(null_op, ty) => stable_mir::mir::Rvalue::NullaryOp(
+                null_op.stable(tables, cx),
+                ty.stable(tables, cx),
+            ),
             UnaryOp(un_op, op) => {
-                stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables))
+                stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables, cx), op.stable(tables, cx))
             }
-            Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables)),
+            Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables, cx)),
             Aggregate(agg_kind, operands) => {
-                let operands = operands.iter().map(|op| op.stable(tables)).collect();
-                stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables), operands)
+                let operands = operands.iter().map(|op| op.stable(tables, cx)).collect();
+                stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), operands)
             }
-            ShallowInitBox(op, ty) => {
-                stable_mir::mir::Rvalue::ShallowInitBox(op.stable(tables), ty.stable(tables))
-            }
-            CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables)),
+            ShallowInitBox(op, ty) => stable_mir::mir::Rvalue::ShallowInitBox(
+                op.stable(tables, cx),
+                ty.stable(tables, cx),
+            ),
+            CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables, cx)),
             WrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"),
         }
     }
@@ -225,7 +266,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
 
 impl<'tcx> Stable<'tcx> for mir::Mutability {
     type T = stable_mir::mir::Mutability;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_hir::Mutability::*;
         match *self {
             Not => stable_mir::mir::Mutability::Not,
@@ -236,7 +277,7 @@ impl<'tcx> Stable<'tcx> for mir::Mutability {
 
 impl<'tcx> Stable<'tcx> for mir::RawPtrKind {
     type T = stable_mir::mir::RawPtrKind;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use mir::RawPtrKind::*;
         match *self {
             Const => stable_mir::mir::RawPtrKind::Const,
@@ -248,19 +289,23 @@ impl<'tcx> Stable<'tcx> for mir::RawPtrKind {
 
 impl<'tcx> Stable<'tcx> for mir::BorrowKind {
     type T = stable_mir::mir::BorrowKind;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::BorrowKind::*;
         match *self {
             Shared => stable_mir::mir::BorrowKind::Shared,
-            Fake(kind) => stable_mir::mir::BorrowKind::Fake(kind.stable(tables)),
-            Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
+            Fake(kind) => stable_mir::mir::BorrowKind::Fake(kind.stable(tables, cx)),
+            Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables, cx) },
         }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
     type T = stable_mir::mir::MutBorrowKind;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::mir::MutBorrowKind::*;
         match *self {
             Default => stable_mir::mir::MutBorrowKind::Default,
@@ -272,7 +317,7 @@ impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
 
 impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind {
     type T = stable_mir::mir::FakeBorrowKind;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::mir::FakeBorrowKind::*;
         match *self {
             Deep => stable_mir::mir::FakeBorrowKind::Deep,
@@ -283,13 +328,17 @@ impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind {
 
 impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
     type T = stable_mir::mir::NullOp;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::NullOp::*;
         match self {
             SizeOf => stable_mir::mir::NullOp::SizeOf,
             AlignOf => stable_mir::mir::NullOp::AlignOf,
             OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf(
-                indices.iter().map(|idx| idx.stable(tables)).collect(),
+                indices.iter().map(|idx| idx.stable(tables, cx)).collect(),
             ),
             UbChecks => stable_mir::mir::NullOp::UbChecks,
             ContractChecks => stable_mir::mir::NullOp::ContractChecks,
@@ -299,12 +348,16 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
 
 impl<'tcx> Stable<'tcx> for mir::CastKind {
     type T = stable_mir::mir::CastKind;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::CastKind::*;
         match self {
             PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress,
             PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance,
-            PointerCoercion(c, _) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
+            PointerCoercion(c, _) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables, cx)),
             IntToInt => stable_mir::mir::CastKind::IntToInt,
             FloatToInt => stable_mir::mir::CastKind::FloatToInt,
             FloatToFloat => stable_mir::mir::CastKind::FloatToFloat,
@@ -318,7 +371,7 @@ impl<'tcx> Stable<'tcx> for mir::CastKind {
 
 impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
     type T = stable_mir::mir::FakeReadCause;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::mir::FakeReadCause::*;
         match self {
             ForMatchGuard => stable_mir::mir::FakeReadCause::ForMatchGuard,
@@ -334,12 +387,16 @@ impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
 
 impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
     type T = stable_mir::mir::Operand;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::Operand::*;
         match self {
-            Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)),
-            Move(place) => stable_mir::mir::Operand::Move(place.stable(tables)),
-            Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables)),
+            Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables, cx)),
+            Move(place) => stable_mir::mir::Operand::Move(place.stable(tables, cx)),
+            Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables, cx)),
         }
     }
 }
@@ -347,35 +404,48 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
 impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
     type T = stable_mir::mir::ConstOperand;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         stable_mir::mir::ConstOperand {
-            span: self.span.stable(tables),
+            span: self.span.stable(tables, cx),
             user_ty: self.user_ty.map(|u| u.as_usize()).or(None),
-            const_: self.const_.stable(tables),
+            const_: self.const_.stable(tables, cx),
         }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
     type T = stable_mir::mir::Place;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         stable_mir::mir::Place {
             local: self.local.as_usize(),
-            projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
+            projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(),
         }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
     type T = stable_mir::mir::ProjectionElem;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::ProjectionElem::*;
         match self {
             Deref => stable_mir::mir::ProjectionElem::Deref,
-            Field(idx, ty) => {
-                stable_mir::mir::ProjectionElem::Field(idx.stable(tables), ty.stable(tables))
-            }
-            Index(local) => stable_mir::mir::ProjectionElem::Index(local.stable(tables)),
+            Field(idx, ty) => stable_mir::mir::ProjectionElem::Field(
+                idx.stable(tables, cx),
+                ty.stable(tables, cx),
+            ),
+            Index(local) => stable_mir::mir::ProjectionElem::Index(local.stable(tables, cx)),
             ConstantIndex { offset, min_length, from_end } => {
                 stable_mir::mir::ProjectionElem::ConstantIndex {
                     offset: *offset,
@@ -393,9 +463,9 @@ impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
             // via a lookup using the `VariantIdx`. The `Option<Symbol>` argument is therefore
             // dropped when converting to Stable MIR. A brief justification for this decision can be
             // found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486
-            Downcast(_, idx) => stable_mir::mir::ProjectionElem::Downcast(idx.stable(tables)),
-            OpaqueCast(ty) => stable_mir::mir::ProjectionElem::OpaqueCast(ty.stable(tables)),
-            Subtype(ty) => stable_mir::mir::ProjectionElem::Subtype(ty.stable(tables)),
+            Downcast(_, idx) => stable_mir::mir::ProjectionElem::Downcast(idx.stable(tables, cx)),
+            OpaqueCast(ty) => stable_mir::mir::ProjectionElem::OpaqueCast(ty.stable(tables, cx)),
+            Subtype(ty) => stable_mir::mir::ProjectionElem::Subtype(ty.stable(tables, cx)),
             UnwrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"),
         }
     }
@@ -404,21 +474,21 @@ impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
 impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
     type T = stable_mir::mir::UserTypeProjection;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::Local {
     type T = stable_mir::mir::Local;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         self.as_usize()
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::RetagKind {
     type T = stable_mir::mir::RetagKind;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::mir::RetagKind;
         match self {
             RetagKind::FnEntry => stable_mir::mir::RetagKind::FnEntry,
@@ -431,7 +501,7 @@ impl<'tcx> Stable<'tcx> for mir::RetagKind {
 
 impl<'tcx> Stable<'tcx> for mir::UnwindAction {
     type T = stable_mir::mir::UnwindAction;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::mir::UnwindAction;
         match self {
             UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
@@ -445,18 +515,22 @@ impl<'tcx> Stable<'tcx> for mir::UnwindAction {
 impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
     type T = stable_mir::mir::NonDivergingIntrinsic;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::NonDivergingIntrinsic;
         use stable_mir::mir::CopyNonOverlapping;
         match self {
             NonDivergingIntrinsic::Assume(op) => {
-                stable_mir::mir::NonDivergingIntrinsic::Assume(op.stable(tables))
+                stable_mir::mir::NonDivergingIntrinsic::Assume(op.stable(tables, cx))
             }
             NonDivergingIntrinsic::CopyNonOverlapping(copy_non_overlapping) => {
                 stable_mir::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
-                    src: copy_non_overlapping.src.stable(tables),
-                    dst: copy_non_overlapping.dst.stable(tables),
-                    count: copy_non_overlapping.count.stable(tables),
+                    src: copy_non_overlapping.src.stable(tables, cx),
+                    dst: copy_non_overlapping.dst.stable(tables, cx),
+                    count: copy_non_overlapping.count.stable(tables, cx),
                 })
             }
         }
@@ -465,47 +539,51 @@ impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
 
 impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
     type T = stable_mir::mir::AssertMessage;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::AssertKind;
         match self {
             AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
-                len: len.stable(tables),
-                index: index.stable(tables),
+                len: len.stable(tables, cx),
+                index: index.stable(tables, cx),
             },
             AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
-                bin_op.stable(tables),
-                op1.stable(tables),
-                op2.stable(tables),
+                bin_op.stable(tables, cx),
+                op1.stable(tables, cx),
+                op2.stable(tables, cx),
             ),
             AssertKind::OverflowNeg(op) => {
-                stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables))
+                stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables, cx))
             }
             AssertKind::DivisionByZero(op) => {
-                stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables))
+                stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables, cx))
             }
             AssertKind::RemainderByZero(op) => {
-                stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
+                stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables, cx))
             }
             AssertKind::ResumedAfterReturn(coroutine) => {
-                stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables))
+                stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables, cx))
             }
             AssertKind::ResumedAfterPanic(coroutine) => {
-                stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables))
+                stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables, cx))
             }
             AssertKind::ResumedAfterDrop(coroutine) => {
-                stable_mir::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables))
+                stable_mir::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables, cx))
             }
             AssertKind::MisalignedPointerDereference { required, found } => {
                 stable_mir::mir::AssertMessage::MisalignedPointerDereference {
-                    required: required.stable(tables),
-                    found: found.stable(tables),
+                    required: required.stable(tables, cx),
+                    found: found.stable(tables, cx),
                 }
             }
             AssertKind::NullPointerDereference => {
                 stable_mir::mir::AssertMessage::NullPointerDereference
             }
             AssertKind::InvalidEnumConstruction(source) => {
-                stable_mir::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables))
+                stable_mir::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx))
             }
         }
     }
@@ -513,7 +591,7 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
 
 impl<'tcx> Stable<'tcx> for mir::BinOp {
     type T = stable_mir::mir::BinOp;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::mir::BinOp;
         match self {
             BinOp::Add => stable_mir::mir::BinOp::Add,
@@ -548,7 +626,7 @@ impl<'tcx> Stable<'tcx> for mir::BinOp {
 
 impl<'tcx> Stable<'tcx> for mir::UnOp {
     type T = stable_mir::mir::UnOp;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::mir::UnOp;
         match self {
             UnOp::Not => stable_mir::mir::UnOp::Not,
@@ -560,17 +638,21 @@ impl<'tcx> Stable<'tcx> for mir::UnOp {
 
 impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
     type T = stable_mir::mir::AggregateKind;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             mir::AggregateKind::Array(ty) => {
-                stable_mir::mir::AggregateKind::Array(ty.stable(tables))
+                stable_mir::mir::AggregateKind::Array(ty.stable(tables, cx))
             }
             mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple,
             mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => {
                 stable_mir::mir::AggregateKind::Adt(
                     tables.adt_def(*def_id),
-                    var_idx.stable(tables),
-                    generic_arg.stable(tables),
+                    var_idx.stable(tables, cx),
+                    generic_arg.stable(tables, cx),
                     user_ty_index.map(|idx| idx.index()),
                     field_idx.map(|idx| idx.index()),
                 )
@@ -578,39 +660,46 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
             mir::AggregateKind::Closure(def_id, generic_arg) => {
                 stable_mir::mir::AggregateKind::Closure(
                     tables.closure_def(*def_id),
-                    generic_arg.stable(tables),
+                    generic_arg.stable(tables, cx),
                 )
             }
             mir::AggregateKind::Coroutine(def_id, generic_arg) => {
                 stable_mir::mir::AggregateKind::Coroutine(
                     tables.coroutine_def(*def_id),
-                    generic_arg.stable(tables),
-                    tables.tcx.coroutine_movability(*def_id).stable(tables),
+                    generic_arg.stable(tables, cx),
+                    cx.coroutine_movability(*def_id).stable(tables, cx),
                 )
             }
             mir::AggregateKind::CoroutineClosure(def_id, generic_args) => {
                 stable_mir::mir::AggregateKind::CoroutineClosure(
                     tables.coroutine_closure_def(*def_id),
-                    generic_args.stable(tables),
+                    generic_args.stable(tables, cx),
                 )
             }
-            mir::AggregateKind::RawPtr(ty, mutability) => {
-                stable_mir::mir::AggregateKind::RawPtr(ty.stable(tables), mutability.stable(tables))
-            }
+            mir::AggregateKind::RawPtr(ty, mutability) => stable_mir::mir::AggregateKind::RawPtr(
+                ty.stable(tables, cx),
+                mutability.stable(tables, cx),
+            ),
         }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
     type T = stable_mir::mir::InlineAsmOperand;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::mir::InlineAsmOperand;
 
         let (in_value, out_place) = match self {
-            InlineAsmOperand::In { value, .. } => (Some(value.stable(tables)), None),
-            InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable(tables))),
+            InlineAsmOperand::In { value, .. } => (Some(value.stable(tables, cx)), None),
+            InlineAsmOperand::Out { place, .. } => {
+                (None, place.map(|place| place.stable(tables, cx)))
+            }
             InlineAsmOperand::InOut { in_value, out_place, .. } => {
-                (Some(in_value.stable(tables)), out_place.map(|place| place.stable(tables)))
+                (Some(in_value.stable(tables, cx)), out_place.map(|place| place.stable(tables, cx)))
             }
             InlineAsmOperand::Const { .. }
             | InlineAsmOperand::SymFn { .. }
@@ -624,22 +713,33 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
 
 impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
     type T = stable_mir::mir::Terminator;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::mir::Terminator;
-        Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
+        Terminator {
+            kind: self.kind.stable(tables, cx),
+            span: self.source_info.span.stable(tables, cx),
+        }
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
     type T = stable_mir::mir::TerminatorKind;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::mir::TerminatorKind;
         match self {
             mir::TerminatorKind::Goto { target } => {
                 TerminatorKind::Goto { target: target.as_usize() }
             }
             mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
-                discr: discr.stable(tables),
+                discr: discr.stable(tables, cx),
                 targets: {
                     let branches = targets.iter().map(|(val, target)| (val, target.as_usize()));
                     stable_mir::mir::SwitchTargets::new(
@@ -660,9 +760,9 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
                 drop: _,
                 async_fut: _,
             } => TerminatorKind::Drop {
-                place: place.stable(tables),
+                place: place.stable(tables, cx),
                 target: target.as_usize(),
-                unwind: unwind.stable(tables),
+                unwind: unwind.stable(tables, cx),
             },
             mir::TerminatorKind::Call {
                 func,
@@ -673,20 +773,20 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
                 call_source: _,
                 fn_span: _,
             } => TerminatorKind::Call {
-                func: func.stable(tables),
-                args: args.iter().map(|arg| arg.node.stable(tables)).collect(),
-                destination: destination.stable(tables),
+                func: func.stable(tables, cx),
+                args: args.iter().map(|arg| arg.node.stable(tables, cx)).collect(),
+                destination: destination.stable(tables, cx),
                 target: target.map(|t| t.as_usize()),
-                unwind: unwind.stable(tables),
+                unwind: unwind.stable(tables, cx),
             },
             mir::TerminatorKind::TailCall { func: _, args: _, fn_span: _ } => todo!(),
             mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => {
                 TerminatorKind::Assert {
-                    cond: cond.stable(tables),
+                    cond: cond.stable(tables, cx),
                     expected: *expected,
-                    msg: msg.stable(tables),
+                    msg: msg.stable(tables, cx),
                     target: target.as_usize(),
-                    unwind: unwind.stable(tables),
+                    unwind: unwind.stable(tables, cx),
                 }
             }
             mir::TerminatorKind::InlineAsm {
@@ -699,12 +799,12 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
                 unwind,
             } => TerminatorKind::InlineAsm {
                 template: format!("{template:?}"),
-                operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
+                operands: operands.iter().map(|operand| operand.stable(tables, cx)).collect(),
                 options: format!("{options:?}"),
                 line_spans: format!("{line_spans:?}"),
                 // FIXME: Figure out how to do labels in SMIR
                 destination: targets.first().map(|d| d.as_usize()),
-                unwind: unwind.stable(tables),
+                unwind: unwind.stable(tables, cx),
             },
             mir::TerminatorKind::Yield { .. }
             | mir::TerminatorKind::CoroutineDrop
@@ -717,22 +817,40 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
 impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
     type T = Allocation;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        self.inner().stable(tables)
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        self.inner().stable(tables, cx)
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
     type T = stable_mir::ty::Allocation;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        alloc::allocation_filter(self, alloc_range(rustc_abi::Size::ZERO, self.size()), tables)
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        use rustc_smir::context::SmirAllocRange;
+        alloc::allocation_filter(
+            self,
+            cx.alloc_range(rustc_abi::Size::ZERO, self.size()),
+            tables,
+            cx,
+        )
     }
 }
 
 impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
     type T = stable_mir::mir::alloc::AllocId;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        _: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         tables.create_alloc_id(*self)
     }
 }
@@ -740,19 +858,25 @@ impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
 impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
     type T = GlobalAlloc;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             mir::interpret::GlobalAlloc::Function { instance, .. } => {
-                GlobalAlloc::Function(instance.stable(tables))
+                GlobalAlloc::Function(instance.stable(tables, cx))
             }
             mir::interpret::GlobalAlloc::VTable(ty, dyn_ty) => {
                 // FIXME: Should we record the whole vtable?
-                GlobalAlloc::VTable(ty.stable(tables), dyn_ty.principal().stable(tables))
+                GlobalAlloc::VTable(ty.stable(tables, cx), dyn_ty.principal().stable(tables, cx))
             }
             mir::interpret::GlobalAlloc::Static(def) => {
                 GlobalAlloc::Static(tables.static_def(*def))
             }
-            mir::interpret::GlobalAlloc::Memory(alloc) => GlobalAlloc::Memory(alloc.stable(tables)),
+            mir::interpret::GlobalAlloc::Memory(alloc) => {
+                GlobalAlloc::Memory(alloc.stable(tables, cx))
+            }
         }
     }
 }
@@ -760,33 +884,37 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
 impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
     type T = stable_mir::ty::MirConst;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap());
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        let id = tables.intern_mir_const(cx.lift(*self).unwrap());
         match *self {
             mir::Const::Ty(ty, c) => MirConst::new(
-                stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
-                ty.stable(tables),
+                stable_mir::ty::ConstantKind::Ty(c.stable(tables, cx)),
+                ty.stable(tables, cx),
                 id,
             ),
             mir::Const::Unevaluated(unev_const, ty) => {
                 let kind =
                     stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
                         def: tables.const_def(unev_const.def),
-                        args: unev_const.args.stable(tables),
+                        args: unev_const.args.stable(tables, cx),
                         promoted: unev_const.promoted.map(|u| u.as_u32()),
                     });
-                let ty = ty.stable(tables);
+                let ty = ty.stable(tables, cx);
                 MirConst::new(kind, ty, id)
             }
             mir::Const::Val(mir::ConstValue::ZeroSized, ty) => {
-                let ty = ty.stable(tables);
+                let ty = ty.stable(tables, cx);
                 MirConst::new(ConstantKind::ZeroSized, ty, id)
             }
             mir::Const::Val(val, ty) => {
-                let ty = tables.tcx.lift(ty).unwrap();
-                let val = tables.tcx.lift(val).unwrap();
-                let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables));
-                let ty = ty.stable(tables);
+                let ty = cx.lift(ty).unwrap();
+                let val = cx.lift(val).unwrap();
+                let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables, cx));
+                let ty = ty.stable(tables, cx);
                 MirConst::new(kind, ty, id)
             }
         }
@@ -796,7 +924,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
 impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
     type T = Error;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         Error::new(format!("{self:?}"))
     }
 }
@@ -804,10 +932,14 @@ impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
 impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
     type T = stable_mir::mir::mono::MonoItem;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::mir::mono::MonoItem as StableMonoItem;
         match self {
-            MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)),
+            MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables, cx)),
             MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)),
             MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)),
         }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/stable_mir/convert/stable/mod.rs
index 3494de62d83..1cead1c3c37 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/convert/stable/mod.rs
@@ -1,18 +1,20 @@
 //! Conversion of internal Rust compiler items to stable ones.
 
 use rustc_abi::FieldIdx;
+use rustc_smir::Tables;
+use rustc_smir::context::SmirCtxt;
+use stable_mir::compiler_interface::BridgeTys;
 
-use crate::rustc_smir::{Stable, Tables};
-use crate::stable_mir;
+use super::Stable;
+use crate::{rustc_smir, stable_mir};
 
 mod abi;
-mod error;
 mod mir;
 mod ty;
 
 impl<'tcx> Stable<'tcx> for rustc_hir::Safety {
     type T = stable_mir::mir::Safety;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             rustc_hir::Safety::Unsafe => stable_mir::mir::Safety::Unsafe,
             rustc_hir::Safety::Safe => stable_mir::mir::Safety::Safe,
@@ -22,14 +24,14 @@ impl<'tcx> Stable<'tcx> for rustc_hir::Safety {
 
 impl<'tcx> Stable<'tcx> for FieldIdx {
     type T = usize;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         self.as_usize()
     }
 }
 
 impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
     type T = stable_mir::mir::CoroutineSource;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_hir::CoroutineSource;
         match self {
             CoroutineSource::Block => stable_mir::mir::CoroutineSource::Block,
@@ -41,28 +43,32 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
 
 impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
     type T = stable_mir::mir::CoroutineKind;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_hir::{CoroutineDesugaring, CoroutineKind};
         match *self {
             CoroutineKind::Desugared(CoroutineDesugaring::Async, source) => {
                 stable_mir::mir::CoroutineKind::Desugared(
                     stable_mir::mir::CoroutineDesugaring::Async,
-                    source.stable(tables),
+                    source.stable(tables, cx),
                 )
             }
             CoroutineKind::Desugared(CoroutineDesugaring::Gen, source) => {
                 stable_mir::mir::CoroutineKind::Desugared(
                     stable_mir::mir::CoroutineDesugaring::Gen,
-                    source.stable(tables),
+                    source.stable(tables, cx),
                 )
             }
             CoroutineKind::Coroutine(movability) => {
-                stable_mir::mir::CoroutineKind::Coroutine(movability.stable(tables))
+                stable_mir::mir::CoroutineKind::Coroutine(movability.stable(tables, cx))
             }
             CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, source) => {
                 stable_mir::mir::CoroutineKind::Desugared(
                     stable_mir::mir::CoroutineDesugaring::AsyncGen,
-                    source.stable(tables),
+                    source.stable(tables, cx),
                 )
             }
         }
@@ -72,7 +78,7 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
 impl<'tcx> Stable<'tcx> for rustc_span::Symbol {
     type T = stable_mir::Symbol;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         self.to_string()
     }
 }
@@ -80,7 +86,11 @@ impl<'tcx> Stable<'tcx> for rustc_span::Symbol {
 impl<'tcx> Stable<'tcx> for rustc_span::Span {
     type T = stable_mir::ty::Span;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        _: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         tables.create_span(*self)
     }
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/stable_mir/convert/stable/ty.rs
index ff0b8e833dc..d84bc119ecc 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/convert/stable/ty.rs
@@ -2,16 +2,20 @@
 
 use rustc_middle::ty::Ty;
 use rustc_middle::{mir, ty};
+use rustc_smir::Tables;
+use rustc_smir::context::SmirCtxt;
+use stable_mir::alloc;
+use stable_mir::compiler_interface::BridgeTys;
+use stable_mir::convert::Stable;
 use stable_mir::ty::{
     AdtKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, TyKind, UintTy,
 };
 
-use crate::rustc_smir::{Stable, Tables, alloc};
-use crate::stable_mir;
+use crate::{rustc_smir, stable_mir};
 
 impl<'tcx> Stable<'tcx> for ty::AliasTyKind {
     type T = stable_mir::ty::AliasKind;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             ty::Projection => stable_mir::ty::AliasKind::Projection,
             ty::Inherent => stable_mir::ty::AliasKind::Inherent,
@@ -23,24 +27,35 @@ impl<'tcx> Stable<'tcx> for ty::AliasTyKind {
 
 impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
     type T = stable_mir::ty::AliasTy;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::AliasTy { args, def_id, .. } = self;
-        stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables) }
+        stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables, cx) }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::AliasTerm<'tcx> {
     type T = stable_mir::ty::AliasTerm;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::AliasTerm { args, def_id, .. } = self;
-        stable_mir::ty::AliasTerm { def_id: tables.alias_def(*def_id), args: args.stable(tables) }
+        stable_mir::ty::AliasTerm {
+            def_id: tables.alias_def(*def_id),
+            args: args.stable(tables, cx),
+        }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::DynKind {
     type T = stable_mir::ty::DynKind;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             ty::Dyn => stable_mir::ty::DynKind::Dyn,
         }
@@ -50,14 +65,18 @@ impl<'tcx> Stable<'tcx> for ty::DynKind {
 impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
     type T = stable_mir::ty::ExistentialPredicate;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::ExistentialPredicate::*;
         match self {
             ty::ExistentialPredicate::Trait(existential_trait_ref) => {
-                Trait(existential_trait_ref.stable(tables))
+                Trait(existential_trait_ref.stable(tables, cx))
             }
             ty::ExistentialPredicate::Projection(existential_projection) => {
-                Projection(existential_projection.stable(tables))
+                Projection(existential_projection.stable(tables, cx))
             }
             ty::ExistentialPredicate::AutoTrait(def_id) => AutoTrait(tables.trait_def(*def_id)),
         }
@@ -67,11 +86,15 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
     type T = stable_mir::ty::ExistentialTraitRef;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::ExistentialTraitRef { def_id, args, .. } = self;
         stable_mir::ty::ExistentialTraitRef {
             def_id: tables.trait_def(*def_id),
-            generic_args: args.stable(tables),
+            generic_args: args.stable(tables, cx),
         }
     }
 }
@@ -79,12 +102,16 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
     type T = stable_mir::ty::TermKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::TermKind;
         match self {
-            ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables)),
+            ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables, cx)),
             ty::TermKind::Const(cnst) => {
-                let cnst = cnst.stable(tables);
+                let cnst = cnst.stable(tables, cx);
                 TermKind::Const(cnst)
             }
         }
@@ -94,25 +121,33 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
     type T = stable_mir::ty::ExistentialProjection;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::ExistentialProjection { def_id, args, term, .. } = self;
         stable_mir::ty::ExistentialProjection {
             def_id: tables.trait_def(*def_id),
-            generic_args: args.stable(tables),
-            term: term.kind().stable(tables),
+            generic_args: args.stable(tables, cx),
+            term: term.kind().stable(tables, cx),
         }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
     type T = stable_mir::mir::PointerCoercion;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::ty::adjustment::PointerCoercion;
         match self {
             PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer,
             PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer,
             PointerCoercion::ClosureFnPointer(safety) => {
-                stable_mir::mir::PointerCoercion::ClosureFnPointer(safety.stable(tables))
+                stable_mir::mir::PointerCoercion::ClosureFnPointer(safety.stable(tables, cx))
             }
             PointerCoercion::MutToConstPointer => {
                 stable_mir::mir::PointerCoercion::MutToConstPointer
@@ -125,7 +160,7 @@ impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
 
 impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex {
     type T = usize;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         self.as_usize()
     }
 }
@@ -133,7 +168,7 @@ impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex {
 impl<'tcx> Stable<'tcx> for ty::AdtKind {
     type T = AdtKind;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             ty::AdtKind::Struct => AdtKind::Struct,
             ty::AdtKind::Union => AdtKind::Union,
@@ -145,30 +180,44 @@ impl<'tcx> Stable<'tcx> for ty::AdtKind {
 impl<'tcx> Stable<'tcx> for ty::FieldDef {
     type T = stable_mir::ty::FieldDef;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         stable_mir::ty::FieldDef {
             def: tables.create_def_id(self.did),
-            name: self.name.stable(tables),
+            name: self.name.stable(tables, cx),
         }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
     type T = stable_mir::ty::GenericArgs;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        GenericArgs(self.iter().map(|arg| arg.kind().stable(tables)).collect())
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        GenericArgs(self.iter().map(|arg| arg.kind().stable(tables, cx)).collect())
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> {
     type T = stable_mir::ty::GenericArgKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::GenericArgKind;
         match self {
-            ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(region.stable(tables)),
-            ty::GenericArgKind::Type(ty) => GenericArgKind::Type(ty.stable(tables)),
-            ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables)),
+            ty::GenericArgKind::Lifetime(region) => {
+                GenericArgKind::Lifetime(region.stable(tables, cx))
+            }
+            ty::GenericArgKind::Type(ty) => GenericArgKind::Type(ty.stable(tables, cx)),
+            ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables, cx)),
         }
     }
 }
@@ -179,15 +228,19 @@ where
 {
     type T = stable_mir::ty::Binder<V>;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::Binder;
 
         Binder {
-            value: self.as_ref().skip_binder().stable(tables),
+            value: self.as_ref().skip_binder().stable(tables, cx),
             bound_vars: self
                 .bound_vars()
                 .iter()
-                .map(|bound_var| bound_var.stable(tables))
+                .map(|bound_var| bound_var.stable(tables, cx))
                 .collect(),
         }
     }
@@ -199,23 +252,35 @@ where
 {
     type T = stable_mir::ty::EarlyBinder<V>;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::EarlyBinder;
 
-        EarlyBinder { value: self.as_ref().skip_binder().stable(tables) }
+        EarlyBinder { value: self.as_ref().skip_binder().stable(tables, cx) }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
     type T = stable_mir::ty::FnSig;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::FnSig;
 
         FnSig {
-            inputs_and_output: self.inputs_and_output.iter().map(|ty| ty.stable(tables)).collect(),
+            inputs_and_output: self
+                .inputs_and_output
+                .iter()
+                .map(|ty| ty.stable(tables, cx))
+                .collect(),
             c_variadic: self.c_variadic,
-            safety: self.safety.stable(tables),
-            abi: self.abi.stable(tables),
+            safety: self.safety.stable(tables, cx),
+            abi: self.abi.stable(tables, cx),
         }
     }
 }
@@ -223,7 +288,11 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
     type T = stable_mir::ty::BoundTyKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        _: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::BoundTyKind;
 
         match self {
@@ -238,7 +307,11 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
 impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
     type T = stable_mir::ty::BoundRegionKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        _: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::BoundRegionKind;
 
         match self {
@@ -254,15 +327,19 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
 impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
     type T = stable_mir::ty::BoundVariableKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::BoundVariableKind;
 
         match self {
             ty::BoundVariableKind::Ty(bound_ty_kind) => {
-                BoundVariableKind::Ty(bound_ty_kind.stable(tables))
+                BoundVariableKind::Ty(bound_ty_kind.stable(tables, cx))
             }
             ty::BoundVariableKind::Region(bound_region_kind) => {
-                BoundVariableKind::Region(bound_region_kind.stable(tables))
+                BoundVariableKind::Region(bound_region_kind.stable(tables, cx))
             }
             ty::BoundVariableKind::Const => BoundVariableKind::Const,
         }
@@ -272,7 +349,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
 impl<'tcx> Stable<'tcx> for ty::IntTy {
     type T = IntTy;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             ty::IntTy::Isize => IntTy::Isize,
             ty::IntTy::I8 => IntTy::I8,
@@ -287,7 +364,7 @@ impl<'tcx> Stable<'tcx> for ty::IntTy {
 impl<'tcx> Stable<'tcx> for ty::UintTy {
     type T = UintTy;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             ty::UintTy::Usize => UintTy::Usize,
             ty::UintTy::U8 => UintTy::U8,
@@ -302,7 +379,7 @@ impl<'tcx> Stable<'tcx> for ty::UintTy {
 impl<'tcx> Stable<'tcx> for ty::FloatTy {
     type T = FloatTy;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             ty::FloatTy::F16 => FloatTy::F16,
             ty::FloatTy::F32 => FloatTy::F32,
@@ -314,46 +391,55 @@ impl<'tcx> Stable<'tcx> for ty::FloatTy {
 
 impl<'tcx> Stable<'tcx> for Ty<'tcx> {
     type T = stable_mir::ty::Ty;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        tables.intern_ty(tables.tcx.lift(*self).unwrap())
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        tables.intern_ty(cx.lift(*self).unwrap())
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
     type T = stable_mir::ty::TyKind;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match self {
             ty::Bool => TyKind::RigidTy(RigidTy::Bool),
             ty::Char => TyKind::RigidTy(RigidTy::Char),
-            ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables))),
-            ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))),
-            ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))),
+            ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables, cx))),
+            ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables, cx))),
+            ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables, cx))),
             ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
                 tables.adt_def(adt_def.did()),
-                generic_args.stable(tables),
+                generic_args.stable(tables, cx),
             )),
             ty::Foreign(def_id) => TyKind::RigidTy(RigidTy::Foreign(tables.foreign_def(*def_id))),
             ty::Str => TyKind::RigidTy(RigidTy::Str),
             ty::Array(ty, constant) => {
-                TyKind::RigidTy(RigidTy::Array(ty.stable(tables), constant.stable(tables)))
+                TyKind::RigidTy(RigidTy::Array(ty.stable(tables, cx), constant.stable(tables, cx)))
             }
             ty::Pat(ty, pat) => {
-                TyKind::RigidTy(RigidTy::Pat(ty.stable(tables), pat.stable(tables)))
+                TyKind::RigidTy(RigidTy::Pat(ty.stable(tables, cx), pat.stable(tables, cx)))
             }
-            ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables))),
+            ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables, cx))),
             ty::RawPtr(ty, mutbl) => {
-                TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables), mutbl.stable(tables)))
+                TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables, cx), mutbl.stable(tables, cx)))
             }
             ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
-                region.stable(tables),
-                ty.stable(tables),
-                mutbl.stable(tables),
+                region.stable(tables, cx),
+                ty.stable(tables, cx),
+                mutbl.stable(tables, cx),
+            )),
+            ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
+                tables.fn_def(*def_id),
+                generic_args.stable(tables, cx),
             )),
-            ty::FnDef(def_id, generic_args) => {
-                TyKind::RigidTy(RigidTy::FnDef(tables.fn_def(*def_id), generic_args.stable(tables)))
-            }
             ty::FnPtr(sig_tys, hdr) => {
-                TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables)))
+                TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables, cx)))
             }
             // FIXME(unsafe_binders):
             ty::UnsafeBinder(_) => todo!(),
@@ -361,36 +447,36 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
                 TyKind::RigidTy(RigidTy::Dynamic(
                     existential_predicates
                         .iter()
-                        .map(|existential_predicate| existential_predicate.stable(tables))
+                        .map(|existential_predicate| existential_predicate.stable(tables, cx))
                         .collect(),
-                    region.stable(tables),
-                    dyn_kind.stable(tables),
+                    region.stable(tables, cx),
+                    dyn_kind.stable(tables, cx),
                 ))
             }
             ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
                 tables.closure_def(*def_id),
-                generic_args.stable(tables),
+                generic_args.stable(tables, cx),
             )),
             ty::CoroutineClosure(..) => todo!("FIXME(async_closures): Lower these to SMIR"),
             ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine(
                 tables.coroutine_def(*def_id),
-                generic_args.stable(tables),
-                tables.tcx.coroutine_movability(*def_id).stable(tables),
+                generic_args.stable(tables, cx),
+                cx.coroutine_movability(*def_id).stable(tables, cx),
             )),
             ty::Never => TyKind::RigidTy(RigidTy::Never),
-            ty::Tuple(fields) => {
-                TyKind::RigidTy(RigidTy::Tuple(fields.iter().map(|ty| ty.stable(tables)).collect()))
-            }
+            ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
+                fields.iter().map(|ty| ty.stable(tables, cx)).collect(),
+            )),
             ty::Alias(alias_kind, alias_ty) => {
-                TyKind::Alias(alias_kind.stable(tables), alias_ty.stable(tables))
+                TyKind::Alias(alias_kind.stable(tables, cx), alias_ty.stable(tables, cx))
             }
-            ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables)),
+            ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables, cx)),
             ty::Bound(debruijn_idx, bound_ty) => {
-                TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables))
+                TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables, cx))
             }
             ty::CoroutineWitness(def_id, args) => TyKind::RigidTy(RigidTy::CoroutineWitness(
                 tables.coroutine_witness_def(*def_id),
-                args.stable(tables),
+                args.stable(tables, cx),
             )),
             ty::Placeholder(..) | ty::Infer(_) | ty::Error(_) => {
                 unreachable!();
@@ -402,12 +488,16 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
     type T = stable_mir::ty::Pattern;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         match **self {
             ty::PatternKind::Range { start, end } => stable_mir::ty::Pattern::Range {
                 // FIXME(SMIR): update data structures to not have an Option here anymore
-                start: Some(start.stable(tables)),
-                end: Some(end.stable(tables)),
+                start: Some(start.stable(tables, cx)),
+                end: Some(end.stable(tables, cx)),
                 include_end: true,
             },
             ty::PatternKind::Or(_) => todo!(),
@@ -418,24 +508,30 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
     type T = stable_mir::ty::TyConst;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        let ct = tables.tcx.lift(*self).unwrap();
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        let ct = cx.lift(*self).unwrap();
         let kind = match ct.kind() {
             ty::ConstKind::Value(cv) => {
-                let const_val = tables.tcx.valtree_to_const_val(cv);
+                let const_val = cx.valtree_to_const_val(cv);
                 if matches!(const_val, mir::ConstValue::ZeroSized) {
-                    stable_mir::ty::TyConstKind::ZSTValue(cv.ty.stable(tables))
+                    stable_mir::ty::TyConstKind::ZSTValue(cv.ty.stable(tables, cx))
                 } else {
                     stable_mir::ty::TyConstKind::Value(
-                        cv.ty.stable(tables),
-                        alloc::new_allocation(cv.ty, const_val, tables),
+                        cv.ty.stable(tables, cx),
+                        alloc::new_allocation(cv.ty, const_val, tables, cx),
                     )
                 }
             }
-            ty::ConstKind::Param(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)),
+            ty::ConstKind::Param(param) => {
+                stable_mir::ty::TyConstKind::Param(param.stable(tables, cx))
+            }
             ty::ConstKind::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated(
                 tables.const_def(uv.def),
-                uv.args.stable(tables),
+                uv.args.stable(tables, cx),
             ),
             ty::ConstKind::Error(_) => unreachable!(),
             ty::ConstKind::Infer(_) => unreachable!(),
@@ -450,7 +546,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
 
 impl<'tcx> Stable<'tcx> for ty::ParamConst {
     type T = stable_mir::ty::ParamConst;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use stable_mir::ty::ParamConst;
         ParamConst { index: self.index, name: self.name.to_string() }
     }
@@ -458,7 +554,7 @@ impl<'tcx> Stable<'tcx> for ty::ParamConst {
 
 impl<'tcx> Stable<'tcx> for ty::ParamTy {
     type T = stable_mir::ty::ParamTy;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use stable_mir::ty::ParamTy;
         ParamTy { index: self.index, name: self.name.to_string() }
     }
@@ -466,15 +562,19 @@ impl<'tcx> Stable<'tcx> for ty::ParamTy {
 
 impl<'tcx> Stable<'tcx> for ty::BoundTy {
     type T = stable_mir::ty::BoundTy;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::BoundTy;
-        BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables) }
+        BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables, cx) }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
     type T = stable_mir::ty::TraitSpecializationKind;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use stable_mir::ty::TraitSpecializationKind;
 
         match self {
@@ -489,20 +589,24 @@ impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
 
 impl<'tcx> Stable<'tcx> for ty::TraitDef {
     type T = stable_mir::ty::TraitDecl;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::opaque;
         use stable_mir::ty::TraitDecl;
 
         TraitDecl {
             def_id: tables.trait_def(self.def_id),
-            safety: self.safety.stable(tables),
+            safety: self.safety.stable(tables, cx),
             paren_sugar: self.paren_sugar,
             has_auto_impl: self.has_auto_impl,
             is_marker: self.is_marker,
             is_coinductive: self.is_coinductive,
             skip_array_during_method_dispatch: self.skip_array_during_method_dispatch,
             skip_boxed_slice_during_method_dispatch: self.skip_boxed_slice_during_method_dispatch,
-            specialization_kind: self.specialization_kind.stable(tables),
+            specialization_kind: self.specialization_kind.stable(tables, cx),
             must_implement_one_of: self
                 .must_implement_one_of
                 .as_ref()
@@ -515,20 +619,28 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
 
 impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
     type T = stable_mir::ty::TraitRef;
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::TraitRef;
 
-        TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables)).unwrap()
+        TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables, cx)).unwrap()
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::Generics {
     type T = stable_mir::ty::Generics;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::Generics;
 
-        let params: Vec<_> = self.own_params.iter().map(|param| param.stable(tables)).collect();
+        let params: Vec<_> = self.own_params.iter().map(|param| param.stable(tables, cx)).collect();
         let param_def_id_to_index =
             params.iter().map(|param| (param.def_id, param.index)).collect();
 
@@ -541,7 +653,7 @@ impl<'tcx> Stable<'tcx> for ty::Generics {
             has_late_bound_regions: self
                 .has_late_bound_regions
                 .as_ref()
-                .map(|late_bound_regions| late_bound_regions.stable(tables)),
+                .map(|late_bound_regions| late_bound_regions.stable(tables, cx)),
         }
     }
 }
@@ -549,7 +661,7 @@ impl<'tcx> Stable<'tcx> for ty::Generics {
 impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
     type T = stable_mir::ty::GenericParamDefKind;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use stable_mir::ty::GenericParamDefKind;
         match self {
             ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime,
@@ -566,13 +678,17 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
 impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef {
     type T = stable_mir::ty::GenericParamDef;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         GenericParamDef {
             name: self.name.to_string(),
             def_id: tables.generic_def(self.def_id),
             index: self.index,
             pure_wrt_drop: self.pure_wrt_drop,
-            kind: self.kind.stable(tables),
+            kind: self.kind.stable(tables, cx),
         }
     }
 }
@@ -580,31 +696,36 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef {
 impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
     type T = stable_mir::ty::PredicateKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::ty::PredicateKind;
         match self {
             PredicateKind::Clause(clause_kind) => {
-                stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables))
+                stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables, cx))
             }
             PredicateKind::DynCompatible(did) => {
                 stable_mir::ty::PredicateKind::DynCompatible(tables.trait_def(*did))
             }
             PredicateKind::Subtype(subtype_predicate) => {
-                stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables))
+                stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables, cx))
             }
             PredicateKind::Coerce(coerce_predicate) => {
-                stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables))
-            }
-            PredicateKind::ConstEquate(a, b) => {
-                stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables))
+                stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables, cx))
             }
+            PredicateKind::ConstEquate(a, b) => stable_mir::ty::PredicateKind::ConstEquate(
+                a.stable(tables, cx),
+                b.stable(tables, cx),
+            ),
             PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous,
             PredicateKind::NormalizesTo(_pred) => unimplemented!(),
             PredicateKind::AliasRelate(a, b, alias_relation_direction) => {
                 stable_mir::ty::PredicateKind::AliasRelate(
-                    a.kind().stable(tables),
-                    b.kind().stable(tables),
-                    alias_relation_direction.stable(tables),
+                    a.kind().stable(tables, cx),
+                    b.kind().stable(tables, cx),
+                    alias_relation_direction.stable(tables, cx),
                 )
             }
         }
@@ -614,34 +735,38 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
     type T = stable_mir::ty::ClauseKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use rustc_middle::ty::ClauseKind;
         match *self {
             ClauseKind::Trait(trait_object) => {
-                stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables))
+                stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables, cx))
             }
             ClauseKind::RegionOutlives(region_outlives) => {
-                stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables))
+                stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables, cx))
             }
             ClauseKind::TypeOutlives(type_outlives) => {
                 let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives;
                 stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate(
-                    a.stable(tables),
-                    b.stable(tables),
+                    a.stable(tables, cx),
+                    b.stable(tables, cx),
                 ))
             }
             ClauseKind::Projection(projection_predicate) => {
-                stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables))
+                stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables, cx))
             }
             ClauseKind::ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType(
-                const_.stable(tables),
-                ty.stable(tables),
+                const_.stable(tables, cx),
+                ty.stable(tables, cx),
             ),
             ClauseKind::WellFormed(term) => {
-                stable_mir::ty::ClauseKind::WellFormed(term.kind().stable(tables))
+                stable_mir::ty::ClauseKind::WellFormed(term.kind().stable(tables, cx))
             }
             ClauseKind::ConstEvaluatable(const_) => {
-                stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables))
+                stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables, cx))
             }
             ClauseKind::HostEffect(..) => {
                 todo!()
@@ -653,7 +778,7 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::ClosureKind {
     type T = stable_mir::ty::ClosureKind;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::ty::ClosureKind::*;
         match self {
             Fn => stable_mir::ty::ClosureKind::Fn,
@@ -666,25 +791,33 @@ impl<'tcx> Stable<'tcx> for ty::ClosureKind {
 impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> {
     type T = stable_mir::ty::SubtypePredicate;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::SubtypePredicate { a, b, a_is_expected: _ } = self;
-        stable_mir::ty::SubtypePredicate { a: a.stable(tables), b: b.stable(tables) }
+        stable_mir::ty::SubtypePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> {
     type T = stable_mir::ty::CoercePredicate;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::CoercePredicate { a, b } = self;
-        stable_mir::ty::CoercePredicate { a: a.stable(tables), b: b.stable(tables) }
+        stable_mir::ty::CoercePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection {
     type T = stable_mir::ty::AliasRelationDirection;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::ty::AliasRelationDirection::*;
         match self {
             Equate => stable_mir::ty::AliasRelationDirection::Equate,
@@ -696,11 +829,15 @@ impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection {
 impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> {
     type T = stable_mir::ty::TraitPredicate;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::TraitPredicate { trait_ref, polarity } = self;
         stable_mir::ty::TraitPredicate {
-            trait_ref: trait_ref.stable(tables),
-            polarity: polarity.stable(tables),
+            trait_ref: trait_ref.stable(tables, cx),
+            polarity: polarity.stable(tables, cx),
         }
     }
 }
@@ -711,20 +848,28 @@ where
 {
     type T = stable_mir::ty::OutlivesPredicate<T::T, Region>;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::OutlivesPredicate(a, b) = self;
-        stable_mir::ty::OutlivesPredicate(a.stable(tables), b.stable(tables))
+        stable_mir::ty::OutlivesPredicate(a.stable(tables, cx), b.stable(tables, cx))
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> {
     type T = stable_mir::ty::ProjectionPredicate;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         let ty::ProjectionPredicate { projection_term, term } = self;
         stable_mir::ty::ProjectionPredicate {
-            projection_term: projection_term.stable(tables),
-            term: term.kind().stable(tables),
+            projection_term: projection_term.stable(tables, cx),
+            term: term.kind().stable(tables, cx),
         }
     }
 }
@@ -732,7 +877,7 @@ impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::ImplPolarity {
     type T = stable_mir::ty::ImplPolarity;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::ty::ImplPolarity::*;
         match self {
             Positive => stable_mir::ty::ImplPolarity::Positive,
@@ -745,7 +890,7 @@ impl<'tcx> Stable<'tcx> for ty::ImplPolarity {
 impl<'tcx> Stable<'tcx> for ty::PredicatePolarity {
     type T = stable_mir::ty::PredicatePolarity;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_middle::ty::PredicatePolarity::*;
         match self {
             Positive => stable_mir::ty::PredicatePolarity::Positive,
@@ -757,15 +902,23 @@ impl<'tcx> Stable<'tcx> for ty::PredicatePolarity {
 impl<'tcx> Stable<'tcx> for ty::Region<'tcx> {
     type T = stable_mir::ty::Region;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        Region { kind: self.kind().stable(tables) }
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        Region { kind: self.kind().stable(tables, cx) }
     }
 }
 
 impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
     type T = stable_mir::ty::RegionKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::{BoundRegion, EarlyParamRegion, RegionKind};
         match self {
             ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion {
@@ -774,7 +927,10 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
             }),
             ty::ReBound(db_index, bound_reg) => RegionKind::ReBound(
                 db_index.as_u32(),
-                BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) },
+                BoundRegion {
+                    var: bound_reg.var.as_u32(),
+                    kind: bound_reg.kind.stable(tables, cx),
+                },
             ),
             ty::ReStatic => RegionKind::ReStatic,
             ty::RePlaceholder(place_holder) => {
@@ -782,7 +938,7 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
                     universe: place_holder.universe.as_u32(),
                     bound: BoundRegion {
                         var: place_holder.bound.var.as_u32(),
-                        kind: place_holder.bound.kind.stable(tables),
+                        kind: place_holder.bound.kind.stable(tables, cx),
                     },
                 })
             }
@@ -795,8 +951,12 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
 impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
     type T = stable_mir::mir::mono::Instance;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        let def = tables.instance_def(tables.tcx.lift(*self).unwrap());
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
+        let def = tables.instance_def(cx.lift(*self).unwrap());
         let kind = match self.def {
             ty::InstanceKind::Item(..) => stable_mir::mir::mono::InstanceKind::Item,
             ty::InstanceKind::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic,
@@ -824,7 +984,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
 
 impl<'tcx> Stable<'tcx> for ty::Variance {
     type T = stable_mir::mir::Variance;
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             ty::Bivariant => stable_mir::mir::Variance::Bivariant,
             ty::Contravariant => stable_mir::mir::Variance::Contravariant,
@@ -837,7 +997,7 @@ impl<'tcx> Stable<'tcx> for ty::Variance {
 impl<'tcx> Stable<'tcx> for ty::Movability {
     type T = stable_mir::ty::Movability;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         match self {
             ty::Movability::Static => stable_mir::ty::Movability::Static,
             ty::Movability::Movable => stable_mir::ty::Movability::Movable,
@@ -848,7 +1008,7 @@ impl<'tcx> Stable<'tcx> for ty::Movability {
 impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi {
     type T = stable_mir::ty::Abi;
 
-    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use rustc_abi::ExternAbi;
         use stable_mir::ty::Abi;
         match *self {
@@ -886,10 +1046,14 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi {
 impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule {
     type T = stable_mir::ty::ForeignModule;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         stable_mir::ty::ForeignModule {
             def_id: tables.foreign_module_def(self.def_id),
-            abi: self.abi.stable(tables),
+            abi: self.abi.stable(tables, cx),
         }
     }
 }
@@ -897,7 +1061,11 @@ impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule {
 impl<'tcx> Stable<'tcx> for ty::AssocKind {
     type T = stable_mir::ty::AssocKind;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::{AssocKind, AssocTypeData};
         match *self {
             ty::AssocKind::Const { name } => AssocKind::Const { name: name.to_string() },
@@ -908,7 +1076,7 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind {
                 data: match data {
                     ty::AssocTypeData::Normal(name) => AssocTypeData::Normal(name.to_string()),
                     ty::AssocTypeData::Rpitit(rpitit) => {
-                        AssocTypeData::Rpitit(rpitit.stable(tables))
+                        AssocTypeData::Rpitit(rpitit.stable(tables, cx))
                     }
                 },
             },
@@ -919,7 +1087,7 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind {
 impl<'tcx> Stable<'tcx> for ty::AssocItemContainer {
     type T = stable_mir::ty::AssocItemContainer;
 
-    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx, BridgeTys>, _: &SmirCtxt<'tcx, BridgeTys>) -> Self::T {
         use stable_mir::ty::AssocItemContainer;
         match self {
             ty::AssocItemContainer::Trait => AssocItemContainer::Trait,
@@ -931,11 +1099,15 @@ impl<'tcx> Stable<'tcx> for ty::AssocItemContainer {
 impl<'tcx> Stable<'tcx> for ty::AssocItem {
     type T = stable_mir::ty::AssocItem;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        cx: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         stable_mir::ty::AssocItem {
             def_id: tables.assoc_def(self.def_id),
-            kind: self.kind.stable(tables),
-            container: self.container.stable(tables),
+            kind: self.kind.stable(tables, cx),
+            container: self.container.stable(tables, cx),
             trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)),
         }
     }
@@ -944,7 +1116,11 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem {
 impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData {
     type T = stable_mir::ty::ImplTraitInTraitData;
 
-    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+    fn stable(
+        &self,
+        tables: &mut Tables<'tcx, BridgeTys>,
+        _: &SmirCtxt<'tcx, BridgeTys>,
+    ) -> Self::T {
         use stable_mir::ty::ImplTraitInTraitData;
         match self {
             ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => {
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
index d3ef5f4001d..33213fcbe08 100644
--- a/compiler/rustc_smir/src/stable_mir/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -41,6 +41,7 @@ use crate::{rustc_smir, stable_mir};
 
 pub mod abi;
 mod alloc;
+pub(crate) mod convert;
 #[macro_use]
 pub mod crate_def;
 pub mod compiler_interface;