From 9aace6723572438a94378451793ca37deb768e72 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Wed, 17 Jan 2024 18:35:19 -0800 Subject: [PATCH] Ensure internal function is safe The internal function was unsound, it could cause UB in rare cases where the user inadvertly stored the returned object in a location that could outlive the TyCtxt. In order to make it safe, we now take a type context as an argument to the internal fn, and we ensure that interned items are lifted using the provided context. Thus, this change ensures that the compiler can properly enforce that the object does not outlive the type context it was lifted to. --- .../rustc_smir/src/rustc_internal/internal.rs | 333 ++++++++++-------- compiler/rustc_smir/src/rustc_internal/mod.rs | 39 +- compiler/rustc_smir/src/rustc_smir/alloc.rs | 3 +- compiler/rustc_smir/src/rustc_smir/context.rs | 117 +++--- tests/ui-fulldeps/stable-mir/smir_internal.rs | 4 +- 5 files changed, 296 insertions(+), 200 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 5689e8f3b3d..01260659fd5 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -5,7 +5,7 @@ // Prefer importing stable_mir over internal rustc constructs to make this file more readable. use crate::rustc_smir::Tables; -use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy}; +use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy, TyCtxt}; use rustc_span::Symbol; use stable_mir::abi::Layout; use stable_mir::mir::alloc::AllocId; @@ -21,118 +21,120 @@ use stable_mir::{CrateItem, CrateNum, DefId}; use super::RustcInternal; -impl<'tcx> RustcInternal<'tcx> for CrateItem { +unsafe impl<'tcx> RustcInternal<'tcx> for CrateItem { type T = rustc_span::def_id::DefId; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - self.0.internal(tables) + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + self.0.internal(tables, tcx) } } -impl<'tcx> RustcInternal<'tcx> for CrateNum { +unsafe impl<'tcx> RustcInternal<'tcx> for CrateNum { type T = rustc_span::def_id::CrateNum; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { rustc_span::def_id::CrateNum::from_usize(*self) } } -impl<'tcx> RustcInternal<'tcx> for DefId { +unsafe impl<'tcx> RustcInternal<'tcx> for DefId { type T = rustc_span::def_id::DefId; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - tables.def_ids[*self] + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + tcx.lift(tables.def_ids[*self]).unwrap() } } -impl<'tcx> RustcInternal<'tcx> for GenericArgs { +unsafe impl<'tcx> RustcInternal<'tcx> for GenericArgs { type T = rustc_ty::GenericArgsRef<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - tables.tcx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables))) + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + tcx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables, tcx))) } } -impl<'tcx> RustcInternal<'tcx> for GenericArgKind { +unsafe impl<'tcx> RustcInternal<'tcx> for GenericArgKind { type T = rustc_ty::GenericArg<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - match self { - GenericArgKind::Lifetime(reg) => reg.internal(tables).into(), - GenericArgKind::Type(ty) => ty.internal(tables).into(), - GenericArgKind::Const(cnst) => ty_const(cnst, tables).into(), - } + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + 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) => ty_const(cnst, tables, tcx).into(), + }; + tcx.lift(arg).unwrap() } } -impl<'tcx> RustcInternal<'tcx> for Region { +unsafe impl<'tcx> RustcInternal<'tcx> for Region { type T = rustc_ty::Region<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - // Cannot recover region. Use erased instead. - tables.tcx.lifetimes.re_erased + fn internal(&self, _tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + // Cannot recover region. Use erased for now. + tcx.lifetimes.re_erased } } -impl<'tcx> RustcInternal<'tcx> for Ty { +unsafe impl<'tcx> RustcInternal<'tcx> for Ty { type T = InternalTy<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - tables.types[*self] + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + tcx.lift(tables.types[*self]).unwrap() } } -impl<'tcx> RustcInternal<'tcx> for RigidTy { +unsafe impl<'tcx> RustcInternal<'tcx> for RigidTy { type T = rustc_ty::TyKind<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { 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)), - RigidTy::Uint(uint_ty) => rustc_ty::TyKind::Uint(uint_ty.internal(tables)), - RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables)), + 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), ty_const(cnst, tables)) + rustc_ty::TyKind::Array(ty.internal(tables, tcx), ty_const(cnst, tables, tcx)) } RigidTy::Adt(def, args) => { - rustc_ty::TyKind::Adt(def.internal(tables), args.internal(tables)) + 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)), + RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables, tcx)), RigidTy::RawPtr(ty, mutability) => rustc_ty::TyKind::RawPtr(rustc_ty::TypeAndMut { - ty: ty.internal(tables), - mutbl: mutability.internal(tables), + ty: ty.internal(tables, tcx), + mutbl: mutability.internal(tables, tcx), }), RigidTy::Ref(region, ty, mutability) => rustc_ty::TyKind::Ref( - region.internal(tables), - ty.internal(tables), - mutability.internal(tables), + region.internal(tables, tcx), + ty.internal(tables, tcx), + mutability.internal(tables, tcx), ), - RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables)), + RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables, tcx)), RigidTy::FnDef(def, args) => { - rustc_ty::TyKind::FnDef(def.0.internal(tables), args.internal(tables)) + rustc_ty::TyKind::FnDef(def.0.internal(tables, tcx), args.internal(tables, tcx)) } - RigidTy::FnPtr(sig) => rustc_ty::TyKind::FnPtr(sig.internal(tables)), + RigidTy::FnPtr(sig) => rustc_ty::TyKind::FnPtr(sig.internal(tables, tcx)), RigidTy::Closure(def, args) => { - rustc_ty::TyKind::Closure(def.0.internal(tables), args.internal(tables)) + 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), args.internal(tables)) - } - RigidTy::CoroutineWitness(def, args) => { - rustc_ty::TyKind::CoroutineWitness(def.0.internal(tables), args.internal(tables)) + rustc_ty::TyKind::Coroutine(def.0.internal(tables, tcx), args.internal(tables, tcx)) } + RigidTy::CoroutineWitness(def, args) => rustc_ty::TyKind::CoroutineWitness( + def.0.internal(tables, tcx), + args.internal(tables, tcx), + ), RigidTy::Dynamic(predicate, region, dyn_kind) => rustc_ty::TyKind::Dynamic( - tables.tcx.mk_poly_existential_predicates(&predicate.internal(tables)), - region.internal(tables), - dyn_kind.internal(tables), + 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(tables.tcx.mk_type_list(&tys.internal(tables))) + rustc_ty::TyKind::Tuple(tcx.mk_type_list(&tys.internal(tables, tcx))) } } } } -impl<'tcx> RustcInternal<'tcx> for IntTy { +unsafe impl<'tcx> RustcInternal<'tcx> for IntTy { type T = rustc_ty::IntTy; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match self { IntTy::Isize => rustc_ty::IntTy::Isize, IntTy::I8 => rustc_ty::IntTy::I8, @@ -144,10 +146,10 @@ impl<'tcx> RustcInternal<'tcx> for IntTy { } } -impl<'tcx> RustcInternal<'tcx> for UintTy { +unsafe impl<'tcx> RustcInternal<'tcx> for UintTy { type T = rustc_ty::UintTy; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match self { UintTy::Usize => rustc_ty::UintTy::Usize, UintTy::U8 => rustc_ty::UintTy::U8, @@ -159,10 +161,10 @@ impl<'tcx> RustcInternal<'tcx> for UintTy { } } -impl<'tcx> RustcInternal<'tcx> for FloatTy { +unsafe impl<'tcx> RustcInternal<'tcx> for FloatTy { type T = rustc_ty::FloatTy; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match self { FloatTy::F32 => rustc_ty::FloatTy::F32, FloatTy::F64 => rustc_ty::FloatTy::F64, @@ -170,10 +172,10 @@ impl<'tcx> RustcInternal<'tcx> for FloatTy { } } -impl<'tcx> RustcInternal<'tcx> for Mutability { +unsafe impl<'tcx> RustcInternal<'tcx> for Mutability { type T = rustc_ty::Mutability; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match self { Mutability::Not => rustc_ty::Mutability::Not, Mutability::Mut => rustc_ty::Mutability::Mut, @@ -181,10 +183,10 @@ impl<'tcx> RustcInternal<'tcx> for Mutability { } } -impl<'tcx> RustcInternal<'tcx> for Movability { +unsafe impl<'tcx> RustcInternal<'tcx> for Movability { type T = rustc_ty::Movability; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match self { Movability::Static => rustc_ty::Movability::Static, Movability::Movable => rustc_ty::Movability::Movable, @@ -192,37 +194,44 @@ impl<'tcx> RustcInternal<'tcx> for Movability { } } -impl<'tcx> RustcInternal<'tcx> for FnSig { +unsafe impl<'tcx> RustcInternal<'tcx> for FnSig { type T = rustc_ty::FnSig<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - rustc_ty::FnSig { - inputs_and_output: tables.tcx.mk_type_list(&self.inputs_and_output.internal(tables)), + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + tcx.lift(rustc_ty::FnSig { + inputs_and_output: tables + .tcx + .mk_type_list(&self.inputs_and_output.internal(tables, tcx)), c_variadic: self.c_variadic, - unsafety: self.unsafety.internal(tables), - abi: self.abi.internal(tables), - } + unsafety: self.unsafety.internal(tables, tcx), + abi: self.abi.internal(tables, tcx), + }) + .unwrap() } } -impl<'tcx> RustcInternal<'tcx> for VariantIdx { +unsafe impl<'tcx> RustcInternal<'tcx> for VariantIdx { type T = rustc_target::abi::VariantIdx; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { rustc_target::abi::VariantIdx::from(self.to_index()) } } -impl<'tcx> RustcInternal<'tcx> for VariantDef { +unsafe impl<'tcx> RustcInternal<'tcx> for VariantDef { type T = &'tcx rustc_ty::VariantDef; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - self.adt_def.internal(tables).variant(self.idx.internal(tables)) + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + self.adt_def.internal(tables, tcx).variant(self.idx.internal(tables, tcx)) } } -fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Const<'tcx> { - match constant.internal(tables) { +fn ty_const<'tcx>( + constant: &Const, + tables: &mut Tables<'tcx>, + tcx: TyCtxt<'tcx>, +) -> rustc_ty::Const<'tcx> { + match constant.internal(tables, tcx) { rustc_middle::mir::Const::Ty(c) => c, cnst => { panic!("Trying to convert constant `{constant:?}` to type constant, but found {cnst:?}") @@ -230,21 +239,33 @@ fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Cons } } -impl<'tcx> RustcInternal<'tcx> for Const { +unsafe impl<'tcx> RustcInternal<'tcx> for Const { type T = rustc_middle::mir::Const<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - tables.constants[self.id] + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + let constant = tables.constants[self.id]; + match constant { + rustc_middle::mir::Const::Ty(ty) => rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap()), + rustc_middle::mir::Const::Unevaluated(uneval, ty) => { + rustc_middle::mir::Const::Unevaluated( + lift_unevaluated(tcx, uneval), + tcx.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()) + } + } } } -impl<'tcx> RustcInternal<'tcx> for MonoItem { +unsafe impl<'tcx> RustcInternal<'tcx> for MonoItem { type T = rustc_middle::mir::mono::MonoItem<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { use rustc_middle::mir::mono as rustc_mono; match self { - MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables)), - MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables)), + 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!() } @@ -252,55 +273,56 @@ impl<'tcx> RustcInternal<'tcx> for MonoItem { } } -impl<'tcx> RustcInternal<'tcx> for Instance { +unsafe impl<'tcx> RustcInternal<'tcx> for Instance { type T = rustc_ty::Instance<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - tables.instances[self.def] + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + tcx.lift(tables.instances[self.def]).unwrap() } } -impl<'tcx> RustcInternal<'tcx> for StaticDef { +unsafe impl<'tcx> RustcInternal<'tcx> for StaticDef { type T = rustc_span::def_id::DefId; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - self.0.internal(tables) + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + self.0.internal(tables, tcx) } } #[allow(rustc::usage_of_qualified_ty)] -impl<'tcx, T> RustcInternal<'tcx> for Binder +unsafe impl<'tcx, T> RustcInternal<'tcx> for Binder where T: RustcInternal<'tcx>, T::T: rustc_ty::TypeVisitable>, { type T = rustc_ty::Binder<'tcx, T::T>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { rustc_ty::Binder::bind_with_vars( - self.value.internal(tables), - tables.tcx.mk_bound_variable_kinds_from_iter( - self.bound_vars.iter().map(|bound| bound.internal(tables)), + self.value.internal(tables, tcx), + tcx.mk_bound_variable_kinds_from_iter( + self.bound_vars.iter().map(|bound| bound.internal(tables, tcx)), ), ) } } -impl<'tcx> RustcInternal<'tcx> for BoundVariableKind { +unsafe impl<'tcx> RustcInternal<'tcx> for BoundVariableKind { type T = rustc_ty::BoundVariableKind; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { 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), Symbol::intern(symbol)) - } + BoundTyKind::Param(def, 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::BrAnon, BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::BrNamed( - def.0.internal(tables), + def.0.internal(tables, tcx), Symbol::intern(symbol), ), BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::BrEnv, @@ -310,10 +332,10 @@ impl<'tcx> RustcInternal<'tcx> for BoundVariableKind { } } -impl<'tcx> RustcInternal<'tcx> for DynKind { +unsafe impl<'tcx> RustcInternal<'tcx> for DynKind { type T = rustc_ty::DynKind; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match self { DynKind::Dyn => rustc_ty::DynKind::Dyn, DynKind::DynStar => rustc_ty::DynKind::DynStar, @@ -321,81 +343,81 @@ impl<'tcx> RustcInternal<'tcx> for DynKind { } } -impl<'tcx> RustcInternal<'tcx> for ExistentialPredicate { +unsafe impl<'tcx> RustcInternal<'tcx> for ExistentialPredicate { type T = rustc_ty::ExistentialPredicate<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { match self { ExistentialPredicate::Trait(trait_ref) => { - rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables)) + rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables, tcx)) } ExistentialPredicate::Projection(proj) => { - rustc_ty::ExistentialPredicate::Projection(proj.internal(tables)) + rustc_ty::ExistentialPredicate::Projection(proj.internal(tables, tcx)) } ExistentialPredicate::AutoTrait(trait_def) => { - rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables)) + rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables, tcx)) } } } } -impl<'tcx> RustcInternal<'tcx> for ExistentialProjection { +unsafe impl<'tcx> RustcInternal<'tcx> for ExistentialProjection { type T = rustc_ty::ExistentialProjection<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { rustc_ty::ExistentialProjection { - def_id: self.def_id.0.internal(tables), - args: self.generic_args.internal(tables), - term: self.term.internal(tables), + def_id: self.def_id.0.internal(tables, tcx), + args: self.generic_args.internal(tables, tcx), + term: self.term.internal(tables, tcx), } } } -impl<'tcx> RustcInternal<'tcx> for TermKind { +unsafe impl<'tcx> RustcInternal<'tcx> for TermKind { type T = rustc_ty::Term<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { match self { - TermKind::Type(ty) => ty.internal(tables).into(), - TermKind::Const(const_) => ty_const(const_, tables).into(), + TermKind::Type(ty) => ty.internal(tables, tcx).into(), + TermKind::Const(const_) => ty_const(const_, tables, tcx).into(), } } } -impl<'tcx> RustcInternal<'tcx> for ExistentialTraitRef { +unsafe impl<'tcx> RustcInternal<'tcx> for ExistentialTraitRef { type T = rustc_ty::ExistentialTraitRef<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { rustc_ty::ExistentialTraitRef { - def_id: self.def_id.0.internal(tables), - args: self.generic_args.internal(tables), + def_id: self.def_id.0.internal(tables, tcx), + args: self.generic_args.internal(tables, tcx), } } } -impl<'tcx> RustcInternal<'tcx> for TraitRef { +unsafe impl<'tcx> RustcInternal<'tcx> for TraitRef { type T = rustc_ty::TraitRef<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { rustc_ty::TraitRef::new( - tables.tcx, - self.def_id.0.internal(tables), - self.args().internal(tables), + tcx, + self.def_id.0.internal(tables, tcx), + self.args().internal(tables, tcx), ) } } -impl<'tcx> RustcInternal<'tcx> for AllocId { +unsafe impl<'tcx> RustcInternal<'tcx> for AllocId { type T = rustc_middle::mir::interpret::AllocId; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - tables.alloc_ids[*self] + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + tcx.lift(tables.alloc_ids[*self]).unwrap() } } -impl<'tcx> RustcInternal<'tcx> for ClosureKind { +unsafe impl<'tcx> RustcInternal<'tcx> for ClosureKind { type T = rustc_ty::ClosureKind; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match self { ClosureKind::Fn => rustc_ty::ClosureKind::Fn, ClosureKind::FnMut => rustc_ty::ClosureKind::FnMut, @@ -404,17 +426,17 @@ impl<'tcx> RustcInternal<'tcx> for ClosureKind { } } -impl<'tcx> RustcInternal<'tcx> for AdtDef { +unsafe impl<'tcx> RustcInternal<'tcx> for AdtDef { type T = rustc_ty::AdtDef<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - tables.tcx.adt_def(self.0.internal(&mut *tables)) + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + tcx.adt_def(self.0.internal(tables, tcx)) } } -impl<'tcx> RustcInternal<'tcx> for Abi { +unsafe impl<'tcx> RustcInternal<'tcx> for Abi { type T = rustc_target::spec::abi::Abi; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match *self { Abi::Rust => rustc_target::spec::abi::Abi::Rust, Abi::C { unwind } => rustc_target::spec::abi::Abi::C { unwind }, @@ -447,10 +469,10 @@ impl<'tcx> RustcInternal<'tcx> for Abi { } } -impl<'tcx> RustcInternal<'tcx> for Safety { +unsafe impl<'tcx> RustcInternal<'tcx> for Safety { type T = rustc_hir::Unsafety; - fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, _tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { match self { Safety::Unsafe => rustc_hir::Unsafety::Unsafe, Safety::Normal => rustc_hir::Unsafety::Normal, @@ -458,51 +480,62 @@ impl<'tcx> RustcInternal<'tcx> for Safety { } } -impl<'tcx> RustcInternal<'tcx> for Span { +unsafe impl<'tcx> RustcInternal<'tcx> for Span { type T = rustc_span::Span; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + fn internal(&self, tables: &mut Tables<'tcx>, _tcx: TyCtxt<'tcx>) -> Self::T { tables[*self] } } -impl<'tcx> RustcInternal<'tcx> for Layout { +unsafe impl<'tcx> RustcInternal<'tcx> for Layout { type T = rustc_target::abi::Layout<'tcx>; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - tables.layouts[*self] + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + tcx.lift(tables.layouts[*self]).unwrap() } } -impl<'tcx, T> RustcInternal<'tcx> for &T +unsafe impl<'tcx, T> RustcInternal<'tcx> for &T where T: RustcInternal<'tcx>, { type T = T::T; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - (*self).internal(tables) + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + (*self).internal(tables, tcx) } } -impl<'tcx, T> RustcInternal<'tcx> for Option +unsafe impl<'tcx, T> RustcInternal<'tcx> for Option where T: RustcInternal<'tcx>, { type T = Option; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - self.as_ref().map(|inner| inner.internal(tables)) + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + self.as_ref().map(|inner| inner.internal(tables, tcx)) } } -impl<'tcx, T> RustcInternal<'tcx> for Vec +unsafe impl<'tcx, T> RustcInternal<'tcx> for Vec where T: RustcInternal<'tcx>, { type T = Vec; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { - self.iter().map(|e| e.internal(tables)).collect() + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T { + self.iter().map(|e| e.internal(tables, tcx)).collect() + } +} + +fn lift_unevaluated<'tcx>( + tcx: TyCtxt<'tcx>, + uneval: rustc_middle::mir::UnevaluatedConst<'tcx>, +) -> rustc_middle::mir::UnevaluatedConst<'tcx> { + rustc_middle::mir::UnevaluatedConst { + def: uneval.def, + args: tcx.lift(uneval.args).unwrap(), + promoted: uneval.promoted, } } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index cd4ad724b00..b17ad153ed5 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -24,12 +24,38 @@ use std::ops::Index; mod internal; pub mod pretty; +/// Convert an internal Rust compiler item into its stable counterpart, if one exists. +/// +/// # Warning +/// +/// This function is unstable, and its behavior may change at any point. +/// E.g.: Items that were previously supported, may no longer be supported, or its translation may +/// change. +/// +/// # Panics +/// +/// This function will panic if StableMIR has not been properly initialized. pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T { with_tables(|tables| item.stable(tables)) } -pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: S) -> S::T { - with_tables(|tables| item.internal(tables)) +/// Convert a stable item into its internal Rust compiler counterpart, if one exists. +/// +/// # Warning +/// +/// This function is unstable, and it's behavior may change at any point. +/// Not every stable item can be converted to an internal one. +/// Furthermore, items that were previously supported, may no longer be supported in newer versions. +/// +/// # Panics +/// +/// This function will panic if StableMIR has not been properly initialized. +pub fn internal<'tcx, S>(tcx: TyCtxt<'tcx>, item: S) -> S::T +where + S: RustcInternal<'tcx>, +{ + // The tcx argument ensures that the item won't outlive the type context. + with_tables(|tables| item.internal(tables, tcx)) } impl<'tcx> Index for Tables<'tcx> { @@ -393,7 +419,12 @@ impl Index { +/// +/// # Safety +/// +/// This trait is unsafe, and every implementation should ensure that their translation +/// is lifted if necessary with the given type context (`tcx`). +pub unsafe trait RustcInternal<'tcx> { type T; - fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T; + fn internal(&self, tables: &mut Tables<'tcx>, tcx: TyCtxt<'tcx>) -> Self::T; } diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 48cb164c308..5d02e3d6e92 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -27,7 +27,8 @@ pub fn new_allocation<'tcx>( const_value: ConstValue<'tcx>, tables: &mut Tables<'tcx>, ) -> Allocation { - try_new_allocation(ty, const_value, tables).unwrap() + try_new_allocation(ty, const_value, tables) + .expect(&format!("Failed to convert: {const_value:?} to {ty:?}")) } #[allow(rustc::usage_of_qualified_ty)] diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index fffc454804d..10085f659b3 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -29,7 +29,7 @@ use stable_mir::{Crate, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, S use std::cell::RefCell; use std::iter; -use crate::rustc_internal::{internal, RustcInternal}; +use crate::rustc_internal::RustcInternal; use crate::rustc_smir::builder::BodyBuilder; use crate::rustc_smir::{alloc, new_item_kind, smir_crate, Stable, Tables}; @@ -74,9 +74,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls { let mut tables = self.0.borrow_mut(); - tables - .tcx - .traits(crate_num.internal(&mut *tables)) + let tcx = tables.tcx; + tcx.traits(crate_num.internal(&mut *tables, tcx)) .iter() .map(|trait_def_id| tables.trait_def(*trait_def_id)) .collect() @@ -101,9 +100,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls { let mut tables = self.0.borrow_mut(); - tables - .tcx - .trait_impls_in_crate(crate_num.internal(&mut *tables)) + let tcx = tables.tcx; + tcx.trait_impls_in_crate(crate_num.internal(&mut *tables, tcx)) .iter() .map(|impl_def_id| tables.impl_def(*impl_def_id)) .collect() @@ -229,57 +227,68 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn adt_kind(&self, def: AdtDef) -> AdtKind { let mut tables = self.0.borrow_mut(); - def.internal(&mut *tables).adt_kind().stable(&mut *tables) + let tcx = tables.tcx; + def.internal(&mut *tables, tcx).adt_kind().stable(&mut *tables) } fn adt_is_box(&self, def: AdtDef) -> bool { let mut tables = self.0.borrow_mut(); - def.internal(&mut *tables).is_box() + let tcx = tables.tcx; + def.internal(&mut *tables, tcx).is_box() } fn adt_is_simd(&self, def: AdtDef) -> bool { let mut tables = self.0.borrow_mut(); - def.internal(&mut *tables).repr().simd() + let tcx = tables.tcx; + def.internal(&mut *tables, tcx).repr().simd() } fn adt_is_cstr(&self, def: AdtDef) -> bool { let mut tables = self.0.borrow_mut(); - let def_id = def.0.internal(&mut *tables); + let tcx = tables.tcx; + let def_id = def.0.internal(&mut *tables, tcx); tables.tcx.lang_items().c_str() == Some(def_id) } fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { let mut tables = self.0.borrow_mut(); - let def_id = def.0.internal(&mut *tables); - let sig = tables.tcx.fn_sig(def_id).instantiate(tables.tcx, args.internal(&mut *tables)); + let tcx = tables.tcx; + let def_id = def.0.internal(&mut *tables, tcx); + let sig = + tables.tcx.fn_sig(def_id).instantiate(tables.tcx, args.internal(&mut *tables, tcx)); sig.stable(&mut *tables) } fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { let mut tables = self.0.borrow_mut(); - let args_ref = args.internal(&mut *tables); + let tcx = tables.tcx; + let args_ref = args.internal(&mut *tables, tcx); let sig = args_ref.as_closure().sig(); sig.stable(&mut *tables) } fn adt_variants_len(&self, def: AdtDef) -> usize { let mut tables = self.0.borrow_mut(); - def.internal(&mut *tables).variants().len() + let tcx = tables.tcx; + def.internal(&mut *tables, tcx).variants().len() } fn variant_name(&self, def: VariantDef) -> Symbol { let mut tables = self.0.borrow_mut(); - def.internal(&mut *tables).name.to_string() + let tcx = tables.tcx; + def.internal(&mut *tables, tcx).name.to_string() } fn variant_fields(&self, def: VariantDef) -> Vec { let mut tables = self.0.borrow_mut(); - def.internal(&mut *tables).fields.iter().map(|f| f.stable(&mut *tables)).collect() + let tcx = tables.tcx; + def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect() } fn eval_target_usize(&self, cnst: &Const) -> Result { let mut tables = self.0.borrow_mut(); - let mir_const = cnst.internal(&mut *tables); + let tcx = tables.tcx; + let mir_const = cnst.internal(&mut *tables, tcx); mir_const .try_eval_target_usize(tables.tcx, ParamEnv::empty()) .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) @@ -299,30 +308,36 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); - let internal_kind = kind.internal(&mut *tables); + let tcx = tables.tcx; + let internal_kind = kind.internal(&mut *tables, tcx); tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables) } fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); - let inner = ty.internal(&mut *tables); + let tcx = tables.tcx; + let inner = ty.internal(&mut *tables, tcx); ty::Ty::new_box(tables.tcx, inner).stable(&mut *tables) } fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); - tables.tcx.type_of(item.internal(&mut *tables)).instantiate_identity().stable(&mut *tables) + let tcx = tables.tcx; + tcx.type_of(item.internal(&mut *tables, tcx)).instantiate_identity().stable(&mut *tables) } fn def_ty_with_args(&self, item: stable_mir::DefId, args: &GenericArgs) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); - let args = args.internal(&mut *tables); - let def_ty = tables.tcx.type_of(item.internal(&mut *tables)); + let tcx = tables.tcx; + let args = args.internal(&mut *tables, tcx); + let def_ty = tables.tcx.type_of(item.internal(&mut *tables, tcx)); def_ty.instantiate(tables.tcx, args).stable(&mut *tables) } fn const_literal(&self, cnst: &stable_mir::ty::Const) -> String { - internal(cnst).to_string() + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + cnst.internal(&mut *tables, tcx).to_string() } fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span { @@ -337,7 +352,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); - let internal_kind = ty.internal(&mut *tables); + let tcx = tables.tcx; + let internal_kind = ty.internal(&mut *tables, tcx); let internal_ty = tables.tcx.mk_ty_from_kind(internal_kind); internal_ty.discriminant_ty(tables.tcx).stable(&mut *tables) } @@ -407,8 +423,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> { args: &stable_mir::ty::GenericArgs, ) -> Option { let mut tables = self.0.borrow_mut(); - let def_id = def.0.internal(&mut *tables); - let args_ref = args.internal(&mut *tables); + let tcx = tables.tcx; + let def_id = def.0.internal(&mut *tables, tcx); + let args_ref = args.internal(&mut *tables, tcx); match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) { Ok(Some(instance)) => Some(instance.stable(&mut *tables)), Ok(None) | Err(_) => None, @@ -417,7 +434,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance { let mut tables = self.0.borrow_mut(); - let internal_ty = ty.internal(&mut *tables); + let tcx = tables.tcx; + let internal_ty = ty.internal(&mut *tables, tcx); let instance = Instance::resolve_drop_in_place(tables.tcx, internal_ty); instance.stable(&mut *tables) } @@ -428,8 +446,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> { args: &GenericArgs, ) -> Option { let mut tables = self.0.borrow_mut(); - let def_id = def.0.internal(&mut *tables); - let args_ref = args.internal(&mut *tables); + let tcx = tables.tcx; + let def_id = def.0.internal(&mut *tables, tcx); + let args_ref = args.internal(&mut *tables, tcx); Instance::resolve_for_fn_ptr(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) .stable(&mut *tables) } @@ -441,36 +460,44 @@ impl<'tcx> Context for TablesWrapper<'tcx> { kind: ClosureKind, ) -> Option { let mut tables = self.0.borrow_mut(); - let def_id = def.0.internal(&mut *tables); - let args_ref = args.internal(&mut *tables); - let closure_kind = kind.internal(&mut *tables); + let tcx = tables.tcx; + let def_id = def.0.internal(&mut *tables, tcx); + let args_ref = args.internal(&mut *tables, tcx); + let closure_kind = kind.internal(&mut *tables, tcx); Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind).stable(&mut *tables) } fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result { let mut tables = self.0.borrow_mut(); let instance = tables.instances[def]; - let result = tables.tcx.const_eval_instance( + let tcx = tables.tcx; + let result = tcx.const_eval_instance( ParamEnv::reveal_all(), instance, - Some(tables.tcx.def_span(instance.def_id())), + Some(tcx.def_span(instance.def_id())), ); result .map(|const_val| { - alloc::try_new_allocation(const_ty.internal(&mut *tables), const_val, &mut *tables) + alloc::try_new_allocation( + const_ty.internal(&mut *tables, tcx), + const_val, + &mut *tables, + ) }) .map_err(|e| e.stable(&mut *tables))? } fn eval_static_initializer(&self, def: StaticDef) -> Result { let mut tables = self.0.borrow_mut(); - let def_id = def.0.internal(&mut *tables); + let tcx = tables.tcx; + let def_id = def.0.internal(&mut *tables, tcx); tables.tcx.eval_static_initializer(def_id).stable(&mut *tables) } fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc { let mut tables = self.0.borrow_mut(); - let alloc_id = alloc.internal(&mut *tables); + let tcx = tables.tcx; + let alloc_id = alloc.internal(&mut *tables, tcx); tables.tcx.global_alloc(alloc_id).stable(&mut *tables) } @@ -480,9 +507,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { ) -> Option { let mut tables = self.0.borrow_mut(); let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { return None }; - let alloc_id = tables - .tcx - .vtable_allocation((ty.internal(&mut *tables), trait_ref.internal(&mut *tables))); + let tcx = tables.tcx; + let alloc_id = tables.tcx.vtable_allocation(( + ty.internal(&mut *tables, tcx), + trait_ref.internal(&mut *tables, tcx), + )); Some(alloc_id.stable(&mut *tables)) } @@ -510,14 +539,16 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn ty_layout(&self, ty: Ty) -> Result { let mut tables = self.0.borrow_mut(); - let ty = ty.internal(&mut *tables); + let tcx = tables.tcx; + let ty = ty.internal(&mut *tables, tcx); let layout = tables.layout_of(ty)?.layout; Ok(layout.stable(&mut *tables)) } fn layout_shape(&self, id: Layout) -> LayoutShape { let mut tables = self.0.borrow_mut(); - id.internal(&mut *tables).0.stable(&mut *tables) + let tcx = tables.tcx; + id.internal(&mut *tables, tcx).0.stable(&mut *tables) } } diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index b4faaeb4fc0..e23b0f6820a 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -26,11 +26,11 @@ use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; -fn test_translation(_tcx: TyCtxt) -> ControlFlow<()> { +fn test_translation(tcx: TyCtxt<'_>) -> ControlFlow<()> { let main_fn = stable_mir::entry_fn().unwrap(); let body = main_fn.body(); let orig_ty = body.locals()[0].ty; - let rustc_ty = rustc_internal::internal(&orig_ty); + let rustc_ty = rustc_internal::internal(tcx, &orig_ty); assert!(rustc_ty.is_unit()); ControlFlow::Continue(()) }