Add more APIs and fix Instance::body
Add more APIs to retrieve information about types, and add more instance resolution options. Make `Instance::body()` return an Option<Body>, since not every instance might have an available body. For example, foreign instances, virtual instances, dependencies.
This commit is contained in:
parent
3f87dac9a2
commit
6515ac9d3f
9 changed files with 422 additions and 47 deletions
|
@ -49,6 +49,20 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
|
|||
*ty = self.monomorphize(*ty);
|
||||
}
|
||||
|
||||
fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
|
||||
let const_ = self.monomorphize(constant.const_);
|
||||
let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), None) {
|
||||
Ok(v) => v,
|
||||
Err(mir::interpret::ErrorHandled::Reported(..)) => return,
|
||||
Err(mir::interpret::ErrorHandled::TooGeneric(..)) => {
|
||||
unreachable!("Failed to evaluate instance constant: {:?}", const_)
|
||||
}
|
||||
};
|
||||
let ty = constant.ty();
|
||||
constant.const_ = mir::Const::Val(val, ty);
|
||||
self.super_constant(constant, location);
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
|
||||
|
||||
use crate::rustc_internal::{IndexMap, RustcInternal};
|
||||
use crate::rustc_smir::hir::def::DefKind;
|
||||
use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyParamRegion, Region};
|
||||
use crate::rustc_smir::stable_mir::ty::{BoundRegion, Region};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{alloc_range, AllocId};
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
|
@ -20,10 +20,11 @@ use rustc_target::abi::FieldIdx;
|
|||
use stable_mir::mir::mono::InstanceDef;
|
||||
use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
|
||||
use stable_mir::ty::{
|
||||
Const, ConstId, ConstantKind, FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy,
|
||||
Span, TyKind, UintTy,
|
||||
AdtDef, AdtKind, ClosureDef, ClosureKind, Const, ConstId, ConstantKind, EarlyParamRegion,
|
||||
FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span,
|
||||
TyKind, UintTy,
|
||||
};
|
||||
use stable_mir::{self, opaque, Context, Filename};
|
||||
use stable_mir::{self, opaque, Context, CrateItem, Filename, ItemKind};
|
||||
use std::cell::RefCell;
|
||||
use tracing::debug;
|
||||
|
||||
|
@ -85,9 +86,23 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||
LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
|
||||
}
|
||||
|
||||
fn def_kind(&self, def_id: stable_mir::DefId) -> stable_mir::DefKind {
|
||||
fn item_kind(&self, item: CrateItem) -> ItemKind {
|
||||
let tables = self.0.borrow();
|
||||
new_item_kind(tables.tcx.def_kind(tables[item.0]))
|
||||
}
|
||||
|
||||
fn adt_kind(&self, def: AdtDef) -> AdtKind {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
tables.tcx.def_kind(tables[def_id]).stable(&mut *tables)
|
||||
let ty = tables.tcx.type_of(def.0.internal(&mut *tables)).instantiate_identity().kind();
|
||||
let ty::TyKind::Adt(def, _) = ty else {
|
||||
panic!("Expected an ADT definition, but found: {ty:?}")
|
||||
};
|
||||
def.adt_kind().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)
|
||||
}
|
||||
|
||||
fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
|
||||
|
@ -198,10 +213,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn instance_body(&self, def: InstanceDef) -> Body {
|
||||
fn instance_body(&self, def: InstanceDef) -> Option<Body> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[def];
|
||||
builder::BodyBuilder::new(tables.tcx, instance).build(&mut *tables)
|
||||
tables
|
||||
.has_body(instance)
|
||||
.then(|| builder::BodyBuilder::new(tables.tcx, instance).build(&mut *tables))
|
||||
}
|
||||
|
||||
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
|
||||
|
@ -249,6 +266,42 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||
Ok(None) | Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_drop_in_place(
|
||||
&self,
|
||||
ty: stable_mir::ty::Ty,
|
||||
) -> Option<stable_mir::mir::mono::Instance> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let internal_ty = ty.internal(&mut *tables);
|
||||
let instance = Instance::resolve_drop_in_place(tables.tcx, internal_ty);
|
||||
matches!(instance.def, ty::InstanceDef::DropGlue(_, Some(_)))
|
||||
.then(|| instance.stable(&mut *tables))
|
||||
}
|
||||
|
||||
fn resolve_for_fn_ptr(
|
||||
&self,
|
||||
def: FnDef,
|
||||
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);
|
||||
Instance::resolve_for_fn_ptr(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref)
|
||||
.stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn resolve_closure(
|
||||
&self,
|
||||
def: ClosureDef,
|
||||
args: &GenericArgs,
|
||||
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);
|
||||
Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind).stable(&mut *tables)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell<Tables<'tcx>>);
|
||||
|
@ -271,6 +324,16 @@ impl<'tcx> Tables<'tcx> {
|
|||
fn intern_const(&mut self, constant: mir::Const<'tcx>) -> ConstId {
|
||||
self.constants.create_or_fetch(constant)
|
||||
}
|
||||
|
||||
fn has_body(&self, instance: Instance<'tcx>) -> bool {
|
||||
let def_id = instance.def_id();
|
||||
!self.tcx.is_foreign_item(def_id)
|
||||
&& self.tcx.is_mir_available(def_id)
|
||||
&& !matches!(
|
||||
instance.def,
|
||||
ty::InstanceDef::Virtual(..) | ty::InstanceDef::Intrinsic(..)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a stable mir crate from a given crate number.
|
||||
|
@ -281,6 +344,43 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
|
|||
stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local }
|
||||
}
|
||||
|
||||
fn new_item_kind(kind: DefKind) -> ItemKind {
|
||||
match kind {
|
||||
DefKind::Mod
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::TyParam
|
||||
| DefKind::ConstParam
|
||||
| DefKind::Macro(_)
|
||||
| DefKind::ExternCrate
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::Field
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::GlobalAsm => {
|
||||
unreachable!("Not a valid item kind: {kind:?}");
|
||||
}
|
||||
DefKind::Closure
|
||||
| DefKind::Coroutine
|
||||
| DefKind::Ctor(_, _)
|
||||
| DefKind::AssocFn
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::Fn => ItemKind::Fn,
|
||||
DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => {
|
||||
ItemKind::Const
|
||||
}
|
||||
DefKind::Static(_) => ItemKind::Static,
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait used to convert between an internal MIR type to a Stable MIR type.
|
||||
pub trait Stable<'tcx> {
|
||||
/// The stable representation of the type implementing Stable.
|
||||
|
@ -926,6 +1026,18 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::AdtKind {
|
||||
type T = AdtKind;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::AdtKind::Struct => AdtKind::Struct,
|
||||
ty::AdtKind::Union => AdtKind::Union,
|
||||
ty::AdtKind::Enum => AdtKind::Enum,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
|
||||
type T = stable_mir::mir::CoroutineSource;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
|
@ -1062,8 +1174,6 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
|||
impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
|
||||
type T = stable_mir::ty::GenericArgs;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::GenericArgs;
|
||||
|
||||
GenericArgs(self.iter().map(|arg| arg.unpack().stable(tables)).collect())
|
||||
}
|
||||
}
|
||||
|
@ -1486,7 +1596,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
|
|||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::TraitRef;
|
||||
|
||||
TraitRef { def_id: tables.trait_def(self.def_id), args: self.args.stable(tables) }
|
||||
TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1762,15 +1872,6 @@ impl<'tcx> Stable<'tcx> for rustc_span::Span {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for DefKind {
|
||||
type T = stable_mir::DefKind;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
// FIXME: add a real implementation of stable DefKind
|
||||
opaque(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
|
||||
type T = stable_mir::mir::mono::Instance;
|
||||
|
||||
|
@ -1805,3 +1906,25 @@ impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for &T
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = T::T;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
(*self).stable(tables)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for Option<T>
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = Option<T::T>;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
self.as_ref().map(|value| value.stable(tables))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ pub mod mir;
|
|||
pub mod ty;
|
||||
pub mod visitor;
|
||||
|
||||
use crate::ty::{AdtDef, AdtKind, ClosureDef, ClosureKind};
|
||||
pub use error::*;
|
||||
use mir::mono::Instance;
|
||||
use ty::{FnDef, GenericArgs};
|
||||
|
@ -99,7 +100,13 @@ pub struct Crate {
|
|||
pub is_local: bool,
|
||||
}
|
||||
|
||||
pub type DefKind = Opaque;
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum ItemKind {
|
||||
Fn,
|
||||
Static,
|
||||
Const,
|
||||
}
|
||||
|
||||
pub type Filename = Opaque;
|
||||
|
||||
/// Holds information about an item in the crate.
|
||||
|
@ -119,13 +126,17 @@ impl CrateItem {
|
|||
with(|cx| cx.name_of_def_id(self.0))
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> DefKind {
|
||||
with(|cx| cx.def_kind(self.0))
|
||||
pub fn kind(&self) -> ItemKind {
|
||||
with(|cx| cx.item_kind(*self))
|
||||
}
|
||||
|
||||
pub fn requires_monomorphization(&self) -> bool {
|
||||
with(|cx| cx.requires_monomorphization(self.0))
|
||||
}
|
||||
|
||||
pub fn ty(&self) -> Ty {
|
||||
with(|cx| cx.def_ty(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the function where execution starts if the current
|
||||
|
@ -204,7 +215,13 @@ pub trait Context {
|
|||
fn get_lines(&self, span: &Span) -> LineInfo;
|
||||
|
||||
/// Returns the `kind` of given `DefId`
|
||||
fn def_kind(&self, def_id: DefId) -> DefKind;
|
||||
fn item_kind(&self, item: CrateItem) -> ItemKind;
|
||||
|
||||
/// Returns the kind of a given algebraic data type
|
||||
fn adt_kind(&self, def: AdtDef) -> AdtKind;
|
||||
|
||||
/// Returns the type of given crate item.
|
||||
fn def_ty(&self, item: DefId) -> Ty;
|
||||
|
||||
/// `Span` of an item
|
||||
fn span_of_an_item(&self, def_id: DefId) -> Span;
|
||||
|
@ -214,7 +231,7 @@ pub trait Context {
|
|||
|
||||
/// Get the body of an Instance.
|
||||
/// FIXME: Monomorphize the body.
|
||||
fn instance_body(&self, instance: InstanceDef) -> Body;
|
||||
fn instance_body(&self, instance: InstanceDef) -> Option<Body>;
|
||||
|
||||
/// Get the instance type with generic substitutions applied and lifetimes erased.
|
||||
fn instance_ty(&self, instance: InstanceDef) -> Ty;
|
||||
|
@ -234,6 +251,20 @@ pub trait Context {
|
|||
|
||||
/// Resolve an instance from the given function definition and generic arguments.
|
||||
fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
|
||||
|
||||
/// Resolve an instance for drop_in_place for the given type.
|
||||
fn resolve_drop_in_place(&self, ty: Ty) -> Option<Instance>;
|
||||
|
||||
/// Resolve instance for a function pointer.
|
||||
fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
|
||||
|
||||
/// Resolve instance for a closure with the requested type.
|
||||
fn resolve_closure(
|
||||
&self,
|
||||
def: ClosureDef,
|
||||
args: &GenericArgs,
|
||||
kind: ClosureKind,
|
||||
) -> Option<Instance>;
|
||||
}
|
||||
|
||||
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use crate::mir::Body;
|
||||
use crate::ty::{FnDef, GenericArgs, IndexedVal, Ty};
|
||||
use crate::{with, CrateItem, DefId, Error, Opaque};
|
||||
use crate::ty::{ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
|
||||
use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque};
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum MonoItem {
|
||||
Fn(Instance),
|
||||
Static(StaticDef),
|
||||
GlobalAsm(Opaque),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Instance {
|
||||
/// The type of instance.
|
||||
pub kind: InstanceKind,
|
||||
|
@ -19,7 +19,7 @@ pub struct Instance {
|
|||
pub def: InstanceDef,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum InstanceKind {
|
||||
/// A user defined item.
|
||||
Item,
|
||||
|
@ -33,7 +33,7 @@ pub enum InstanceKind {
|
|||
|
||||
impl Instance {
|
||||
/// Get the body of an Instance. The body will be eagerly monomorphized.
|
||||
pub fn body(&self) -> Body {
|
||||
pub fn body(&self) -> Option<Body> {
|
||||
with(|context| context.instance_body(self.def))
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,34 @@ impl Instance {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Resolve the drop in place for a given type.
|
||||
/// Return `None` if the drop is a no-op.
|
||||
pub fn resolve_drop_in_place(ty: Ty) -> Option<Instance> {
|
||||
with(|cx| cx.resolve_drop_in_place(ty))
|
||||
}
|
||||
|
||||
/// Resolve the drop in place for a given type.
|
||||
pub fn resolve_for_fn_ptr(def: FnDef, args: &GenericArgs) -> Result<Instance, crate::Error> {
|
||||
with(|context| {
|
||||
context.resolve_for_fn_ptr(def, args).ok_or_else(|| {
|
||||
crate::Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Resolve a closure (do we need kind? -- most cases use FnOnce)
|
||||
pub fn resolve_closure(
|
||||
def: ClosureDef,
|
||||
args: &GenericArgs,
|
||||
kind: ClosureKind,
|
||||
) -> Result<Instance, crate::Error> {
|
||||
with(|context| {
|
||||
context.resolve_closure(def, args, kind).ok_or_else(|| {
|
||||
crate::Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`"))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to convert a crate item into an instance.
|
||||
|
@ -86,12 +114,36 @@ impl TryFrom<Instance> for CrateItem {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
impl From<Instance> for MonoItem {
|
||||
fn from(value: Instance) -> Self {
|
||||
MonoItem::Fn(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct InstanceDef(usize);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct StaticDef(pub DefId);
|
||||
|
||||
impl TryFrom<CrateItem> for StaticDef {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(value: CrateItem) -> Result<Self, Self::Error> {
|
||||
if matches!(value.kind(), ItemKind::Static | ItemKind::Const) {
|
||||
Ok(StaticDef(value.0))
|
||||
} else {
|
||||
Err(Error::new(format!("Expected a static item, but found: {value:?}")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StaticDef {
|
||||
pub fn ty(&self) -> Ty {
|
||||
with(|cx| cx.def_ty(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexedVal for InstanceDef {
|
||||
fn to_val(index: usize) -> Self {
|
||||
InstanceDef(index)
|
||||
|
|
|
@ -4,7 +4,7 @@ use super::{
|
|||
with, AllocId, DefId, Symbol,
|
||||
};
|
||||
use crate::{Filename, Opaque};
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Ty(pub usize);
|
||||
|
@ -135,6 +135,46 @@ pub enum TyKind {
|
|||
Bound(usize, BoundTy),
|
||||
}
|
||||
|
||||
impl TyKind {
|
||||
pub fn rigid(&self) -> Option<&RigidTy> {
|
||||
if let TyKind::RigidTy(inner) = self { Some(inner) } else { None }
|
||||
}
|
||||
|
||||
pub fn is_unit(&self) -> bool {
|
||||
matches!(self, TyKind::RigidTy(RigidTy::Tuple(data)) if data.len() == 0)
|
||||
}
|
||||
|
||||
pub fn is_trait(&self) -> bool {
|
||||
matches!(self, TyKind::RigidTy(RigidTy::Dynamic(_, _, DynKind::Dyn)))
|
||||
}
|
||||
|
||||
pub fn is_enum(&self) -> bool {
|
||||
matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Enum)
|
||||
}
|
||||
|
||||
pub fn is_struct(&self) -> bool {
|
||||
matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Struct)
|
||||
}
|
||||
|
||||
pub fn is_union(&self) -> bool {
|
||||
matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Union)
|
||||
}
|
||||
|
||||
pub fn trait_principal(&self) -> Option<Binder<ExistentialTraitRef>> {
|
||||
if let TyKind::RigidTy(RigidTy::Dynamic(predicates, _, _)) = self {
|
||||
if let Some(Binder { value: ExistentialPredicate::Trait(trait_ref), bound_vars }) =
|
||||
predicates.first()
|
||||
{
|
||||
Some(Binder { value: trait_ref.clone(), bound_vars: bound_vars.clone() })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum RigidTy {
|
||||
Bool,
|
||||
|
@ -218,6 +258,43 @@ pub struct BrNamedDef(pub DefId);
|
|||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct AdtDef(pub DefId);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum AdtKind {
|
||||
Enum,
|
||||
Union,
|
||||
Struct,
|
||||
}
|
||||
|
||||
impl AdtDef {
|
||||
pub fn kind(&self) -> AdtKind {
|
||||
with(|cx| cx.adt_kind(*self))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AdtKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
AdtKind::Enum => "enum",
|
||||
AdtKind::Union => "union",
|
||||
AdtKind::Struct => "struct",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AdtKind {
|
||||
pub fn is_enum(&self) -> bool {
|
||||
matches!(self, AdtKind::Enum)
|
||||
}
|
||||
|
||||
pub fn is_struct(&self) -> bool {
|
||||
matches!(self, AdtKind::Struct)
|
||||
}
|
||||
|
||||
pub fn is_union(&self) -> bool {
|
||||
matches!(self, AdtKind::Union)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct AliasDef(pub DefId);
|
||||
|
||||
|
@ -355,6 +432,30 @@ pub struct Binder<T> {
|
|||
pub bound_vars: Vec<BoundVariableKind>,
|
||||
}
|
||||
|
||||
impl<T> Binder<T> {
|
||||
pub fn skip_binder(self) -> T {
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U>
|
||||
where
|
||||
F: FnOnce(&T) -> U,
|
||||
{
|
||||
let Binder { value, bound_vars } = self;
|
||||
let new_value = f(value);
|
||||
Binder { value: new_value, bound_vars: bound_vars.clone() }
|
||||
}
|
||||
|
||||
pub fn map_bound<F, U>(self, f: F) -> Binder<U>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
let Binder { value, bound_vars } = self;
|
||||
let new_value = f(value);
|
||||
Binder { value: new_value, bound_vars }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct EarlyBinder<T> {
|
||||
pub value: T,
|
||||
|
@ -393,12 +494,27 @@ pub enum ExistentialPredicate {
|
|||
AutoTrait(TraitDef),
|
||||
}
|
||||
|
||||
/// An existential reference to a trait where `Self` is not included.
|
||||
///
|
||||
/// The `generic_args` will include any other known argument.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ExistentialTraitRef {
|
||||
pub def_id: TraitDef,
|
||||
pub generic_args: GenericArgs,
|
||||
}
|
||||
|
||||
impl Binder<ExistentialTraitRef> {
|
||||
pub fn with_self_ty(&self, self_ty: Ty) -> Binder<TraitRef> {
|
||||
self.map_bound_ref(|trait_ref| trait_ref.with_self_ty(self_ty))
|
||||
}
|
||||
}
|
||||
|
||||
impl ExistentialTraitRef {
|
||||
pub fn with_self_ty(&self, self_ty: Ty) -> TraitRef {
|
||||
TraitRef::new(self.def_id, self_ty, &self.generic_args)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ExistentialProjection {
|
||||
pub def_id: TraitDef,
|
||||
|
@ -504,10 +620,39 @@ impl TraitDecl {
|
|||
|
||||
pub type ImplTrait = EarlyBinder<TraitRef>;
|
||||
|
||||
/// A complete reference to a trait, i.e., one where `Self` is known.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct TraitRef {
|
||||
pub def_id: TraitDef,
|
||||
pub args: GenericArgs,
|
||||
/// The generic arguments for this definition.
|
||||
/// The first element must always be type, and it represents `Self`.
|
||||
args: GenericArgs,
|
||||
}
|
||||
|
||||
impl TraitRef {
|
||||
pub fn new(def_id: TraitDef, self_ty: Ty, gen_args: &GenericArgs) -> TraitRef {
|
||||
let mut args = vec![GenericArgKind::Type(self_ty)];
|
||||
args.extend_from_slice(&gen_args.0);
|
||||
TraitRef { def_id, args: GenericArgs(args) }
|
||||
}
|
||||
|
||||
pub fn try_new(def_id: TraitDef, args: GenericArgs) -> Result<TraitRef, ()> {
|
||||
match &args.0[..] {
|
||||
[GenericArgKind::Type(_), ..] => Ok(TraitRef { def_id, args }),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn args(&self) -> &GenericArgs {
|
||||
&self.args
|
||||
}
|
||||
|
||||
pub fn self_ty(&self) -> Ty {
|
||||
let GenericArgKind::Type(self_ty) = self.args.0[0] else {
|
||||
panic!("Self must be a type, but found: {:?}", self.args.0[0])
|
||||
};
|
||||
self_ty
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
|
|
|
@ -49,7 +49,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
|||
assert!(generic.iter().all(|item| mir::mono::Instance::try_from(*item).is_err()));
|
||||
|
||||
for instance in instances {
|
||||
test_body(instance.body())
|
||||
test_body(instance.body().unwrap())
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
@ -61,8 +61,10 @@ fn test_body(body: mir::Body) {
|
|||
Call { func, .. } => {
|
||||
let TyKind::RigidTy(ty) = func.ty(body.locals()).kind() else { unreachable!() };
|
||||
let RigidTy::FnDef(def, args) = ty else { unreachable!() };
|
||||
let result = Instance::resolve(def, &args);
|
||||
assert!(result.is_ok());
|
||||
let instance = Instance::resolve(def, &args).unwrap();
|
||||
let mangled_name = instance.mangled_name();
|
||||
let body = instance.body();
|
||||
assert!(body.is_some() || mangled_name == "setpwent", "Failed: {func:?}");
|
||||
}
|
||||
Goto { .. } | Assert { .. } | SwitchInt { .. } | Return | Drop { .. } => {
|
||||
/* Do nothing */
|
||||
|
@ -105,10 +107,16 @@ fn generate_input(path: &str) -> std::io::Result<()> {
|
|||
LEN > 0 && a[0]
|
||||
}}
|
||||
|
||||
extern "C" {{
|
||||
// Body should not be available.
|
||||
fn setpwent();
|
||||
}}
|
||||
|
||||
pub fn monomorphic() {{
|
||||
let v = vec![10];
|
||||
let dup = ty_param(&v);
|
||||
assert_eq!(v, dup);
|
||||
unsafe {{ setpwent() }};
|
||||
}}
|
||||
|
||||
pub mod foo {{
|
||||
|
|
|
@ -22,6 +22,7 @@ extern crate stable_mir;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_smir::rustc_internal;
|
||||
use stable_mir::ItemKind;
|
||||
use stable_mir::mir::mono::Instance;
|
||||
use stable_mir::ty::{RigidTy, TyKind};
|
||||
use std::assert_matches::assert_matches;
|
||||
|
@ -120,13 +121,13 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
|||
|
||||
let monomorphic = get_item(&items, (DefKind::Fn, "monomorphic")).unwrap();
|
||||
let instance = Instance::try_from(monomorphic.clone()).unwrap();
|
||||
for block in instance.body().blocks {
|
||||
for block in instance.body().unwrap().blocks {
|
||||
match &block.terminator.kind {
|
||||
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() {
|
||||
match next_func.body().unwrap().locals()[1].ty.kind() {
|
||||
TyKind::RigidTy(RigidTy::Uint(_)) | TyKind::RigidTy(RigidTy::Tuple(_)) => {}
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
|
@ -172,7 +173,8 @@ fn get_item<'a>(
|
|||
item: (DefKind, &str),
|
||||
) -> Option<&'a stable_mir::CrateItem> {
|
||||
items.iter().find(|crate_item| {
|
||||
crate_item.kind().to_string() == format!("{:?}", item.0) && crate_item.name() == item.1
|
||||
matches!((item.0, crate_item.kind()), (DefKind::Fn, ItemKind::Fn) | (DefKind::Const,
|
||||
ItemKind::Const)) && crate_item.name() == item.1
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -19,11 +19,11 @@ extern crate rustc_driver;
|
|||
extern crate rustc_interface;
|
||||
extern crate stable_mir;
|
||||
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_smir::rustc_internal;
|
||||
use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
|
||||
use stable_mir::ty::{RigidTy, TyKind};
|
||||
use stable_mir::ItemKind;
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
@ -33,7 +33,7 @@ const CRATE_NAME: &str = "input";
|
|||
/// Tests projections within Place objects
|
||||
fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
||||
let items = stable_mir::all_local_items();
|
||||
let body = get_item(&items, (DefKind::Fn, "projections")).unwrap().body();
|
||||
let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().body();
|
||||
assert_eq!(body.blocks.len(), 4);
|
||||
// The first statement assigns `&s.c` to a local. The projections include a deref for `s`, since
|
||||
// `s` is passed as a reference argument, and a field access for field `c`.
|
||||
|
@ -131,10 +131,10 @@ fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
|||
// Use internal API to find a function in a crate.
|
||||
fn get_item<'a>(
|
||||
items: &'a stable_mir::CrateItems,
|
||||
item: (DefKind, &str),
|
||||
item: (ItemKind, &str),
|
||||
) -> Option<&'a stable_mir::CrateItem> {
|
||||
items.iter().find(|crate_item| {
|
||||
crate_item.kind().to_string() == format!("{:?}", item.0) && crate_item.name() == item.1
|
||||
crate_item.kind() == item.0 && crate_item.name() == item.1
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ fn test_visitor(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
|||
let exit_fn = main_visitor.calls.last().unwrap();
|
||||
assert!(exit_fn.mangled_name().contains("exit_fn"), "Unexpected last function: {exit_fn:?}");
|
||||
|
||||
let exit_body = exit_fn.body();
|
||||
let exit_body = exit_fn.body().unwrap();
|
||||
let exit_visitor = TestVisitor::collect(&exit_body);
|
||||
assert!(exit_visitor.ret_val.is_some());
|
||||
assert_eq!(exit_visitor.args.len(), 1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue