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.
This commit is contained in:
Celina G. Val 2024-01-17 18:35:19 -08:00 committed by Oli Scherer
parent 61361c16aa
commit 9aace67235
5 changed files with 296 additions and 200 deletions

View File

@ -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<T>
unsafe impl<'tcx, T> RustcInternal<'tcx> for Binder<T>
where
T: RustcInternal<'tcx>,
T::T: rustc_ty::TypeVisitable<rustc_ty::TyCtxt<'tcx>>,
{
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<T>
unsafe impl<'tcx, T> RustcInternal<'tcx> for Option<T>
where
T: RustcInternal<'tcx>,
{
type T = Option<T::T>;
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<T>
unsafe impl<'tcx, T> RustcInternal<'tcx> for Vec<T>
where
T: RustcInternal<'tcx>,
{
type T = Vec<T::T>;
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,
}
}

View File

@ -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<stable_mir::DefId> for Tables<'tcx> {
@ -393,7 +419,12 @@ impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V
/// Trait used to translate a stable construct to its rustc counterpart.
///
/// This is basically a mirror of [crate::rustc_smir::Stable].
pub trait RustcInternal<'tcx> {
///
/// # 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;
}

View File

@ -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)]

View File

@ -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<FieldDef> {
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<u64, Error> {
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<stable_mir::mir::mono::Instance> {
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<stable_mir::mir::mono::Instance> {
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<stable_mir::mir::mono::Instance> {
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<Allocation, Error> {
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<Allocation, Error> {
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<stable_mir::mir::alloc::AllocId> {
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<Layout, Error> {
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)
}
}

View File

@ -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(())
}