Auto merge of #115532 - oli-obk:smir_folder, r=compiler-errors
Implement SMIR generic parameter instantiation Also demonstrates the use of it with a test. This required a few smaller changes that may conflict with `@ericmarkmartin` work, but should be easy to resolve any conflicts on my end if their stuff lands first.
This commit is contained in:
commit
c1d80ba9e2
@ -78,8 +78,8 @@ impl<'tcx> Context for Tables<'tcx> {
|
||||
impl_trait.stable(self)
|
||||
}
|
||||
|
||||
fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
|
||||
let def_id = self[item.0];
|
||||
fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body {
|
||||
let def_id = self[item];
|
||||
let mir = self.tcx.optimized_mir(def_id);
|
||||
stable_mir::mir::Body {
|
||||
blocks: mir
|
||||
@ -103,8 +103,13 @@ impl<'tcx> Context for Tables<'tcx> {
|
||||
}
|
||||
|
||||
fn ty_kind(&mut self, ty: crate::stable_mir::ty::Ty) -> TyKind {
|
||||
let ty = self.types[ty.0];
|
||||
ty.stable(self)
|
||||
self.types[ty.0].clone().stable(self)
|
||||
}
|
||||
|
||||
fn mk_ty(&mut self, kind: TyKind) -> stable_mir::ty::Ty {
|
||||
let n = self.types.len();
|
||||
self.types.push(MaybeStable::Stable(kind));
|
||||
stable_mir::ty::Ty(n)
|
||||
}
|
||||
|
||||
fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
|
||||
@ -128,20 +133,47 @@ impl<'tcx> Context for Tables<'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 struct Tables<'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
pub def_ids: Vec<DefId>,
|
||||
pub alloc_ids: Vec<AllocId>,
|
||||
pub types: Vec<Ty<'tcx>>,
|
||||
pub types: Vec<MaybeStable<stable_mir::ty::TyKind, Ty<'tcx>>>,
|
||||
}
|
||||
|
||||
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) {
|
||||
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(ty);
|
||||
self.types.push(MaybeStable::Rustc(ty));
|
||||
stable_mir::ty::Ty(id)
|
||||
}
|
||||
}
|
||||
@ -1097,14 +1129,13 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
|
||||
tables,
|
||||
))
|
||||
}
|
||||
ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(¶m)),
|
||||
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 {
|
||||
ty: tables.intern_ty(self.ty()),
|
||||
def: tables.const_def(uv.def),
|
||||
args: uv.args.stable(tables),
|
||||
promoted: None,
|
||||
@ -1112,10 +1143,19 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
|
||||
}
|
||||
ty::ExprCt(_) => unimplemented!(),
|
||||
},
|
||||
ty: tables.intern_ty(self.ty()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ParamConst {
|
||||
type T = stable_mir::ty::ParamConst;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::ParamConst;
|
||||
ParamConst { index: self.index, name: self.name.to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ParamTy {
|
||||
type T = stable_mir::ty::ParamTy;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
@ -1184,22 +1224,27 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
|
||||
type T = stable_mir::ty::ConstantKind;
|
||||
type T = stable_mir::ty::Const;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match *self {
|
||||
ConstantKind::Ty(c) => c.stable(tables).literal,
|
||||
ConstantKind::Unevaluated(unev_const, ty) => {
|
||||
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
|
||||
ty: tables.intern_ty(ty),
|
||||
def: tables.const_def(unev_const.def),
|
||||
args: unev_const.args.stable(tables),
|
||||
promoted: unev_const.promoted.map(|u| u.as_u32()),
|
||||
})
|
||||
}
|
||||
ConstantKind::Val(val, ty) => {
|
||||
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(ty, val, tables))
|
||||
}
|
||||
ConstantKind::Ty(c) => c.stable(tables),
|
||||
ConstantKind::Unevaluated(unev_const, ty) => stable_mir::ty::Const {
|
||||
literal: 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),
|
||||
},
|
||||
ConstantKind::Val(val, ty) => stable_mir::ty::Const {
|
||||
literal: stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
|
||||
ty, val, tables,
|
||||
)),
|
||||
ty: tables.intern_ty(ty),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
230
compiler/rustc_smir/src/stable_mir/fold.rs
Normal file
230
compiler/rustc_smir/src/stable_mir/fold.rs
Normal file
@ -0,0 +1,230 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use crate::rustc_internal::Opaque;
|
||||
|
||||
use super::ty::{
|
||||
Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind,
|
||||
GenericArgs, Promoted, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst,
|
||||
};
|
||||
|
||||
pub trait Folder: Sized {
|
||||
type Break;
|
||||
fn visit_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)
|
||||
}
|
||||
}
|
||||
|
||||
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.visit_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.clone())
|
||||
}
|
||||
}
|
||||
|
||||
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.clone())
|
||||
}
|
||||
}
|
||||
|
||||
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 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(_, ty, _) => *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::Generator(_, 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 visit_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(),
|
||||
})
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
use crate::rustc_internal::Opaque;
|
||||
use crate::stable_mir::ty::{
|
||||
AdtDef, ClosureDef, Const, ConstantKind, GeneratorDef, GenericArgs, Movability, Region,
|
||||
AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region,
|
||||
};
|
||||
use crate::stable_mir::{self, ty::Ty, Span};
|
||||
|
||||
@ -352,7 +352,7 @@ type UserTypeAnnotationIndex = usize;
|
||||
pub struct Constant {
|
||||
pub span: Span,
|
||||
pub user_ty: Option<UserTypeAnnotationIndex>,
|
||||
pub literal: ConstantKind,
|
||||
pub literal: Const,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -391,7 +391,7 @@ pub enum Mutability {
|
||||
Mut,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Safety {
|
||||
Unsafe,
|
||||
Normal,
|
||||
|
@ -20,6 +20,7 @@ use self::ty::{
|
||||
};
|
||||
use crate::rustc_smir::Tables;
|
||||
|
||||
pub mod fold;
|
||||
pub mod mir;
|
||||
pub mod ty;
|
||||
pub mod visitor;
|
||||
@ -86,7 +87,7 @@ pub struct CrateItem(pub(crate) DefId);
|
||||
|
||||
impl CrateItem {
|
||||
pub fn body(&self) -> mir::Body {
|
||||
with(|cx| cx.mir_body(self))
|
||||
with(|cx| cx.mir_body(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +138,7 @@ pub trait Context {
|
||||
fn entry_fn(&mut self) -> Option<CrateItem>;
|
||||
/// Retrieve all items of the local crate that have a MIR associated with them.
|
||||
fn all_local_items(&mut self) -> CrateItems;
|
||||
fn mir_body(&mut self, item: &CrateItem) -> mir::Body;
|
||||
fn mir_body(&mut self, item: DefId) -> mir::Body;
|
||||
fn all_trait_decls(&mut self) -> TraitDecls;
|
||||
fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
|
||||
fn all_trait_impls(&mut self) -> ImplTraitDecls;
|
||||
@ -158,6 +159,9 @@ pub trait Context {
|
||||
/// Obtain the representation of a type.
|
||||
fn ty_kind(&mut self, ty: Ty) -> TyKind;
|
||||
|
||||
/// Create a new `Ty` from scratch without information from rustc.
|
||||
fn mk_ty(&mut self, kind: TyKind) -> Ty;
|
||||
|
||||
/// HACK: Until we have fully stable consumers, we need an escape hatch
|
||||
/// to get `DefId`s out of `CrateItem`s.
|
||||
fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>));
|
||||
|
@ -1,4 +1,8 @@
|
||||
use super::{mir::Mutability, mir::Safety, with, AllocId, DefId};
|
||||
use super::{
|
||||
mir::Safety,
|
||||
mir::{Body, Mutability},
|
||||
with, AllocId, DefId,
|
||||
};
|
||||
use crate::rustc_internal::Opaque;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -10,9 +14,16 @@ impl Ty {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TyKind> for Ty {
|
||||
fn from(value: TyKind) -> Self {
|
||||
with(|context| context.mk_ty(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Const {
|
||||
pub literal: ConstantKind,
|
||||
pub ty: Ty,
|
||||
}
|
||||
|
||||
type Ident = Opaque;
|
||||
@ -88,6 +99,12 @@ pub struct ForeignDef(pub(crate) DefId);
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct FnDef(pub(crate) DefId);
|
||||
|
||||
impl FnDef {
|
||||
pub fn body(&self) -> Body {
|
||||
with(|ctx| ctx.mir_body(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct ClosureDef(pub(crate) DefId);
|
||||
|
||||
@ -121,6 +138,22 @@ pub struct ImplDef(pub(crate) DefId);
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GenericArgs(pub Vec<GenericArgKind>);
|
||||
|
||||
impl std::ops::Index<ParamTy> for GenericArgs {
|
||||
type Output = Ty;
|
||||
|
||||
fn index(&self, index: ParamTy) -> &Self::Output {
|
||||
self.0[index.index as usize].expect_ty()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<ParamConst> for GenericArgs {
|
||||
type Output = Const;
|
||||
|
||||
fn index(&self, index: ParamConst) -> &Self::Output {
|
||||
self.0[index.index as usize].expect_const()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum GenericArgKind {
|
||||
Lifetime(Region),
|
||||
@ -128,6 +161,28 @@ pub enum GenericArgKind {
|
||||
Const(Const),
|
||||
}
|
||||
|
||||
impl GenericArgKind {
|
||||
/// Panic if this generic argument is not a type, otherwise
|
||||
/// return the type.
|
||||
#[track_caller]
|
||||
pub fn expect_ty(&self) -> &Ty {
|
||||
match self {
|
||||
GenericArgKind::Type(ty) => ty,
|
||||
_ => panic!("{self:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Panic if this generic argument is not a const, otherwise
|
||||
/// return the const.
|
||||
#[track_caller]
|
||||
pub fn expect_const(&self) -> &Const {
|
||||
match self {
|
||||
GenericArgKind::Const(c) => c,
|
||||
_ => panic!("{self:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TermKind {
|
||||
Type(Ty),
|
||||
@ -287,12 +342,17 @@ pub struct Allocation {
|
||||
pub enum ConstantKind {
|
||||
Allocated(Allocation),
|
||||
Unevaluated(UnevaluatedConst),
|
||||
ParamCt(Opaque),
|
||||
Param(ParamConst),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParamConst {
|
||||
pub index: u32,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UnevaluatedConst {
|
||||
pub ty: Ty,
|
||||
pub def: ConstDef,
|
||||
pub args: GenericArgs,
|
||||
pub promoted: Option<Promoted>,
|
||||
|
@ -30,11 +30,12 @@ impl Visitable for Ty {
|
||||
}
|
||||
fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
|
||||
match self.kind() {
|
||||
super::ty::TyKind::RigidTy(ty) => ty.visit(visitor),
|
||||
super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor),
|
||||
super::ty::TyKind::Param(_) => todo!(),
|
||||
super::ty::TyKind::Bound(_, _) => todo!(),
|
||||
super::ty::TyKind::RigidTy(ty) => ty.visit(visitor)?,
|
||||
super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor)?,
|
||||
super::ty::TyKind::Param(_) => {}
|
||||
super::ty::TyKind::Bound(_, _) => {}
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,10 +45,11 @@ impl Visitable for Const {
|
||||
}
|
||||
fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
|
||||
match &self.literal {
|
||||
super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor),
|
||||
super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor),
|
||||
super::ty::ConstantKind::ParamCt(param) => param.visit(visitor),
|
||||
super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?,
|
||||
super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?,
|
||||
super::ty::ConstantKind::Param(_) => {}
|
||||
}
|
||||
self.ty.visit(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,8 +67,7 @@ impl Visitable for Allocation {
|
||||
|
||||
impl Visitable for UnevaluatedConst {
|
||||
fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
|
||||
let UnevaluatedConst { ty, def, args, promoted } = self;
|
||||
ty.visit(visitor)?;
|
||||
let UnevaluatedConst { def, args, promoted } = self;
|
||||
def.visit(visitor)?;
|
||||
args.visit(visitor)?;
|
||||
promoted.visit(visitor)
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(control_flow_enum)]
|
||||
|
||||
extern crate rustc_hir;
|
||||
extern crate rustc_middle;
|
||||
@ -15,7 +16,10 @@ extern crate rustc_smir;
|
||||
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_smir::{rustc_internal, stable_mir};
|
||||
use rustc_smir::{
|
||||
rustc_internal,
|
||||
stable_mir::{self, fold::Foldable},
|
||||
};
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
@ -110,6 +114,46 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
|
||||
let monomorphic = get_item(tcx, &items, (DefKind::Fn, "monomorphic")).unwrap();
|
||||
for block in monomorphic.body().blocks {
|
||||
match &block.terminator {
|
||||
stable_mir::mir::Terminator::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]
|
||||
.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:?}"),
|
||||
}
|
||||
}
|
||||
other => panic!("{other:?}"),
|
||||
},
|
||||
other => panic!("{other:?}"),
|
||||
},
|
||||
stable_mir::mir::Terminator::Return => {}
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
@ -147,6 +191,16 @@ fn generate_input(path: &str) -> std::io::Result<()> {
|
||||
write!(
|
||||
file,
|
||||
r#"
|
||||
fn generic<T, const U: usize>(t: T) -> [(); U] {{
|
||||
_ = t;
|
||||
[(); U]
|
||||
}}
|
||||
|
||||
pub fn monomorphic() {{
|
||||
generic::<(), 5>(());
|
||||
generic::<u32, 0>(45);
|
||||
}}
|
||||
|
||||
mod foo {{
|
||||
pub fn bar(i: i32) -> i64 {{
|
||||
i as i64
|
||||
|
Loading…
x
Reference in New Issue
Block a user