Auto merge of #117113 - celinval:smir-stable-ty, r=oli-obk

Remove fold code and add `Const::internal()` to StableMIR

We are not planning to support user generated constant in the foreseeable future, so we are cleaning up the fold logic and user created type for now. Users should use `Instance::resolve` in order to trigger monomorphization.

The Instance::resolve was however incomplete, since we weren't handling internalizing constants yet. Thus, I added that.

I decided to keep the `Const` fields private in case we decide to translate them lazily.
This commit is contained in:
bors 2023-10-25 13:19:54 +00:00
commit b66fe58f68
10 changed files with 155 additions and 421 deletions

View File

@ -13,6 +13,7 @@
#![cfg_attr(not(bootstrap), doc(rust_logo))]
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![cfg_attr(not(bootstrap), allow(internal_features))]
#![allow(rustc::usage_of_ty_tykind)]
pub mod rustc_internal;

View File

@ -4,7 +4,7 @@
//! due to incomplete stable coverage.
// Prefer importing stable_mir over internal rustc constructs to make this file more readable.
use crate::rustc_smir::{MaybeStable, Tables};
use crate::rustc_smir::Tables;
use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
use stable_mir::ty::{Const, GenericArgKind, GenericArgs, Region, Ty};
use stable_mir::DefId;
@ -31,7 +31,7 @@ impl<'tcx> RustcInternal<'tcx> for GenericArgKind {
match self {
GenericArgKind::Lifetime(reg) => reg.internal(tables).into(),
GenericArgKind::Type(ty) => ty.internal(tables).into(),
GenericArgKind::Const(cnst) => cnst.internal(tables).into(),
GenericArgKind::Const(cnst) => ty_const(cnst, tables).into(),
}
}
}
@ -46,16 +46,22 @@ impl<'tcx> RustcInternal<'tcx> for Region {
impl<'tcx> RustcInternal<'tcx> for Ty {
type T = InternalTy<'tcx>;
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
match tables.types[self.0] {
MaybeStable::Stable(_) => todo!(),
MaybeStable::Rustc(ty) => ty,
tables.types[*self]
}
}
fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Const<'tcx> {
match constant.internal(tables) {
rustc_middle::mir::Const::Ty(c) => c,
cnst => {
panic!("Trying to covert constant `{constant:?}` to type constant, but found {cnst:?}")
}
}
}
impl<'tcx> RustcInternal<'tcx> for Const {
type T = rustc_ty::Const<'tcx>;
fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
todo!()
type T = rustc_middle::mir::Const<'tcx>;
fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
tables.constants[self.id]
}
}

View File

@ -167,8 +167,9 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
def_ids: IndexMap::default(),
alloc_ids: IndexMap::default(),
spans: IndexMap::default(),
types: vec![],
types: IndexMap::default(),
instances: IndexMap::default(),
constants: IndexMap::default(),
}));
stable_mir::run(&tables, || init(&tables, f));
}

View File

@ -20,7 +20,8 @@ use rustc_target::abi::FieldIdx;
use stable_mir::mir::mono::InstanceDef;
use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
use stable_mir::ty::{
FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy,
Const, ConstId, ConstantKind, FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy,
Span, TyKind, UintTy,
};
use stable_mir::{self, opaque, Context, Filename};
use std::cell::RefCell;
@ -147,14 +148,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
let mut tables = self.0.borrow_mut();
tables.types[ty.0].clone().stable(&mut *tables)
}
fn mk_ty(&self, kind: TyKind) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let n = tables.types.len();
tables.types.push(MaybeStable::Stable(kind));
stable_mir::ty::Ty(n)
tables.types[ty].kind().stable(&mut *tables)
}
fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
@ -213,8 +207,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
let ty = instance.ty(tables.tcx, ParamEnv::empty());
tables.intern_ty(ty)
instance.ty(tables.tcx, ParamEnv::empty()).stable(&mut *tables)
}
fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
@ -252,33 +245,6 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
}
}
#[derive(Clone)]
pub enum MaybeStable<S, R> {
Stable(S),
Rustc(R),
}
impl<'tcx, S, R> MaybeStable<S, R> {
fn stable(self, tables: &mut Tables<'tcx>) -> S
where
R: Stable<'tcx, T = S>,
{
match self {
MaybeStable::Stable(s) => s,
MaybeStable::Rustc(r) => r.stable(tables),
}
}
}
impl<S, R: PartialEq> PartialEq<R> for MaybeStable<S, R> {
fn eq(&self, other: &R) -> bool {
match self {
MaybeStable::Stable(_) => false,
MaybeStable::Rustc(r) => r == other,
}
}
}
pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell<Tables<'tcx>>);
pub struct Tables<'tcx> {
@ -286,18 +252,18 @@ pub struct Tables<'tcx> {
pub(crate) def_ids: IndexMap<DefId, stable_mir::DefId>,
pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
pub(crate) spans: IndexMap<rustc_span::Span, Span>,
pub(crate) types: Vec<MaybeStable<TyKind, Ty<'tcx>>>,
pub(crate) types: IndexMap<Ty<'tcx>, stable_mir::ty::Ty>,
pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
pub(crate) constants: IndexMap<mir::Const<'tcx>, ConstId>,
}
impl<'tcx> Tables<'tcx> {
fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
if let Some(id) = self.types.iter().position(|t| *t == ty) {
return stable_mir::ty::Ty(id);
}
let id = self.types.len();
self.types.push(MaybeStable::Rustc(ty));
stable_mir::ty::Ty(id)
self.types.create_or_fetch(ty)
}
fn intern_const(&mut self, constant: mir::Const<'tcx>) -> ConstId {
self.constants.create_or_fetch(constant)
}
}
@ -338,7 +304,7 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
.local_decls
.iter()
.map(|decl| stable_mir::mir::LocalDecl {
ty: tables.intern_ty(decl.ty),
ty: decl.ty.stable(tables),
span: decl.source_info.span.stable(tables),
})
.collect(),
@ -436,7 +402,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast(
cast_kind.stable(tables),
op.stable(tables),
tables.intern_ty(*ty),
ty.stable(tables),
),
BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp(
bin_op.stable(tables),
@ -449,7 +415,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
ops.1.stable(tables),
),
NullaryOp(null_op, ty) => {
stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), tables.intern_ty(*ty))
stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), ty.stable(tables))
}
UnaryOp(un_op, op) => {
stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables))
@ -460,7 +426,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables), operands)
}
ShallowInitBox(op, ty) => {
stable_mir::mir::Rvalue::ShallowInitBox(op.stable(tables), tables.intern_ty(*ty))
stable_mir::mir::Rvalue::ShallowInitBox(op.stable(tables), ty.stable(tables))
}
CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables)),
}
@ -604,7 +570,7 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use stable_mir::ty::TermKind;
match self {
ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)),
ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables)),
ty::TermKind::Const(cnst) => {
let cnst = cnst.stable(tables);
TermKind::Const(cnst)
@ -885,7 +851,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
match self {
mir::AggregateKind::Array(ty) => {
stable_mir::mir::AggregateKind::Array(tables.intern_ty(*ty))
stable_mir::mir::AggregateKind::Array(ty.stable(tables))
}
mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple,
mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => {
@ -1053,7 +1019,7 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> {
use stable_mir::ty::GenericArgKind;
match self {
ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(region.stable(tables)),
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(*ty)),
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(ty.stable(tables)),
ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables)),
}
}
@ -1099,11 +1065,7 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
use stable_mir::ty::{Abi, FnSig};
FnSig {
inputs_and_output: self
.inputs_and_output
.iter()
.map(|ty| tables.intern_ty(ty))
.collect(),
inputs_and_output: self.inputs_and_output.iter().map(|ty| ty.stable(tables)).collect(),
c_variadic: self.c_variadic,
unsafety: self.unsafety.stable(tables),
abi: match self.abi {
@ -1241,9 +1203,16 @@ impl<'tcx> Stable<'tcx> for hir::Movability {
}
impl<'tcx> Stable<'tcx> for Ty<'tcx> {
type T = stable_mir::ty::Ty;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
tables.intern_ty(*self)
}
}
impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
type T = stable_mir::ty::TyKind;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
match self.kind() {
match self {
ty::Bool => TyKind::RigidTy(RigidTy::Bool),
ty::Char => TyKind::RigidTy(RigidTy::Char),
ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables))),
@ -1256,15 +1225,15 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
ty::Foreign(def_id) => TyKind::RigidTy(RigidTy::Foreign(tables.foreign_def(*def_id))),
ty::Str => TyKind::RigidTy(RigidTy::Str),
ty::Array(ty, constant) => {
TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), constant.stable(tables)))
TyKind::RigidTy(RigidTy::Array(ty.stable(tables), constant.stable(tables)))
}
ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(tables.intern_ty(*ty))),
ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables))),
ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
TyKind::RigidTy(RigidTy::RawPtr(tables.intern_ty(*ty), mutbl.stable(tables)))
TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables), mutbl.stable(tables)))
}
ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
region.stable(tables),
tables.intern_ty(*ty),
ty.stable(tables),
mutbl.stable(tables),
)),
ty::FnDef(def_id, generic_args) => {
@ -1291,9 +1260,9 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
movability.stable(tables),
)),
ty::Never => TyKind::RigidTy(RigidTy::Never),
ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
fields.iter().map(|ty| tables.intern_ty(ty)).collect(),
)),
ty::Tuple(fields) => {
TyKind::RigidTy(RigidTy::Tuple(fields.iter().map(|ty| ty.stable(tables)).collect()))
}
ty::Alias(alias_kind, alias_ty) => {
TyKind::Alias(alias_kind.stable(tables), alias_ty.stable(tables))
}
@ -1312,32 +1281,32 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
type T = stable_mir::ty::Const;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
stable_mir::ty::Const {
literal: match self.kind() {
ty::Value(val) => {
let const_val = tables.tcx.valtree_to_const_val((self.ty(), val));
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
self.ty(),
const_val,
tables,
))
}
ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
ty::ErrorCt(_) => unreachable!(),
ty::InferCt(_) => unreachable!(),
ty::BoundCt(_, _) => unimplemented!(),
ty::PlaceholderCt(_) => unimplemented!(),
ty::Unevaluated(uv) => {
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
def: tables.const_def(uv.def),
args: uv.args.stable(tables),
promoted: None,
})
}
ty::ExprCt(_) => unimplemented!(),
},
ty: tables.intern_ty(self.ty()),
}
let kind = match self.kind() {
ty::Value(val) => {
let const_val = tables.tcx.valtree_to_const_val((self.ty(), val));
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
self.ty(),
const_val,
tables,
))
}
ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
ty::ErrorCt(_) => unreachable!(),
ty::InferCt(_) => unreachable!(),
ty::BoundCt(_, _) => unimplemented!(),
ty::PlaceholderCt(_) => unimplemented!(),
ty::Unevaluated(uv) => {
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
def: tables.const_def(uv.def),
args: uv.args.stable(tables),
promoted: None,
})
}
ty::ExprCt(_) => unimplemented!(),
};
let ty = self.ty().stable(tables);
let id = tables.intern_const(mir::Const::Ty(*self));
Const::new(kind, ty, id)
}
}
@ -1422,22 +1391,23 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
match *self {
mir::Const::Ty(c) => c.stable(tables),
mir::Const::Unevaluated(unev_const, ty) => stable_mir::ty::Const {
literal: stable_mir::ty::ConstantKind::Unevaluated(
stable_mir::ty::UnevaluatedConst {
mir::Const::Unevaluated(unev_const, ty) => {
let kind =
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
def: tables.const_def(unev_const.def),
args: unev_const.args.stable(tables),
promoted: unev_const.promoted.map(|u| u.as_u32()),
},
),
ty: tables.intern_ty(ty),
},
mir::Const::Val(val, ty) => stable_mir::ty::Const {
literal: stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
ty, val, tables,
)),
ty: tables.intern_ty(ty),
},
});
let ty = ty.stable(tables);
let id = tables.intern_const(*self);
Const::new(kind, ty, id)
}
mir::Const::Val(val, ty) => {
let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables));
let ty = ty.stable(tables);
let id = tables.intern_const(*self);
Const::new(kind, ty, id)
}
}
}
}
@ -1562,7 +1532,7 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
ClauseKind::TypeOutlives(type_outlives) => {
let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives;
stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate(
tables.intern_ty(a),
a.stable(tables),
b.stable(tables),
))
}
@ -1571,7 +1541,7 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
}
ClauseKind::ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType(
const_.stable(tables),
tables.intern_ty(ty),
ty.stable(tables),
),
ClauseKind::WellFormed(generic_arg) => {
stable_mir::ty::ClauseKind::WellFormed(generic_arg.unpack().stable(tables))
@ -1601,7 +1571,7 @@ impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
let ty::SubtypePredicate { a, b, a_is_expected: _ } = self;
stable_mir::ty::SubtypePredicate { a: tables.intern_ty(*a), b: tables.intern_ty(*b) }
stable_mir::ty::SubtypePredicate { a: a.stable(tables), b: b.stable(tables) }
}
}
@ -1610,7 +1580,7 @@ impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
let ty::CoercePredicate { a, b } = self;
stable_mir::ty::CoercePredicate { a: tables.intern_ty(*a), b: tables.intern_ty(*b) }
stable_mir::ty::CoercePredicate { a: a.stable(tables), b: b.stable(tables) }
}
}

View File

@ -1,245 +0,0 @@
use std::ops::ControlFlow;
use crate::Opaque;
use super::ty::{
Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind,
GenericArgs, Promoted, Region, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst,
};
pub trait Folder: Sized {
type Break;
fn fold_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
ty.super_fold(self)
}
fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> {
c.super_fold(self)
}
fn fold_reg(&mut self, reg: &Region) -> ControlFlow<Self::Break, Region> {
reg.super_fold(self)
}
}
pub trait Foldable: Sized + Clone {
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
self.super_fold(folder)
}
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self>;
}
impl Foldable for Ty {
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
folder.fold_ty(self)
}
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
let mut kind = self.kind();
match &mut kind {
super::ty::TyKind::RigidTy(ty) => *ty = ty.fold(folder)?,
super::ty::TyKind::Alias(_, alias) => alias.args = alias.args.fold(folder)?,
super::ty::TyKind::Param(_) => {}
super::ty::TyKind::Bound(_, _) => {}
}
ControlFlow::Continue(kind.into())
}
}
impl Foldable for Const {
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
folder.fold_const(self)
}
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
let mut this = self.clone();
match &mut this.literal {
super::ty::ConstantKind::Allocated(alloc) => *alloc = alloc.fold(folder)?,
super::ty::ConstantKind::Unevaluated(uv) => *uv = uv.fold(folder)?,
super::ty::ConstantKind::Param(_) => {}
}
this.ty = this.ty.fold(folder)?;
ControlFlow::Continue(this)
}
}
impl Foldable for Opaque {
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(self.clone())
}
}
impl Foldable for Allocation {
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(self.clone())
}
}
impl Foldable for UnevaluatedConst {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
let UnevaluatedConst { def, args, promoted } = self;
ControlFlow::Continue(UnevaluatedConst {
def: def.fold(folder)?,
args: args.fold(folder)?,
promoted: promoted.fold(folder)?,
})
}
}
impl Foldable for ConstDef {
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(*self)
}
}
impl<T: Foldable> Foldable for Option<T> {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(match self {
Some(val) => Some(val.fold(folder)?),
None => None,
})
}
}
impl Foldable for Promoted {
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(*self)
}
}
impl Foldable for GenericArgs {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(GenericArgs(self.0.fold(folder)?))
}
}
impl Foldable for Region {
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
folder.fold_reg(self)
}
fn super_fold<V: Folder>(&self, _: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(self.clone())
}
}
impl Foldable for GenericArgKind {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
let mut this = self.clone();
match &mut this {
GenericArgKind::Lifetime(lt) => *lt = lt.fold(folder)?,
GenericArgKind::Type(t) => *t = t.fold(folder)?,
GenericArgKind::Const(c) => *c = c.fold(folder)?,
}
ControlFlow::Continue(this)
}
}
impl Foldable for RigidTy {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
let mut this = self.clone();
match &mut this {
RigidTy::Bool
| RigidTy::Char
| RigidTy::Int(_)
| RigidTy::Uint(_)
| RigidTy::Float(_)
| RigidTy::Never
| RigidTy::Foreign(_)
| RigidTy::Str => {}
RigidTy::Array(t, c) => {
*t = t.fold(folder)?;
*c = c.fold(folder)?;
}
RigidTy::Slice(inner) => *inner = inner.fold(folder)?,
RigidTy::RawPtr(ty, _) => *ty = ty.fold(folder)?,
RigidTy::Ref(reg, ty, _) => {
*reg = reg.fold(folder)?;
*ty = ty.fold(folder)?
}
RigidTy::FnDef(_, args) => *args = args.fold(folder)?,
RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?,
RigidTy::Closure(_, args) => *args = args.fold(folder)?,
RigidTy::Coroutine(_, args, _) => *args = args.fold(folder)?,
RigidTy::Dynamic(pred, r, _) => {
*pred = pred.fold(folder)?;
*r = r.fold(folder)?;
}
RigidTy::Tuple(fields) => *fields = fields.fold(folder)?,
RigidTy::Adt(_, args) => *args = args.fold(folder)?,
}
ControlFlow::Continue(this)
}
}
impl<T: Foldable> Foldable for Vec<T> {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
let mut this = self.clone();
for arg in &mut this {
*arg = arg.fold(folder)?;
}
ControlFlow::Continue(this)
}
}
impl<T: Foldable> Foldable for Binder<T> {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(Self {
value: self.value.fold(folder)?,
bound_vars: self.bound_vars.clone(),
})
}
}
impl Foldable for ExistentialPredicate {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
let mut this = self.clone();
match &mut this {
ExistentialPredicate::Trait(tr) => tr.generic_args = tr.generic_args.fold(folder)?,
ExistentialPredicate::Projection(p) => {
p.term = p.term.fold(folder)?;
p.generic_args = p.generic_args.fold(folder)?;
}
ExistentialPredicate::AutoTrait(_) => {}
}
ControlFlow::Continue(this)
}
}
impl Foldable for TermKind {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(match self {
TermKind::Type(t) => TermKind::Type(t.fold(folder)?),
TermKind::Const(c) => TermKind::Const(c.fold(folder)?),
})
}
}
impl Foldable for FnSig {
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
ControlFlow::Continue(Self {
inputs_and_output: self.inputs_and_output.fold(folder)?,
c_variadic: self.c_variadic,
unsafety: self.unsafety,
abi: self.abi.clone(),
})
}
}
pub enum Never {}
/// In order to instantiate a `Foldable`'s generic parameters with specific arguments,
/// `GenericArgs` can be used as a `Folder` that replaces all mentions of generic params
/// with the entries in its list.
impl Folder for GenericArgs {
type Break = Never;
fn fold_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
ControlFlow::Continue(match ty.kind() {
TyKind::Param(p) => self[p],
_ => *ty,
})
}
fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> {
ControlFlow::Continue(match &c.literal {
ConstantKind::Param(p) => self[p.clone()].clone(),
_ => c.clone(),
})
}
}

View File

@ -32,7 +32,6 @@ use self::ty::{
extern crate scoped_tls;
pub mod error;
pub mod fold;
pub mod mir;
pub mod ty;
pub mod visitor;
@ -215,9 +214,6 @@ pub trait Context {
/// Obtain the representation of a type.
fn ty_kind(&self, ty: Ty) -> TyKind;
/// Create a new `Ty` from scratch without information from rustc.
fn mk_ty(&self, kind: TyKind) -> Ty;
/// Get the body of an Instance.
/// FIXME: Monomorphize the body.
fn instance_body(&self, instance: InstanceDef) -> Body;

View File

@ -477,7 +477,7 @@ impl Operand {
impl Constant {
pub fn ty(&self) -> Ty {
self.literal.ty
self.literal.ty()
}
}

View File

@ -6,7 +6,7 @@ use super::{
use crate::{Filename, Opaque};
use std::fmt::{self, Debug, Formatter};
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Ty(pub usize);
impl Debug for Ty {
@ -21,17 +21,36 @@ impl Ty {
}
}
impl From<TyKind> for Ty {
fn from(value: TyKind) -> Self {
with(|context| context.mk_ty(value))
/// Represents a constant in MIR or from the Type system.
#[derive(Clone, Debug)]
pub struct Const {
/// The constant kind.
kind: ConstantKind,
/// The constant type.
ty: Ty,
/// Used for internal tracking of the internal constant.
pub id: ConstId,
}
impl Const {
/// Build a constant. Note that this should only be used by the compiler.
pub fn new(kind: ConstantKind, ty: Ty, id: ConstId) -> Const {
Const { kind, ty, id }
}
/// Retrieve the constant kind.
pub fn kind(&self) -> &ConstantKind {
&self.kind
}
/// Get the constant type.
pub fn ty(&self) -> Ty {
self.ty
}
}
#[derive(Debug, Clone)]
pub struct Const {
pub literal: ConstantKind,
pub ty: Ty,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ConstId(pub usize);
type Ident = Opaque;
@ -108,15 +127,6 @@ pub struct LineInfo {
pub end_col: usize,
}
impl IndexedVal for Span {
fn to_val(index: usize) -> Self {
Span(index)
}
fn to_index(&self) -> usize {
self.0
}
}
#[derive(Clone, Debug)]
pub enum TyKind {
RigidTy(RigidTy),
@ -603,3 +613,20 @@ pub trait IndexedVal {
fn to_index(&self) -> usize;
}
macro_rules! index_impl {
($name:ident) => {
impl IndexedVal for $name {
fn to_val(index: usize) -> Self {
$name(index)
}
fn to_index(&self) -> usize {
self.0
}
}
};
}
index_impl!(ConstId);
index_impl!(Ty);
index_impl!(Span);

View File

@ -47,12 +47,12 @@ impl Visitable for Const {
visitor.visit_const(self)
}
fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
match &self.literal {
match &self.kind() {
super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?,
super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?,
super::ty::ConstantKind::Param(_) => {}
}
self.ty.visit(visitor)
self.ty().visit(visitor)
}
}

View File

@ -22,8 +22,8 @@ extern crate stable_mir;
use rustc_hir::def::DefKind;
use rustc_middle::ty::TyCtxt;
use rustc_smir::rustc_internal;
use stable_mir::fold::Foldable;
use stable_mir::mir::mono::Instance;
use stable_mir::ty::{RigidTy, TyKind};
use std::assert_matches::assert_matches;
use std::io::Write;
use std::ops::ControlFlow;
@ -119,40 +119,18 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
}
let monomorphic = get_item(&items, (DefKind::Fn, "monomorphic")).unwrap();
for block in monomorphic.body().blocks {
let instance = Instance::try_from(monomorphic.clone()).unwrap();
for block in instance.body().blocks {
match &block.terminator.kind {
stable_mir::mir::TerminatorKind::Call { func, .. } => match func {
stable_mir::mir::Operand::Constant(c) => match &c.literal.literal {
stable_mir::ty::ConstantKind::Allocated(alloc) => {
assert!(alloc.bytes.is_empty());
match c.literal.ty.kind() {
stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::FnDef(
def,
mut args,
)) => {
let func = def.body();
match func.locals[1].ty
.fold(&mut args)
.continue_value()
.unwrap()
.kind()
{
stable_mir::ty::TyKind::RigidTy(
stable_mir::ty::RigidTy::Uint(_),
) => {}
stable_mir::ty::TyKind::RigidTy(
stable_mir::ty::RigidTy::Tuple(_),
) => {}
other => panic!("{other:?}"),
}
}
other => panic!("{other:?}"),
}
}
stable_mir::mir::TerminatorKind::Call { func, .. } => {
let TyKind::RigidTy(ty) = func.ty(&body.locals).kind() else { unreachable!() };
let RigidTy::FnDef(def, args) = ty else { unreachable!() };
let next_func = Instance::resolve(def, &args).unwrap();
match next_func.body().locals[1].ty.kind() {
TyKind::RigidTy(RigidTy::Uint(_)) | TyKind::RigidTy(RigidTy::Tuple(_)) => {}
other => panic!("{other:?}"),
},
other => panic!("{other:?}"),
},
}
}
stable_mir::mir::TerminatorKind::Return => {}
other => panic!("{other:?}"),
}