Skip to content

Commit 281b65a

Browse files
committed
Add method to get type of an Rvalue in StableMIR
1 parent 7a34091 commit 281b65a

File tree

5 files changed

+177
-0
lines changed

5 files changed

+177
-0
lines changed

compiler/rustc_smir/src/rustc_smir/context.rs

+14
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
250250
tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
251251
}
252252

253+
#[allow(rustc::usage_of_qualified_ty)]
254+
fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty {
255+
let mut tables = self.0.borrow_mut();
256+
let inner = ty.internal(&mut *tables);
257+
ty::Ty::new_box(tables.tcx, inner).stable(&mut *tables)
258+
}
259+
253260
fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
254261
let mut tables = self.0.borrow_mut();
255262
tables.tcx.type_of(item.internal(&mut *tables)).instantiate_identity().stable(&mut *tables)
@@ -276,6 +283,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
276283
tables.types[ty].kind().stable(&mut *tables)
277284
}
278285

286+
fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
287+
let mut tables = self.0.borrow_mut();
288+
let internal_kind = ty.internal(&mut *tables);
289+
let internal_ty = tables.tcx.mk_ty_from_kind(internal_kind);
290+
internal_ty.discriminant_ty(tables.tcx).stable(&mut *tables)
291+
}
292+
279293
fn instance_body(&self, def: InstanceDef) -> Option<Body> {
280294
let mut tables = self.0.borrow_mut();
281295
let instance = tables.instances[def];

compiler/stable_mir/src/compiler_interface.rs

+6
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ pub trait Context {
8787
/// Create a new type from the given kind.
8888
fn new_rigid_ty(&self, kind: RigidTy) -> Ty;
8989

90+
/// Create a new box type, `Box<T>`, for the given inner type `T`.
91+
fn new_box_ty(&self, ty: Ty) -> Ty;
92+
9093
/// Returns the type of given crate item.
9194
fn def_ty(&self, item: DefId) -> Ty;
9295

@@ -102,6 +105,9 @@ pub trait Context {
102105
/// Obtain the representation of a type.
103106
fn ty_kind(&self, ty: Ty) -> TyKind;
104107

108+
// Get the discriminant Ty for this Ty if there's one.
109+
fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty;
110+
105111
/// Get the body of an Instance which is already monomorphized.
106112
fn instance_body(&self, instance: InstanceDef) -> Option<Body>;
107113

compiler/stable_mir/src/mir/body.rs

+94
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,32 @@ pub enum BinOp {
274274
Offset,
275275
}
276276

277+
impl BinOp {
278+
/// Return the type of this operation for the given input Ty.
279+
/// This function does not perform type checking, and it currently doesn't handle SIMD.
280+
pub fn ty(&self, lhs_ty: Ty, _rhs_ty: Ty) -> Ty {
281+
match self {
282+
BinOp::Add
283+
| BinOp::AddUnchecked
284+
| BinOp::Sub
285+
| BinOp::SubUnchecked
286+
| BinOp::Mul
287+
| BinOp::MulUnchecked
288+
| BinOp::Div
289+
| BinOp::Rem
290+
| BinOp::BitXor
291+
| BinOp::BitAnd
292+
| BinOp::BitOr
293+
| BinOp::Shl
294+
| BinOp::ShlUnchecked
295+
| BinOp::Shr
296+
| BinOp::ShrUnchecked
297+
| BinOp::Offset => lhs_ty,
298+
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => Ty::bool_ty(),
299+
}
300+
}
301+
}
302+
277303
#[derive(Clone, Debug, Eq, PartialEq)]
278304
pub enum UnOp {
279305
Not,
@@ -475,6 +501,63 @@ pub enum Rvalue {
475501
Use(Operand),
476502
}
477503

504+
impl Rvalue {
505+
pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
506+
match self {
507+
Rvalue::Use(operand) => operand.ty(locals),
508+
Rvalue::Repeat(operand, count) => {
509+
Ok(Ty::new_array_with_const_len(operand.ty(locals)?, count.clone()))
510+
}
511+
Rvalue::ThreadLocalRef(did) => Ok(did.ty()),
512+
Rvalue::Ref(reg, bk, place) => {
513+
let place_ty = place.ty(locals)?;
514+
Ok(Ty::new_ref(reg.clone(), place_ty, bk.to_mutable_lossy()))
515+
}
516+
Rvalue::AddressOf(mutability, place) => {
517+
let place_ty = place.ty(locals)?;
518+
Ok(Ty::new_ptr(place_ty, *mutability))
519+
}
520+
Rvalue::Len(..) => Ok(Ty::usize_ty()),
521+
Rvalue::Cast(.., ty) => Ok(*ty),
522+
Rvalue::BinaryOp(op, lhs, rhs) => {
523+
let lhs_ty = lhs.ty(locals)?;
524+
let rhs_ty = rhs.ty(locals)?;
525+
Ok(op.ty(lhs_ty, rhs_ty))
526+
}
527+
Rvalue::CheckedBinaryOp(op, lhs, rhs) => {
528+
let lhs_ty = lhs.ty(locals)?;
529+
let rhs_ty = rhs.ty(locals)?;
530+
let ty = op.ty(lhs_ty, rhs_ty);
531+
Ok(Ty::new_tuple(&[ty, Ty::bool_ty()]))
532+
}
533+
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, operand) => operand.ty(locals),
534+
Rvalue::Discriminant(place) => {
535+
let place_ty = place.ty(locals)?;
536+
place_ty
537+
.kind()
538+
.discriminant_ty()
539+
.ok_or_else(|| error!("Expected a `RigidTy` but found: {place_ty:?}"))
540+
}
541+
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
542+
Ok(Ty::usize_ty())
543+
}
544+
Rvalue::Aggregate(ak, ops) => match *ak {
545+
AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64),
546+
AggregateKind::Tuple => Ok(Ty::new_tuple(
547+
&ops.iter().map(|op| op.ty(locals)).collect::<Result<Vec<_>, _>>()?,
548+
)),
549+
AggregateKind::Adt(def, _, ref args, _, _) => Ok(def.ty_with_args(args)),
550+
AggregateKind::Closure(def, ref args) => Ok(Ty::new_closure(def, args.clone())),
551+
AggregateKind::Coroutine(def, ref args, mov) => {
552+
Ok(Ty::new_coroutine(def, args.clone(), mov))
553+
}
554+
},
555+
Rvalue::ShallowInitBox(_, ty) => Ok(Ty::new_box(*ty)),
556+
Rvalue::CopyForDeref(place) => place.ty(locals),
557+
}
558+
}
559+
}
560+
478561
#[derive(Clone, Debug, Eq, PartialEq)]
479562
pub enum AggregateKind {
480563
Array(Ty),
@@ -725,6 +808,17 @@ pub enum BorrowKind {
725808
},
726809
}
727810

811+
impl BorrowKind {
812+
pub fn to_mutable_lossy(self) -> Mutability {
813+
match self {
814+
BorrowKind::Mut { .. } => Mutability::Mut,
815+
BorrowKind::Shared => Mutability::Not,
816+
// There's no type corresponding to a shallow borrow, so use `&` as an approximation.
817+
BorrowKind::Fake => Mutability::Not,
818+
}
819+
}
820+
}
821+
728822
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
729823
pub enum MutBorrowKind {
730824
Default,

compiler/stable_mir/src/mir/mono.rs

+15
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,21 @@ impl TryFrom<CrateItem> for StaticDef {
212212
}
213213
}
214214

215+
impl TryFrom<Instance> for StaticDef {
216+
type Error = crate::Error;
217+
218+
fn try_from(value: Instance) -> Result<Self, Self::Error> {
219+
StaticDef::try_from(CrateItem::try_from(value)?)
220+
}
221+
}
222+
223+
impl From<StaticDef> for Instance {
224+
fn from(value: StaticDef) -> Self {
225+
// A static definition should always be convertible to an instance.
226+
Instance::try_from(CrateItem::from(value)).unwrap()
227+
}
228+
}
229+
215230
impl StaticDef {
216231
/// Return the type of this static definition.
217232
pub fn ty(&self) -> Ty {

compiler/stable_mir/src/ty.rs

+48
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,50 @@ impl Ty {
3131
Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, Const::try_from_target_usize(size)?)))
3232
}
3333

34+
/// Create a new array type from Const length.
35+
pub fn new_array_with_const_len(elem_ty: Ty, len: Const) -> Ty {
36+
Ty::from_rigid_kind(RigidTy::Array(elem_ty, len))
37+
}
38+
3439
/// Create a new pointer type.
3540
pub fn new_ptr(pointee_ty: Ty, mutability: Mutability) -> Ty {
3641
Ty::from_rigid_kind(RigidTy::RawPtr(pointee_ty, mutability))
3742
}
3843

44+
/// Create a new reference type.
45+
pub fn new_ref(reg: Region, pointee_ty: Ty, mutability: Mutability) -> Ty {
46+
Ty::from_rigid_kind(RigidTy::Ref(reg, pointee_ty, mutability))
47+
}
48+
49+
/// Create a new pointer type.
50+
pub fn new_tuple(tys: &[Ty]) -> Ty {
51+
Ty::from_rigid_kind(RigidTy::Tuple(Vec::from(tys)))
52+
}
53+
54+
/// Create a new closure type.
55+
pub fn new_closure(def: ClosureDef, args: GenericArgs) -> Ty {
56+
Ty::from_rigid_kind(RigidTy::Closure(def, args))
57+
}
58+
59+
/// Create a new coroutine type.
60+
pub fn new_coroutine(def: CoroutineDef, args: GenericArgs, mov: Movability) -> Ty {
61+
Ty::from_rigid_kind(RigidTy::Coroutine(def, args, mov))
62+
}
63+
64+
/// Create a new box type that represents `Box<T>`, for the given inner type `T`.
65+
pub fn new_box(inner_ty: Ty) -> Ty {
66+
with(|cx| cx.new_box_ty(inner_ty))
67+
}
68+
3969
/// Create a type representing `usize`.
4070
pub fn usize_ty() -> Ty {
4171
Ty::from_rigid_kind(RigidTy::Uint(UintTy::Usize))
4272
}
73+
74+
/// Create a type representing `bool`.
75+
pub fn bool_ty() -> Ty {
76+
Ty::from_rigid_kind(RigidTy::Bool)
77+
}
4378
}
4479

4580
impl Ty {
@@ -251,13 +286,19 @@ impl TyKind {
251286
}
252287

253288
/// Get the function signature for function like types (Fn, FnPtr, Closure, Coroutine)
289+
/// FIXME(closure)
254290
pub fn fn_sig(&self) -> Option<PolyFnSig> {
255291
match self {
256292
TyKind::RigidTy(RigidTy::FnDef(def, args)) => Some(with(|cx| cx.fn_sig(*def, args))),
257293
TyKind::RigidTy(RigidTy::FnPtr(sig)) => Some(sig.clone()),
258294
_ => None,
259295
}
260296
}
297+
298+
/// Get the discriminant type for this type.
299+
pub fn discriminant_ty(&self) -> Option<Ty> {
300+
self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty)))
301+
}
261302
}
262303

263304
pub struct TypeAndMut {
@@ -289,6 +330,13 @@ pub enum RigidTy {
289330
CoroutineWitness(CoroutineWitnessDef, GenericArgs),
290331
}
291332

333+
impl RigidTy {
334+
/// Get the discriminant type for this type.
335+
pub fn discriminant_ty(&self) -> Ty {
336+
with(|cx| cx.rigid_ty_discriminant_ty(self))
337+
}
338+
}
339+
292340
impl From<RigidTy> for TyKind {
293341
fn from(value: RigidTy) -> Self {
294342
TyKind::RigidTy(value)

0 commit comments

Comments
 (0)