about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMakai <m4kai410@gmail.com>2025-06-09 08:13:27 +0000
committerMakai <m4kai410@gmail.com>2025-07-04 01:57:38 +0000
commitefa26e1d64c374fa9960e5bf8709937fc251816b (patch)
treeda58b00d3661f13f84df5fcd1282b22f05527212
parentb5a2e7d08057bc04c823ab1611e60cccb2d2cce4 (diff)
downloadrust-efa26e1d64c374fa9960e5bf8709937fc251816b.tar.gz
rust-efa26e1d64c374fa9960e5bf8709937fc251816b.zip
fix: resolve the unsoundness
add a new trait `InternalCx`, which defines the methods that are fine to call from `RustcInternal`. `RustcInternal::internal()` then takes a `impl InternalCx<'tcx>` instead of `TyCtxt<'tcx>`.

make `tcx` in `SmirCtxt` public, since we need to pass it to `RustcInternal::internal()` in `SmirInterface`.
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs13
-rw-r--r--compiler/rustc_smir/src/rustc_smir/alloc.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context/impls.rs77
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context/mod.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context/traits.rs4
-rw-r--r--compiler/rustc_smir/src/stable_mir/compiler_interface.rs145
-rw-r--r--compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs (renamed from compiler/rustc_smir/src/stable_mir/convert/internal.rs)253
-rw-r--r--compiler/rustc_smir/src/stable_mir/unstable/mod.rs210
8 files changed, 422 insertions, 288 deletions
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index b99514a3b73..a8d2ab55d03 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -43,11 +43,14 @@ pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T {
 /// # Panics
 ///
 /// This function will panic if StableMIR has not been properly initialized.
-pub fn internal<'tcx, S>(item: S) -> S::T<'tcx>
+pub fn internal<'tcx, S>(tcx: TyCtxt<'tcx>, item: S) -> S::T<'tcx>
 where
     S: RustcInternal,
 {
-    with_container(|tables, cx| item.internal(tables, cx))
+    // The tcx argument ensures that the item won't outlive the type context.
+    // See https://github.com/rust-lang/rust/pull/120128/commits/9aace6723572438a94378451793ca37deb768e72
+    // for more details.
+    with_container(|tables, _| item.internal(tables, tcx))
 }
 
 pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
@@ -69,14 +72,14 @@ where
 
 /// Loads the current context and calls a function with it.
 /// Do not nest these, as that will ICE.
-pub(crate) fn with_container<'tcx, R, B: Bridge>(
-    f: impl FnOnce(&mut Tables<'tcx, B>, &SmirCtxt<'tcx, B>) -> R,
+pub(crate) fn with_container<R, B: Bridge>(
+    f: impl for<'tcx> FnOnce(&mut Tables<'tcx, B>, &SmirCtxt<'tcx, B>) -> R,
 ) -> R {
     assert!(TLV.is_set());
     TLV.with(|tlv| {
         let ptr = tlv.get();
         assert!(!ptr.is_null());
-        let container = ptr as *const SmirContainer<'tcx, B>;
+        let container = ptr as *const SmirContainer<'_, B>;
         let mut tables = unsafe { (*container).tables.borrow_mut() };
         let cx = unsafe { (*container).cx.borrow() };
         f(&mut *tables, &*cx)
diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs
index 6b32b5b07d8..f5412806d33 100644
--- a/compiler/rustc_smir/src/rustc_smir/alloc.rs
+++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs
@@ -43,8 +43,8 @@ pub fn try_new_slice<'tcx, B: Bridge>(
 ) -> Result<Allocation, B::Error> {
     let alloc_id = cx.tcx.reserve_and_set_memory_alloc(data);
     let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
-    let scalar_ptr = Scalar::from_pointer(ptr, &tables.tcx);
-    let scalar_meta: Scalar = Scalar::from_target_usize(meta, &tables.tcx);
+    let scalar_ptr = Scalar::from_pointer(ptr, &cx.tcx);
+    let scalar_meta: Scalar = Scalar::from_target_usize(meta, &cx.tcx);
     let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ());
     allocation
         .write_scalar(&cx.tcx, alloc_range(Size::ZERO, cx.tcx.data_layout.pointer_size), scalar_ptr)
diff --git a/compiler/rustc_smir/src/rustc_smir/context/impls.rs b/compiler/rustc_smir/src/rustc_smir/context/impls.rs
index bf86d4ac41d..edca740cf0e 100644
--- a/compiler/rustc_smir/src/rustc_smir/context/impls.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context/impls.rs
@@ -25,44 +25,10 @@ use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_span::{FileNameDisplayPreference, Span, Symbol};
 use rustc_target::callconv::FnAbi;
 
-use super::{
-    SmirAllocRange, SmirCtxt, SmirExistentialProjection, SmirExistentialTraitRef, SmirRegion,
-    SmirTraitRef, SmirTy, SmirTypingEnv,
-};
+use super::{SmirAllocRange, SmirCtxt, SmirTy, SmirTypingEnv};
 use crate::rustc_smir::builder::BodyBuilder;
 use crate::rustc_smir::{Bridge, SmirError, Tables, filter_def_ids};
 
-impl<'tcx, B: Bridge> SmirExistentialProjection<'tcx> for SmirCtxt<'tcx, B> {
-    fn new_from_args(
-        &self,
-        def_id: rustc_span::def_id::DefId,
-        args: ty::GenericArgsRef<'tcx>,
-        term: ty::Term<'tcx>,
-    ) -> ty::ExistentialProjection<'tcx> {
-        ty::ExistentialProjection::new_from_args(self.tcx, def_id, args, term)
-    }
-}
-
-impl<'tcx, B: Bridge> SmirExistentialTraitRef<'tcx> for SmirCtxt<'tcx, B> {
-    fn new_from_args(
-        &self,
-        trait_def_id: DefId,
-        args: ty::GenericArgsRef<'tcx>,
-    ) -> ty::ExistentialTraitRef<'tcx> {
-        ty::ExistentialTraitRef::new_from_args(self.tcx, trait_def_id, args)
-    }
-}
-
-impl<'tcx, B: Bridge> SmirTraitRef<'tcx> for SmirCtxt<'tcx, B> {
-    fn new_from_args(
-        &self,
-        trait_def_id: DefId,
-        args: ty::GenericArgsRef<'tcx>,
-    ) -> ty::TraitRef<'tcx> {
-        ty::TraitRef::new_from_args(self.tcx, trait_def_id, args)
-    }
-}
-
 impl<'tcx, B: Bridge> SmirTy<'tcx> for SmirCtxt<'tcx, B> {
     fn new_foreign(&self, def_id: DefId) -> ty::Ty<'tcx> {
         ty::Ty::new_foreign(self.tcx, def_id)
@@ -85,52 +51,11 @@ impl<'tcx, B: Bridge> SmirAllocRange<'tcx> for SmirCtxt<'tcx, B> {
     }
 }
 
-impl<'tcx, B: Bridge> SmirRegion<'tcx> for SmirCtxt<'tcx, B> {
-    fn lifetimes_re_erased(&self) -> ty::Region<'tcx> {
-        self.tcx.lifetimes.re_erased
-    }
-}
-
 impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
     pub fn lift<T: ty::Lift<TyCtxt<'tcx>>>(&self, value: T) -> Option<T::Lifted> {
         self.tcx.lift(value)
     }
 
-    pub fn mk_args_from_iter<I, T>(&self, iter: I) -> T::Output
-    where
-        I: Iterator<Item = T>,
-        T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>,
-    {
-        self.tcx.mk_args_from_iter(iter)
-    }
-
-    pub fn mk_pat(&self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx> {
-        self.tcx.mk_pat(v)
-    }
-
-    pub fn mk_poly_existential_predicates(
-        &self,
-        eps: &[ty::PolyExistentialPredicate<'tcx>],
-    ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
-        self.tcx.mk_poly_existential_predicates(eps)
-    }
-
-    pub fn mk_type_list(&self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
-        self.tcx.mk_type_list(v)
-    }
-
-    pub fn mk_bound_variable_kinds_from_iter<I, T>(&self, iter: I) -> T::Output
-    where
-        I: Iterator<Item = T>,
-        T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
-    {
-        self.tcx.mk_bound_variable_kinds_from_iter(iter)
-    }
-
-    pub fn mk_place_elems(&self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>> {
-        self.tcx.mk_place_elems(v)
-    }
-
     pub fn adt_def(&self, def_id: DefId) -> AdtDef<'tcx> {
         self.tcx.adt_def(def_id)
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/context/mod.rs b/compiler/rustc_smir/src/rustc_smir/context/mod.rs
index b31d92cdfca..38743e5f7d3 100644
--- a/compiler/rustc_smir/src/rustc_smir/context/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context/mod.rs
@@ -21,12 +21,12 @@ pub use traits::*;
 /// The [`crate::stable_mir::compiler_interface::SmirInterface`] must go through
 /// this context to obtain rustc-level information.
 pub struct SmirCtxt<'tcx, B: Bridge> {
-    pub(crate) tcx: TyCtxt<'tcx>,
+    pub tcx: TyCtxt<'tcx>,
     _marker: PhantomData<B>,
 }
 
 impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
-    pub(crate) fn new(tcx: TyCtxt<'tcx>) -> Self {
+    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
         Self { tcx, _marker: Default::default() }
     }
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/context/traits.rs b/compiler/rustc_smir/src/rustc_smir/context/traits.rs
index f5cd7c330b8..19e09016cdd 100644
--- a/compiler/rustc_smir/src/rustc_smir/context/traits.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context/traits.rs
@@ -44,7 +44,3 @@ pub trait SmirTypingEnv<'tcx> {
 pub trait SmirAllocRange<'tcx> {
     fn alloc_range(&self, offset: rustc_abi::Size, size: rustc_abi::Size) -> AllocRange;
 }
-
-pub trait SmirRegion<'tcx> {
-    fn lifetimes_re_erased(&self) -> ty::Region<'tcx>;
-}
diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
index 54d88ddf197..80be1f6efe0 100644
--- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
+++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
@@ -6,6 +6,7 @@
 use std::cell::Cell;
 
 use rustc_hir::def::DefKind;
+use rustc_smir::context::SmirCtxt;
 use rustc_smir::{Bridge, SmirContainer};
 use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions};
 use stable_mir::convert::{RustcInternal, Stable};
@@ -327,16 +328,15 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     /// Check whether the body of a function is available.
     fn has_body(&self, item: DefId) -> bool {
         let mut tables = self.tables.borrow_mut();
-        let tables_ref = &mut *tables;
         let cx = &*self.cx.borrow();
-        let def = item.internal(tables_ref, cx);
+        let def = item.internal(&mut *tables, cx.tcx);
         cx.has_body(def)
     }
 
     fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        cx.foreign_modules(crate_num.internal(&mut *tables, cx))
+        cx.foreign_modules(crate_num.internal(&mut *tables, cx.tcx))
             .iter()
             .map(|did| tables.foreign_module_def(*did))
             .collect()
@@ -346,7 +346,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let krate = crate_num.internal(&mut *tables, cx);
+        let krate = crate_num.internal(&mut *tables, cx.tcx);
         cx.crate_functions(krate).iter().map(|did| tables.fn_def(*did)).collect()
     }
 
@@ -354,7 +354,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let krate = crate_num.internal(&mut *tables, cx);
+        let krate = crate_num.internal(&mut *tables, cx.tcx);
         cx.crate_statics(krate).iter().map(|did| tables.static_def(*did)).collect()
     }
 
@@ -381,7 +381,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let krate = crate_num.internal(&mut *tables, cx);
+        let krate = crate_num.internal(&mut *tables, cx.tcx);
         cx.trait_decls(krate).iter().map(|did| tables.trait_def(*did)).collect()
     }
 
@@ -401,7 +401,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let krate = crate_num.internal(&mut *tables, cx);
+        let krate = crate_num.internal(&mut *tables, cx.tcx);
         cx.trait_impls(krate).iter().map(|did| tables.impl_def(*did)).collect()
     }
 
@@ -461,19 +461,19 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     /// Get information about the local crate.
     fn local_crate(&self) -> Crate {
         let cx = &*self.cx.borrow();
-        self.smir_crate(cx.local_crate_num())
+        smir_crate(cx, cx.local_crate_num())
     }
 
     /// Retrieve a list of all external crates.
     fn external_crates(&self) -> Vec<Crate> {
         let cx = &*self.cx.borrow();
-        cx.external_crates().iter().map(|crate_num| self.smir_crate(*crate_num)).collect()
+        cx.external_crates().iter().map(|crate_num| smir_crate(cx, *crate_num)).collect()
     }
 
     /// Find a crate with the given name.
     fn find_crates(&self, name: &str) -> Vec<Crate> {
         let cx = &*self.cx.borrow();
-        cx.find_crates(name).iter().map(|crate_num| self.smir_crate(*crate_num)).collect()
+        cx.find_crates(name).iter().map(|crate_num| smir_crate(cx, *crate_num)).collect()
     }
 
     /// Returns the name of given `DefId`.
@@ -574,28 +574,28 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn adt_kind(&self, def: AdtDef) -> AdtKind {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        cx.adt_kind(def.internal(&mut *tables, cx)).stable(&mut *tables, cx)
+        cx.adt_kind(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx)
     }
 
     /// Returns if the ADT is a box.
     fn adt_is_box(&self, def: AdtDef) -> bool {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        cx.adt_is_box(def.internal(&mut *tables, cx))
+        cx.adt_is_box(def.internal(&mut *tables, cx.tcx))
     }
 
     /// Returns whether this ADT is simd.
     fn adt_is_simd(&self, def: AdtDef) -> bool {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        cx.adt_is_simd(def.internal(&mut *tables, cx))
+        cx.adt_is_simd(def.internal(&mut *tables, cx.tcx))
     }
 
     /// Returns whether this definition is a C string.
     fn adt_is_cstr(&self, def: AdtDef) -> bool {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        cx.adt_is_cstr(def.0.internal(&mut *tables, cx))
+        cx.adt_is_cstr(def.0.internal(&mut *tables, cx.tcx))
     }
 
     /// Returns the representation options for this ADT
@@ -607,8 +607,8 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx);
-        let args_ref = args.internal(&mut *tables, cx);
+        let def_id = def.0.internal(&mut *tables, cx.tcx);
+        let args_ref = args.internal(&mut *tables, cx.tcx);
         cx.fn_sig(def_id, args_ref).stable(&mut *tables, cx)
     }
 
@@ -616,7 +616,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let def_id = item.internal(&mut *tables, cx);
+        let def_id = item.internal(&mut *tables, cx.tcx);
         cx.intrinsic(def_id).map(|_| IntrinsicDef(item))
     }
 
@@ -624,7 +624,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx);
+        let def_id = def.0.internal(&mut *tables, cx.tcx);
         cx.intrinsic_name(def_id)
     }
 
@@ -632,7 +632,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let args_ref = args.internal(&mut *tables, cx);
+        let args_ref = args.internal(&mut *tables, cx.tcx);
         cx.closure_sig(args_ref).stable(&mut *tables, cx)
     }
 
@@ -640,7 +640,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn adt_variants_len(&self, def: AdtDef) -> usize {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        cx.adt_variants_len(def.internal(&mut *tables, cx))
+        cx.adt_variants_len(def.internal(&mut *tables, cx.tcx))
     }
 
     /// Discriminant for a given variant index of AdtDef
@@ -662,27 +662,31 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn variant_name(&self, def: VariantDef) -> Symbol {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        cx.variant_name(def.internal(&mut *tables, cx))
+        cx.variant_name(def.internal(&mut *tables, cx.tcx))
     }
 
     fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        def.internal(&mut *tables, cx).fields.iter().map(|f| f.stable(&mut *tables, cx)).collect()
+        def.internal(&mut *tables, cx.tcx)
+            .fields
+            .iter()
+            .map(|f| f.stable(&mut *tables, cx))
+            .collect()
     }
 
     /// Evaluate constant as a target usize.
     fn eval_target_usize(&self, mir_const: &MirConst) -> Result<u64, Error> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let cnst = mir_const.internal(&mut *tables, cx);
+        let cnst = mir_const.internal(&mut *tables, cx.tcx);
         cx.eval_target_usize(cnst)
     }
 
     fn eval_target_usize_ty(&self, ty_const: &TyConst) -> Result<u64, Error> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let cnst = ty_const.internal(&mut *tables, cx);
+        let cnst = ty_const.internal(&mut *tables, cx.tcx);
         cx.eval_target_usize_ty(cnst)
     }
 
@@ -690,7 +694,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let ty_internal = ty.internal(&mut *tables, cx);
+        let ty_internal = ty.internal(&mut *tables, cx.tcx);
         cx.try_new_const_zst(ty_internal).map(|cnst| cnst.stable(&mut *tables, cx))
     }
 
@@ -712,14 +716,14 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx));
+        let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx));
         cx.try_new_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx))
     }
 
     fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<TyConst, Error> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx));
+        let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx));
         cx.try_new_ty_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx))
     }
 
@@ -727,7 +731,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn new_rigid_ty(&self, kind: RigidTy) -> Ty {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let internal_kind = kind.internal(&mut *tables, cx);
+        let internal_kind = kind.internal(&mut *tables, cx.tcx);
         cx.new_rigid_ty(internal_kind).stable(&mut *tables, cx)
     }
 
@@ -735,7 +739,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn new_box_ty(&self, ty: Ty) -> Ty {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let inner = ty.internal(&mut *tables, cx);
+        let inner = ty.internal(&mut *tables, cx.tcx);
         cx.new_box_ty(inner).stable(&mut *tables, cx)
     }
 
@@ -743,7 +747,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn def_ty(&self, item: DefId) -> Ty {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let inner = item.internal(&mut *tables, cx);
+        let inner = item.internal(&mut *tables, cx.tcx);
         cx.def_ty(inner).stable(&mut *tables, cx)
     }
 
@@ -751,8 +755,8 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let inner = item.internal(&mut *tables, cx);
-        let args_ref = args.internal(&mut *tables, cx);
+        let inner = item.internal(&mut *tables, cx.tcx);
+        let args_ref = args.internal(&mut *tables, cx.tcx);
         cx.def_ty_with_args(inner, args_ref).stable(&mut *tables, cx)
     }
 
@@ -760,7 +764,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn mir_const_pretty(&self, cnst: &MirConst) -> String {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        cnst.internal(&mut *tables, cx).to_string()
+        cnst.internal(&mut *tables, cx.tcx).to_string()
     }
 
     /// `Span` of an item.
@@ -795,7 +799,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let internal_kind = ty.internal(&mut *tables, cx);
+        let internal_kind = ty.internal(&mut *tables, cx.tcx);
         cx.rigid_ty_discriminant_ty(internal_kind).stable(&mut *tables, cx)
     }
 
@@ -868,8 +872,8 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx);
-        let args_ref = args.internal(&mut *tables, cx);
+        let def_id = def.0.internal(&mut *tables, cx.tcx);
+        let args_ref = args.internal(&mut *tables, cx.tcx);
         cx.resolve_instance(def_id, args_ref).map(|inst| inst.stable(&mut *tables, cx))
     }
 
@@ -877,7 +881,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn resolve_drop_in_place(&self, ty: Ty) -> Instance {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let internal_ty = ty.internal(&mut *tables, cx);
+        let internal_ty = ty.internal(&mut *tables, cx.tcx);
 
         cx.resolve_drop_in_place(internal_ty).stable(&mut *tables, cx)
     }
@@ -886,8 +890,8 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx);
-        let args_ref = args.internal(&mut *tables, cx);
+        let def_id = def.0.internal(&mut *tables, cx.tcx);
+        let args_ref = args.internal(&mut *tables, cx.tcx);
         cx.resolve_for_fn_ptr(def_id, args_ref).stable(&mut *tables, cx)
     }
 
@@ -900,9 +904,9 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     ) -> Option<Instance> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx);
-        let args_ref = args.internal(&mut *tables, cx);
-        let closure_kind = kind.internal(&mut *tables, cx);
+        let def_id = def.0.internal(&mut *tables, cx.tcx);
+        let args_ref = args.internal(&mut *tables, cx.tcx);
+        let closure_kind = kind.internal(&mut *tables, cx.tcx);
         cx.resolve_closure(def_id, args_ref, closure_kind).map(|inst| inst.stable(&mut *tables, cx))
     }
 
@@ -910,7 +914,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let def_id = def.0.internal(&mut *tables, cx);
+        let def_id = def.0.internal(&mut *tables, cx.tcx);
 
         cx.eval_static_initializer(def_id).stable(&mut *tables, cx)
     }
@@ -920,7 +924,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
         let mut tables = self.tables.borrow_mut();
         let instance = tables.instances[def];
         let cx = &*self.cx.borrow();
-        let const_ty = const_ty.internal(&mut *tables, cx);
+        let const_ty = const_ty.internal(&mut *tables, cx.tcx);
         cx.eval_instance(instance)
             .map(|const_val| alloc::try_new_allocation(const_ty, const_val, &mut *tables, cx))
             .map_err(|e| e.stable(&mut *tables, cx))?
@@ -930,7 +934,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn global_alloc(&self, id: AllocId) -> GlobalAlloc {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let alloc_id = id.internal(&mut *tables, cx);
+        let alloc_id = id.internal(&mut *tables, cx.tcx);
         cx.global_alloc(alloc_id).stable(&mut *tables, cx)
     }
 
@@ -941,15 +945,16 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
             return None;
         };
         let cx = &*self.cx.borrow();
-        let ty = ty.internal(&mut *tables, cx);
-        let trait_ref = trait_ref.internal(&mut *tables, cx);
+        let ty = ty.internal(&mut *tables, cx.tcx);
+        let trait_ref = trait_ref.internal(&mut *tables, cx.tcx);
         let alloc_id = cx.vtable_allocation(ty, trait_ref);
         Some(alloc_id.stable(&mut *tables, cx))
     }
 
     fn krate(&self, def_id: DefId) -> Crate {
         let tables = self.tables.borrow();
-        self.smir_crate(tables[def_id].krate)
+        let cx = &*self.cx.borrow();
+        smir_crate(cx, tables[def_id].krate)
     }
 
     fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
@@ -981,7 +986,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let sig = fn_ptr.internal(&mut *tables, cx);
+        let sig = fn_ptr.internal(&mut *tables, cx.tcx);
         cx.fn_ptr_abi(sig).map(|fn_abi| fn_abi.stable(&mut *tables, cx))
     }
 
@@ -989,7 +994,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let internal_ty = ty.internal(&mut *tables, cx);
+        let internal_ty = ty.internal(&mut *tables, cx.tcx);
         cx.ty_layout(internal_ty).map(|layout| layout.stable(&mut *tables, cx))
     }
 
@@ -997,7 +1002,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn layout_shape(&self, id: Layout) -> LayoutShape {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        id.internal(&mut *tables, cx).0.stable(&mut *tables, cx)
+        id.internal(&mut *tables, cx.tcx).0.stable(&mut *tables, cx)
     }
 
     /// Get a debug string representation of a place.
@@ -1005,16 +1010,16 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
 
-        format!("{:?}", place.internal(&mut *tables, cx))
+        format!("{:?}", place.internal(&mut *tables, cx.tcx))
     }
 
     /// Get the resulting type of binary operation.
     fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let rhs_internal = rhs.internal(&mut *tables, cx);
-        let lhs_internal = lhs.internal(&mut *tables, cx);
-        let bin_op_internal = bin_op.internal(&mut *tables, cx);
+        let rhs_internal = rhs.internal(&mut *tables, cx.tcx);
+        let lhs_internal = lhs.internal(&mut *tables, cx.tcx);
+        let bin_op_internal = bin_op.internal(&mut *tables, cx.tcx);
         cx.binop_ty(bin_op_internal, rhs_internal, lhs_internal).stable(&mut *tables, cx)
     }
 
@@ -1022,8 +1027,8 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
         let mut tables = self.tables.borrow_mut();
         let cx = &*self.cx.borrow();
-        let un_op = un_op.internal(&mut *tables, cx);
-        let arg = arg.internal(&mut *tables, cx);
+        let un_op = un_op.internal(&mut *tables, cx.tcx);
+        let arg = arg.internal(&mut *tables, cx.tcx);
         cx.unop_ty(un_op, arg).stable(&mut *tables, cx)
     }
 
@@ -1036,21 +1041,6 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> {
     }
 }
 
-impl<'tcx> Helper for SmirContainer<'tcx, BridgeTys> {
-    fn smir_crate(&self, crate_num: rustc_span::def_id::CrateNum) -> Crate {
-        let cx = &*self.cx.borrow();
-        let name = cx.crate_name(crate_num);
-        let is_local = cx.crate_is_local(crate_num);
-        let id = cx.crate_num_id(crate_num);
-        debug!(?name, ?crate_num, "smir_crate");
-        Crate { id, name, is_local }
-    }
-}
-
-trait Helper {
-    fn smir_crate(&self, crate_num: rustc_span::def_id::CrateNum) -> Crate;
-}
-
 // A thread local variable that stores a pointer to [`SmirInterface`].
 scoped_tls::scoped_thread_local!(static TLV: Cell<*const ()>);
 
@@ -1078,3 +1068,14 @@ pub(crate) fn with<R>(f: impl FnOnce(&dyn SmirInterface) -> R) -> R {
         f(unsafe { *(ptr as *const &dyn SmirInterface) })
     })
 }
+
+fn smir_crate<'tcx>(
+    cx: &SmirCtxt<'tcx, BridgeTys>,
+    crate_num: rustc_span::def_id::CrateNum,
+) -> Crate {
+    let name = cx.crate_name(crate_num);
+    let is_local = cx.crate_is_local(crate_num);
+    let id = cx.crate_num_id(crate_num);
+    debug!(?name, ?crate_num, "smir_crate");
+    Crate { id, name, is_local }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/convert/internal.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs
index a8c5f108528..2a71aece7a0 100644
--- a/compiler/rustc_smir/src/stable_mir/convert/internal.rs
+++ b/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs
@@ -6,12 +6,11 @@
 // 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};
-use rustc_smir::context::SmirCtxt;
-use rustc_smir::{IndexedVal, Tables};
+use rustc_smir::Tables;
 use rustc_span::Symbol;
 use stable_mir::abi::Layout;
 use stable_mir::compiler_interface::BridgeTys;
-use stable_mir::convert::RustcInternal;
+use stable_mir::unstable::{RustcInternal, InternalCx};
 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};
@@ -21,18 +20,19 @@ use stable_mir::ty::{
     GenericArgKind, GenericArgs, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span,
     TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx,
 };
-use stable_mir::{CrateItem, CrateNum, DefId};
+use stable_mir::{CrateItem, CrateNum, DefId, IndexedVal};
 
 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<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        self.0.internal(tables, cx)
+        self.0.internal(tables, tcx)
     }
 }
 
@@ -41,7 +41,7 @@ impl RustcInternal for CrateNum {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         rustc_span::def_id::CrateNum::from_usize(*self)
     }
@@ -52,9 +52,9 @@ impl RustcInternal for DefId {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.lift(tables.def_ids[*self]).unwrap()
+        tcx.lift(tables.def_ids[*self]).unwrap()
     }
 }
 
@@ -63,9 +63,9 @@ impl RustcInternal for GenericArgs {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables, cx)))
+        InternalCx::mk_args_from_iter(tcx, self.0.iter().map(|arg| arg.internal(tables, tcx)))
     }
 }
 
@@ -74,14 +74,14 @@ impl RustcInternal for GenericArgKind {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         let arg: rustc_ty::GenericArg<'tcx> = match self {
-            GenericArgKind::Lifetime(reg) => reg.internal(tables, cx).into(),
-            GenericArgKind::Type(ty) => ty.internal(tables, cx).into(),
-            GenericArgKind::Const(cnst) => cnst.internal(tables, cx).into(),
+            GenericArgKind::Lifetime(reg) => reg.internal(tables, tcx).into(),
+            GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(),
+            GenericArgKind::Const(cnst) => cnst.internal(tables, tcx).into(),
         };
-        cx.lift(arg).unwrap()
+        tcx.lift(arg).unwrap()
     }
 }
 
@@ -90,11 +90,10 @@ impl RustcInternal for Region {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         // Cannot recover region. Use erased for now.
-        use rustc_smir::context::SmirRegion;
-        cx.lifetimes_re_erased()
+        tcx.lifetimes_re_erased()
     }
 }
 
@@ -103,9 +102,9 @@ impl RustcInternal for Ty {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.lift(tables.types[*self]).unwrap()
+        tcx.lift(tables.types[*self]).unwrap()
     }
 }
 
@@ -114,9 +113,9 @@ impl RustcInternal for TyConst {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.lift(tables.ty_consts[self.id]).unwrap()
+        tcx.lift(tables.ty_consts[self.id]).unwrap()
     }
 }
 
@@ -125,12 +124,12 @@ impl RustcInternal for Pattern {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.mk_pat(match self {
+        tcx.mk_pat(match self {
             Pattern::Range { start, end, include_end: _ } => rustc_ty::PatternKind::Range {
-                start: start.as_ref().unwrap().internal(tables, cx),
-                end: end.as_ref().unwrap().internal(tables, cx),
+                start: start.as_ref().unwrap().internal(tables, tcx),
+                end: end.as_ref().unwrap().internal(tables, tcx),
             },
         })
     }
@@ -142,63 +141,63 @@ impl RustcInternal for RigidTy {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> 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, 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::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::Never => rustc_ty::TyKind::Never,
             RigidTy::Array(ty, cnst) => {
-                rustc_ty::TyKind::Array(ty.internal(tables, cx), cnst.internal(tables, cx))
+                rustc_ty::TyKind::Array(ty.internal(tables, tcx), cnst.internal(tables, tcx))
             }
             RigidTy::Pat(ty, pat) => {
-                rustc_ty::TyKind::Pat(ty.internal(tables, cx), pat.internal(tables, cx))
+                rustc_ty::TyKind::Pat(ty.internal(tables, tcx), pat.internal(tables, tcx))
             }
             RigidTy::Adt(def, args) => {
-                rustc_ty::TyKind::Adt(def.internal(tables, cx), args.internal(tables, cx))
+                rustc_ty::TyKind::Adt(def.internal(tables, tcx), args.internal(tables, tcx))
             }
             RigidTy::Str => rustc_ty::TyKind::Str,
-            RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables, cx)),
+            RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables, tcx)),
             RigidTy::RawPtr(ty, mutability) => {
-                rustc_ty::TyKind::RawPtr(ty.internal(tables, cx), mutability.internal(tables, cx))
+                rustc_ty::TyKind::RawPtr(ty.internal(tables, tcx), mutability.internal(tables, tcx))
             }
             RigidTy::Ref(region, ty, mutability) => rustc_ty::TyKind::Ref(
-                region.internal(tables, cx),
-                ty.internal(tables, cx),
-                mutability.internal(tables, cx),
+                region.internal(tables, tcx),
+                ty.internal(tables, tcx),
+                mutability.internal(tables, tcx),
             ),
-            RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables, cx)),
+            RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables, tcx)),
             RigidTy::FnDef(def, args) => {
-                rustc_ty::TyKind::FnDef(def.0.internal(tables, cx), args.internal(tables, cx))
+                rustc_ty::TyKind::FnDef(def.0.internal(tables, tcx), args.internal(tables, tcx))
             }
             RigidTy::FnPtr(sig) => {
-                let (sig_tys, hdr) = sig.internal(tables, cx).split();
+                let (sig_tys, hdr) = sig.internal(tables, tcx).split();
                 rustc_ty::TyKind::FnPtr(sig_tys, hdr)
             }
             RigidTy::Closure(def, args) => {
-                rustc_ty::TyKind::Closure(def.0.internal(tables, cx), args.internal(tables, cx))
+                rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx))
             }
             RigidTy::Coroutine(def, args, _mov) => {
-                rustc_ty::TyKind::Coroutine(def.0.internal(tables, cx), args.internal(tables, cx))
+                rustc_ty::TyKind::Coroutine(def.0.internal(tables, tcx), args.internal(tables, tcx))
             }
             RigidTy::CoroutineClosure(def, args) => rustc_ty::TyKind::CoroutineClosure(
-                def.0.internal(tables, cx),
-                args.internal(tables, cx),
+                def.0.internal(tables, tcx),
+                args.internal(tables, tcx),
             ),
             RigidTy::CoroutineWitness(def, args) => rustc_ty::TyKind::CoroutineWitness(
-                def.0.internal(tables, cx),
-                args.internal(tables, cx),
+                def.0.internal(tables, tcx),
+                args.internal(tables, tcx),
             ),
             RigidTy::Dynamic(predicate, region, dyn_kind) => rustc_ty::TyKind::Dynamic(
-                cx.mk_poly_existential_predicates(&predicate.internal(tables, cx)),
-                region.internal(tables, cx),
-                dyn_kind.internal(tables, cx),
+                tcx.mk_poly_existential_predicates(&predicate.internal(tables, tcx)),
+                region.internal(tables, tcx),
+                dyn_kind.internal(tables, tcx),
             ),
             RigidTy::Tuple(tys) => {
-                rustc_ty::TyKind::Tuple(cx.mk_type_list(&tys.internal(tables, cx)))
+                rustc_ty::TyKind::Tuple(tcx.mk_type_list(&tys.internal(tables, tcx)))
             }
         }
     }
@@ -210,7 +209,7 @@ impl RustcInternal for IntTy {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             IntTy::Isize => rustc_ty::IntTy::Isize,
@@ -229,7 +228,7 @@ impl RustcInternal for UintTy {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             UintTy::Usize => rustc_ty::UintTy::Usize,
@@ -248,7 +247,7 @@ impl RustcInternal for FloatTy {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             FloatTy::F16 => rustc_ty::FloatTy::F16,
@@ -265,7 +264,7 @@ impl RustcInternal for Mutability {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             Mutability::Not => rustc_ty::Mutability::Not,
@@ -280,7 +279,7 @@ impl RustcInternal for Movability {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             Movability::Static => rustc_ty::Movability::Static,
@@ -295,7 +294,7 @@ impl RustcInternal for RawPtrKind {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             RawPtrKind::Mut => rustc_middle::mir::RawPtrKind::Mut,
@@ -311,13 +310,13 @@ impl RustcInternal for FnSig {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.lift(rustc_ty::FnSig {
-            inputs_and_output: cx.mk_type_list(&self.inputs_and_output.internal(tables, cx)),
+        tcx.lift(rustc_ty::FnSig {
+            inputs_and_output: tcx.mk_type_list(&self.inputs_and_output.internal(tables, tcx)),
             c_variadic: self.c_variadic,
-            safety: self.safety.internal(tables, cx),
-            abi: self.abi.internal(tables, cx),
+            safety: self.safety.internal(tables, tcx),
+            abi: self.abi.internal(tables, tcx),
         })
         .unwrap()
     }
@@ -329,7 +328,7 @@ impl RustcInternal for VariantIdx {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         rustc_abi::VariantIdx::from(self.to_index())
     }
@@ -341,9 +340,9 @@ impl RustcInternal for VariantDef {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        self.adt_def.internal(tables, cx).variant(self.idx.internal(tables, cx))
+        self.adt_def.internal(tables, tcx).variant(self.idx.internal(tables, tcx))
     }
 }
 
@@ -352,21 +351,21 @@ impl RustcInternal for MirConst {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         let constant = tables.mir_consts[self.id];
         match constant {
             rustc_middle::mir::Const::Ty(ty, ct) => {
-                rustc_middle::mir::Const::Ty(cx.lift(ty).unwrap(), cx.lift(ct).unwrap())
+                rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap(), tcx.lift(ct).unwrap())
             }
             rustc_middle::mir::Const::Unevaluated(uneval, ty) => {
                 rustc_middle::mir::Const::Unevaluated(
-                    cx.lift(uneval).unwrap(),
-                    cx.lift(ty).unwrap(),
+                    tcx.lift(uneval).unwrap(),
+                    tcx.lift(ty).unwrap(),
                 )
             }
             rustc_middle::mir::Const::Val(const_val, ty) => {
-                rustc_middle::mir::Const::Val(cx.lift(const_val).unwrap(), cx.lift(ty).unwrap())
+                rustc_middle::mir::Const::Val(tcx.lift(const_val).unwrap(), tcx.lift(ty).unwrap())
             }
         }
     }
@@ -378,12 +377,12 @@ impl RustcInternal for MonoItem {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         use rustc_middle::mir::mono as rustc_mono;
         match self {
-            MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables, cx)),
-            MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables, cx)),
+            MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables, tcx)),
+            MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables, tcx)),
             MonoItem::GlobalAsm(_) => {
                 unimplemented!()
             }
@@ -397,9 +396,9 @@ impl RustcInternal for Instance {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.lift(tables.instances[self.def]).unwrap()
+        tcx.lift(tables.instances[self.def]).unwrap()
     }
 }
 
@@ -409,9 +408,9 @@ impl RustcInternal for StaticDef {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        self.0.internal(tables, cx)
+        self.0.internal(tables, tcx)
     }
 }
 
@@ -426,12 +425,12 @@ where
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         rustc_ty::Binder::bind_with_vars(
-            self.value.internal(tables, cx),
-            cx.mk_bound_variable_kinds_from_iter(
-                self.bound_vars.iter().map(|bound| bound.internal(tables, cx)),
+            self.value.internal(tables, tcx),
+            tcx.mk_bound_variable_kinds_from_iter(
+                self.bound_vars.iter().map(|bound| bound.internal(tables, tcx)),
             ),
         )
     }
@@ -443,19 +442,19 @@ impl RustcInternal for BoundVariableKind {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> 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, cx), Symbol::intern(symbol))
+                    rustc_ty::BoundTyKind::Param(def.0.internal(tables, tcx), 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, cx),
+                    def.0.internal(tables, tcx),
                     Symbol::intern(symbol),
                 ),
                 BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::ClosureEnv,
@@ -471,7 +470,7 @@ impl RustcInternal for DynKind {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             DynKind::Dyn => rustc_ty::DynKind::Dyn,
@@ -485,17 +484,17 @@ impl RustcInternal for ExistentialPredicate {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             ExistentialPredicate::Trait(trait_ref) => {
-                rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables, cx))
+                rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables, tcx))
             }
             ExistentialPredicate::Projection(proj) => {
-                rustc_ty::ExistentialPredicate::Projection(proj.internal(tables, cx))
+                rustc_ty::ExistentialPredicate::Projection(proj.internal(tables, tcx))
             }
             ExistentialPredicate::AutoTrait(trait_def) => {
-                rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables, cx))
+                rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables, tcx))
             }
         }
     }
@@ -507,13 +506,13 @@ impl RustcInternal for ExistentialProjection {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> 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),
+        tcx.new_from_args(
+            self.def_id.0.internal(tables, tcx),
+            self.generic_args.internal(tables, tcx),
+            self.term.internal(tables, tcx),
         )
     }
 }
@@ -524,11 +523,11 @@ impl RustcInternal for TermKind {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
-            TermKind::Type(ty) => ty.internal(tables, cx).into(),
-            TermKind::Const(cnst) => cnst.internal(tables, cx).into(),
+            TermKind::Type(ty) => ty.internal(tables, tcx).into(),
+            TermKind::Const(cnst) => cnst.internal(tables, tcx).into(),
         }
     }
 }
@@ -539,10 +538,10 @@ impl RustcInternal for ExistentialTraitRef {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> 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))
+        tcx.new_from_args(self.def_id.0.internal(tables, tcx), self.generic_args.internal(tables, tcx))
     }
 }
 
@@ -552,10 +551,10 @@ impl RustcInternal for TraitRef {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         use rustc_smir::context::SmirTraitRef;
-        cx.new_from_args(self.def_id.0.internal(tables, cx), self.args().internal(tables, cx))
+        tcx.new_from_args(self.def_id.0.internal(tables, tcx), self.args().internal(tables, tcx))
     }
 }
 
@@ -564,9 +563,9 @@ impl RustcInternal for AllocId {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.lift(tables.alloc_ids[*self]).unwrap()
+        tcx.lift(tables.alloc_ids[*self]).unwrap()
     }
 }
 
@@ -576,7 +575,7 @@ impl RustcInternal for ClosureKind {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             ClosureKind::Fn => rustc_ty::ClosureKind::Fn,
@@ -591,9 +590,9 @@ impl RustcInternal for AdtDef {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.adt_def(self.0.internal(tables, cx))
+        InternalCx::adt_def(tcx, self.0.internal(tables, tcx))
     }
 }
 
@@ -603,7 +602,7 @@ impl RustcInternal for Abi {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match *self {
             Abi::Rust => rustc_abi::ExternAbi::Rust,
@@ -643,7 +642,7 @@ impl RustcInternal for Safety {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             Safety::Unsafe => rustc_hir::Safety::Unsafe,
@@ -657,7 +656,7 @@ impl RustcInternal for Span {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         tables.spans[*self]
     }
@@ -669,9 +668,9 @@ impl RustcInternal for Layout {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        cx.lift(tables.layouts[*self]).unwrap()
+        tcx.lift(tables.layouts[*self]).unwrap()
     }
 }
 
@@ -681,11 +680,11 @@ impl RustcInternal for Place {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         rustc_middle::mir::Place {
             local: rustc_middle::mir::Local::from_usize(self.local),
-            projection: cx.mk_place_elems(&self.projection.internal(tables, cx)),
+            projection: tcx.mk_place_elems(&self.projection.internal(tables, tcx)),
         }
     }
 }
@@ -696,12 +695,12 @@ impl RustcInternal for ProjectionElem {
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> 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, cx))
+                rustc_middle::mir::PlaceElem::Field((*idx).into(), ty.internal(tables, tcx))
             }
             ProjectionElem::Index(idx) => rustc_middle::mir::PlaceElem::Index((*idx).into()),
             ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
@@ -715,13 +714,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, cx))
+                rustc_middle::mir::PlaceElem::Downcast(None, idx.internal(tables, tcx))
             }
             ProjectionElem::OpaqueCast(ty) => {
-                rustc_middle::mir::PlaceElem::OpaqueCast(ty.internal(tables, cx))
+                rustc_middle::mir::PlaceElem::OpaqueCast(ty.internal(tables, tcx))
             }
             ProjectionElem::Subtype(ty) => {
-                rustc_middle::mir::PlaceElem::Subtype(ty.internal(tables, cx))
+                rustc_middle::mir::PlaceElem::Subtype(ty.internal(tables, tcx))
             }
         }
     }
@@ -733,7 +732,7 @@ impl RustcInternal for BinOp {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             BinOp::Add => rustc_middle::mir::BinOp::Add,
@@ -769,7 +768,7 @@ impl RustcInternal for UnOp {
     fn internal<'tcx>(
         &self,
         _tables: &mut Tables<'_, BridgeTys>,
-        _cx: &SmirCtxt<'tcx, BridgeTys>,
+        _tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
         match self {
             UnOp::Not => rustc_middle::mir::UnOp::Not,
@@ -788,9 +787,9 @@ where
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        (*self).internal(tables, cx)
+        (*self).internal(tables, tcx)
     }
 }
 
@@ -803,9 +802,9 @@ where
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        self.as_ref().map(|inner| inner.internal(tables, cx))
+        self.as_ref().map(|inner| inner.internal(tables, tcx))
     }
 }
 
@@ -818,8 +817,8 @@ where
     fn internal<'tcx>(
         &self,
         tables: &mut Tables<'_, BridgeTys>,
-        cx: &SmirCtxt<'tcx, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
     ) -> Self::T<'tcx> {
-        self.iter().map(|e| e.internal(tables, cx)).collect()
+        self.iter().map(|e| e.internal(tables, tcx)).collect()
     }
 }
diff --git a/compiler/rustc_smir/src/stable_mir/unstable/mod.rs b/compiler/rustc_smir/src/stable_mir/unstable/mod.rs
new file mode 100644
index 00000000000..c0e7e60a2c2
--- /dev/null
+++ b/compiler/rustc_smir/src/stable_mir/unstable/mod.rs
@@ -0,0 +1,210 @@
+//! Module that collects the things that have no stability guarantees.
+//!
+//! We want to keep StableMIR definitions and logic separate from 
+//! any sort of conversion and usage of internal rustc code. So we 
+//! restrict the usage of internal items to be inside this module.
+
+use std::marker::PointeeSized;
+
+use rustc_hir::def::DefKind;
+use rustc_middle::ty::{List, Ty, TyCtxt};
+use rustc_middle::{mir, ty};
+use rustc_smir::Tables;
+use rustc_smir::context::{SmirCtxt, SmirExistentialProjection, SmirExistentialTraitRef, SmirTraitRef};
+
+use stable_mir::{CtorKind, ItemKind};
+
+use crate::{rustc_smir, stable_mir};
+
+use super::compiler_interface::BridgeTys;
+
+pub(crate) mod convert;
+
+impl<'tcx, T: InternalCx<'tcx>> SmirExistentialProjection<'tcx> for T {
+    fn new_from_args(
+        &self,
+        def_id: rustc_span::def_id::DefId,
+        args: ty::GenericArgsRef<'tcx>,
+        term: ty::Term<'tcx>,
+    ) -> ty::ExistentialProjection<'tcx> {
+        ty::ExistentialProjection::new_from_args(self.tcx(), def_id, args, term)
+    }
+}
+
+impl<'tcx, T: InternalCx<'tcx>> SmirExistentialTraitRef<'tcx> for T {
+    fn new_from_args(
+        &self,
+        trait_def_id: rustc_span::def_id::DefId,
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> ty::ExistentialTraitRef<'tcx> {
+        ty::ExistentialTraitRef::new_from_args(self.tcx(), trait_def_id, args)
+    }
+}
+
+impl<'tcx, T: InternalCx<'tcx>> SmirTraitRef<'tcx> for T {
+    fn new_from_args(
+        &self,
+        trait_def_id: rustc_span::def_id::DefId,
+        args: ty::GenericArgsRef<'tcx>,
+    ) -> ty::TraitRef<'tcx> {
+        ty::TraitRef::new_from_args(self.tcx(), trait_def_id, args)
+    }
+}
+
+impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> {
+    fn tcx(self) -> TyCtxt<'tcx> {
+        self
+    }
+
+    fn lift<T: ty::Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> {
+        TyCtxt::lift(self, value)
+    }
+
+    fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>,
+    {
+        TyCtxt::mk_args_from_iter(self, iter)
+    }
+
+    fn mk_pat(self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx> {
+        TyCtxt::mk_pat(self, v)
+    }
+
+    fn mk_poly_existential_predicates(
+        self,
+        eps: &[ty::PolyExistentialPredicate<'tcx>],
+    ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
+        TyCtxt::mk_poly_existential_predicates(self, eps)
+    }
+
+    fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
+        TyCtxt::mk_type_list(self, v)
+    }
+
+    fn lifetimes_re_erased(self) -> ty::Region<'tcx> {
+        self.lifetimes.re_erased
+    }
+    
+    fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
+    {
+        TyCtxt::mk_bound_variable_kinds_from_iter(self, iter)
+    }
+    
+    fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>> {
+        TyCtxt::mk_place_elems(self, v)
+    }
+
+    fn adt_def(self, def_id: rustc_hir::def_id::DefId) -> ty::AdtDef<'tcx> {
+        self.adt_def(def_id)
+    }
+}
+
+/// Trait that defines the methods that are fine to call from [`RustcInternal`].
+/// 
+/// This trait is only for [`RustcInternal`]. Any other other access to rustc's internals
+/// should go through [`crate::rustc_smir::context::SmirCtxt`].
+pub trait InternalCx<'tcx> : Copy + Clone {
+    fn tcx(self) -> TyCtxt<'tcx>;
+
+    fn lift<T: ty::Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted>;
+
+    fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>;
+
+    fn mk_pat(self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx>;
+
+    fn mk_poly_existential_predicates(
+        self,
+        eps: &[ty::PolyExistentialPredicate<'tcx>],
+    ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>>;
+
+    fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>>;
+
+    fn lifetimes_re_erased(self) -> ty::Region<'tcx>;
+
+    fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>;
+
+    fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>>;
+
+    fn adt_def(self, def_id: rustc_hir::def_id::DefId) -> ty::AdtDef<'tcx>;
+}
+
+/// Trait used to convert between an internal MIR type to a Stable MIR type.
+///
+/// This trait is currently exposed to users so they can have interoperability between internal MIR
+/// and StableMIR constructs. However, they should be used seldom and they have no influence
+/// in this crate semver.
+#[doc(hidden)]
+pub trait Stable<'tcx>: PointeeSized {
+    /// The stable representation of the type implementing Stable.
+    type T;
+    /// Converts an object to the equivalent Stable MIR representation.
+    fn stable<'cx>(
+        &self,
+        tables: &mut Tables<'cx, BridgeTys>,
+        cx: &SmirCtxt<'cx, BridgeTys>,
+    ) -> Self::T;
+}
+
+/// Trait used to translate a stable construct to its rustc counterpart.
+///
+/// This is basically a mirror of [Stable].
+///
+/// This trait is currently exposed to users so they can have interoperability between internal MIR
+/// and StableMIR constructs. They should be used seldom as they have no stability guarantees.
+#[doc(hidden)]
+pub trait RustcInternal {
+    type T<'tcx>;
+    fn internal<'tcx>(
+        &self,
+        tables: &mut Tables<'_, BridgeTys>,
+        tcx: impl InternalCx<'tcx>,
+    ) -> Self::T<'tcx>;
+}
+
+pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind {
+    match kind {
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::AssocTy
+        | DefKind::TyParam
+        | DefKind::ConstParam
+        | DefKind::Macro(_)
+        | DefKind::ExternCrate
+        | DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::OpaqueTy
+        | DefKind::Field
+        | DefKind::LifetimeParam
+        | DefKind::Impl { .. }
+        | DefKind::GlobalAsm => {
+            unreachable!("Not a valid item kind: {kind:?}");
+        }
+        DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => {
+            ItemKind::Fn
+        }
+        DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => {
+            ItemKind::Const
+        }
+        DefKind::Static { .. } => ItemKind::Static,
+        DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const),
+        DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn),
+    }
+}