diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 5bb3c1a0d4c..147d683b51f 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -9,8 +9,8 @@ use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy}; use rustc_span::Symbol; use stable_mir::mir::mono::{Instance, MonoItem, StaticDef}; use stable_mir::ty::{ - Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, GenericArgKind, - GenericArgs, Region, TraitRef, Ty, + AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, FloatTy, + GenericArgKind, GenericArgs, IntTy, Region, RigidTy, TraitRef, Ty, UintTy, }; use stable_mir::{AllocId, CrateItem, DefId}; @@ -63,6 +63,82 @@ impl<'tcx> RustcInternal<'tcx> for Ty { } } +impl<'tcx> RustcInternal<'tcx> for RigidTy { + type T = rustc_ty::TyKind<'tcx>; + + fn internal(&self, tables: &mut Tables<'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::Never => rustc_ty::TyKind::Never, + RigidTy::Array(ty, cnst) => { + rustc_ty::TyKind::Array(ty.internal(tables), ty_const(cnst, tables)) + } + RigidTy::Adt(def, args) => { + rustc_ty::TyKind::Adt(def.internal(tables), args.internal(tables)) + } + RigidTy::Str => rustc_ty::TyKind::Str, + RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables)), + RigidTy::RawPtr(..) + | RigidTy::Ref(..) + | RigidTy::Foreign(_) + | RigidTy::FnDef(_, _) + | RigidTy::FnPtr(_) + | RigidTy::Closure(..) + | RigidTy::Coroutine(..) + | RigidTy::CoroutineWitness(..) + | RigidTy::Dynamic(..) + | RigidTy::Tuple(..) => { + todo!() + } + } + } +} + +impl<'tcx> RustcInternal<'tcx> for IntTy { + type T = rustc_ty::IntTy; + + fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + match self { + IntTy::Isize => rustc_ty::IntTy::Isize, + IntTy::I8 => rustc_ty::IntTy::I8, + IntTy::I16 => rustc_ty::IntTy::I16, + IntTy::I32 => rustc_ty::IntTy::I32, + IntTy::I64 => rustc_ty::IntTy::I64, + IntTy::I128 => rustc_ty::IntTy::I128, + } + } +} + +impl<'tcx> RustcInternal<'tcx> for UintTy { + type T = rustc_ty::UintTy; + + fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + match self { + UintTy::Usize => rustc_ty::UintTy::Usize, + UintTy::U8 => rustc_ty::UintTy::U8, + UintTy::U16 => rustc_ty::UintTy::U16, + UintTy::U32 => rustc_ty::UintTy::U32, + UintTy::U64 => rustc_ty::UintTy::U64, + UintTy::U128 => rustc_ty::UintTy::U128, + } + } +} + +impl<'tcx> RustcInternal<'tcx> for FloatTy { + type T = rustc_ty::FloatTy; + + fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T { + match self { + FloatTy::F32 => rustc_ty::FloatTy::F32, + FloatTy::F64 => rustc_ty::FloatTy::F64, + } + } +} + 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, @@ -183,6 +259,13 @@ impl<'tcx> RustcInternal<'tcx> for ClosureKind { } } +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)) + } +} + impl<'tcx, T> RustcInternal<'tcx> for &T where T: RustcInternal<'tcx>, diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 89dbf40c7b4..167a01ab799 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -14,7 +14,7 @@ use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::{alloc_range, AllocId}; use rustc_middle::mir::mono::MonoItem; -use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt, Variance}; +use rustc_middle::ty::{self, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, Variance}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_target::abi::FieldIdx; use stable_mir::mir::mono::InstanceDef; @@ -24,7 +24,7 @@ use stable_mir::ty::{ FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy, }; -use stable_mir::{self, opaque, Context, CrateItem, Filename, ItemKind}; +use stable_mir::{self, opaque, Context, CrateItem, Error, Filename, ItemKind}; use std::cell::RefCell; use tracing::debug; @@ -91,13 +91,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> { new_item_kind(tables.tcx.def_kind(tables[item.0])) } + fn is_foreign_item(&self, item: CrateItem) -> bool { + let tables = self.0.borrow(); + tables.tcx.is_foreign_item(tables[item.0]) + } + fn adt_kind(&self, def: AdtDef) -> AdtKind { let mut tables = self.0.borrow_mut(); - 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) + def.internal(&mut *tables).adt_kind().stable(&mut *tables) } fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty { @@ -302,6 +303,37 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let closure_kind = kind.internal(&mut *tables); Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_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() + } + + fn eval_target_usize(&self, cnst: &Const) -> Result { + let mut tables = self.0.borrow_mut(); + let mir_const = cnst.internal(&mut *tables); + mir_const + .try_eval_target_usize(tables.tcx, ParamEnv::empty()) + .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) + } + + fn usize_to_const(&self, val: u64) -> Result { + let mut tables = self.0.borrow_mut(); + let ty = tables.tcx.types.usize; + let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size; + + let scalar = ScalarInt::try_from_uint(val, size).ok_or_else(|| { + Error::new(format!("Value overflow: cannot convert `{val}` to usize.")) + })?; + Ok(ty::Const::new_value(tables.tcx, ty::ValTree::from_scalar_int(scalar), ty) + .stable(&mut *tables)) + } + + 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); + tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables) + } } pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell>); diff --git a/compiler/stable_mir/src/error.rs b/compiler/stable_mir/src/error.rs index 19910691456..1ff65717e87 100644 --- a/compiler/stable_mir/src/error.rs +++ b/compiler/stable_mir/src/error.rs @@ -8,6 +8,11 @@ use std::convert::From; use std::fmt::{Debug, Display, Formatter}; use std::{error, fmt}; +macro_rules! error { + ($fmt: literal $(,)?) => { Error(format!($fmt)) }; + ($fmt: literal, $($arg:tt)*) => { Error(format!($fmt, $($arg:tt)*)) }; + } + /// An error type used to represent an error that has already been reported by the compiler. #[derive(Clone, Copy, PartialEq, Eq)] pub enum CompilerError { @@ -24,10 +29,10 @@ pub enum CompilerError { /// A generic error to represent an API request that cannot be fulfilled. #[derive(Debug)] -pub struct Error(String); +pub struct Error(pub(crate) String); impl Error { - pub(crate) fn new(msg: String) -> Self { + pub fn new(msg: String) -> Self { Self(msg) } } diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 79102dcce35..91f1066d720 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -31,6 +31,7 @@ use self::ty::{ #[macro_use] extern crate scoped_tls; +#[macro_use] pub mod error; pub mod mir; pub mod ty; @@ -38,10 +39,10 @@ pub mod visitor; use crate::mir::pretty::function_name; use crate::mir::Mutability; -use crate::ty::{AdtDef, AdtKind, ClosureDef, ClosureKind}; +use crate::ty::{AdtDef, AdtKind, ClosureDef, ClosureKind, Const, RigidTy}; pub use error::*; use mir::mono::Instance; -use ty::{Const, FnDef, GenericArgs}; +use ty::{FnDef, GenericArgs}; /// Use String for now but we should replace it. pub type Symbol = String; @@ -224,9 +225,24 @@ pub trait Context { /// Returns the `kind` of given `DefId` fn item_kind(&self, item: CrateItem) -> ItemKind; + /// Returns whether this is a foreign item. + fn is_foreign_item(&self, item: CrateItem) -> bool; + /// Returns the kind of a given algebraic data type fn adt_kind(&self, def: AdtDef) -> AdtKind; + /// Returns if the ADT is a box. + fn adt_is_box(&self, def: AdtDef) -> bool; + + /// Evaluate constant as a target usize. + fn eval_target_usize(&self, cnst: &Const) -> Result; + + /// Create a target usize constant for the given value. + fn usize_to_const(&self, val: u64) -> Result; + + /// Create a new type from the given kind. + fn new_rigid_ty(&self, kind: RigidTy) -> Ty; + /// Returns the type of given crate item. fn def_ty(&self, item: DefId) -> Ty; diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index fa58a7ffe15..ac07246dfd3 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1,8 +1,10 @@ use crate::mir::pretty::{function_body, pretty_statement}; -use crate::ty::{AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, Ty}; -use crate::Opaque; -use crate::Span; +use crate::ty::{ + AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind, +}; +use crate::{Error, Opaque, Span}; use std::io; + /// The SMIR representation of a single function. #[derive(Clone, Debug)] pub struct Body { @@ -561,7 +563,7 @@ pub struct SwitchTarget { pub target: usize, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum BorrowKind { /// Data must be immutable and is aliasable. Shared, @@ -579,14 +581,14 @@ pub enum BorrowKind { }, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum MutBorrowKind { Default, TwoPhaseBorrow, ClosureCapture, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Mutability { Not, Mut, @@ -651,10 +653,16 @@ pub enum NullOp { } impl Operand { - pub fn ty(&self, locals: &[LocalDecl]) -> Ty { + /// Get the type of an operand relative to the local declaration. + /// + /// In order to retrieve the correct type, the `locals` argument must match the list of all + /// locals from the function body where this operand originates from. + /// + /// Errors indicate a malformed operand or incompatible locals list. + pub fn ty(&self, locals: &[LocalDecl]) -> Result { match self { Operand::Copy(place) | Operand::Move(place) => place.ty(locals), - Operand::Constant(c) => c.ty(), + Operand::Constant(c) => Ok(c.ty()), } } } @@ -666,12 +674,57 @@ impl Constant { } impl Place { - // FIXME(klinvill): This function is expected to resolve down the chain of projections to get - // the type referenced at the end of it. E.g. calling `ty()` on `*(_1.f)` should end up - // returning the type referenced by `f`. The information needed to do this may not currently be - // present in Stable MIR since at least an implementation for AdtDef is probably needed. - pub fn ty(&self, locals: &[LocalDecl]) -> Ty { - let _start_ty = locals[self.local].ty; - todo!("Implement projection") + /// Resolve down the chain of projections to get the type referenced at the end of it. + /// E.g.: + /// Calling `ty()` on `var.field` should return the type of `field`. + /// + /// In order to retrieve the correct type, the `locals` argument must match the list of all + /// locals from the function body where this place originates from. + pub fn ty(&self, locals: &[LocalDecl]) -> Result { + let start_ty = locals[self.local].ty; + self.projection.iter().fold(Ok(start_ty), |place_ty, elem| { + let ty = place_ty?; + match elem { + ProjectionElem::Deref => Self::deref_ty(ty), + ProjectionElem::Field(_idx, fty) => Ok(*fty), + ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => { + Self::index_ty(ty) + } + ProjectionElem::Subslice { from, to, from_end } => { + Self::subslice_ty(ty, from, to, from_end) + } + ProjectionElem::Downcast(_) => Ok(ty), + ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty), + } + }) + } + + fn index_ty(ty: Ty) -> Result { + ty.kind().builtin_index().ok_or_else(|| error!("Cannot index non-array type: {ty:?}")) + } + + fn subslice_ty(ty: Ty, from: &u64, to: &u64, from_end: &bool) -> Result { + let ty_kind = ty.kind(); + match ty_kind { + TyKind::RigidTy(RigidTy::Slice(..)) => Ok(ty), + TyKind::RigidTy(RigidTy::Array(inner, _)) if !from_end => Ty::try_new_array( + inner, + to.checked_sub(*from).ok_or_else(|| error!("Subslice overflow: {from}..{to}"))?, + ), + TyKind::RigidTy(RigidTy::Array(inner, size)) => { + let size = size.eval_target_usize()?; + let len = size - from - to; + Ty::try_new_array(inner, len) + } + _ => Err(Error(format!("Cannot subslice non-array type: `{ty_kind:?}`"))), + } + } + + fn deref_ty(ty: Ty) -> Result { + let deref_ty = ty + .kind() + .builtin_deref(true) + .ok_or_else(|| error!("Cannot dereference type: {ty:?}"))?; + Ok(deref_ty.ty) } } diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 8562bfd3905..8c43f2c4b8f 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -1,7 +1,7 @@ use crate::mir::Body; use crate::ty::{ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty}; use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque}; -use std::fmt::Debug; +use std::fmt::{Debug, Formatter}; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum MonoItem { @@ -10,7 +10,7 @@ pub enum MonoItem { GlobalAsm(Opaque), } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Instance { /// The type of instance. pub kind: InstanceKind, @@ -83,6 +83,15 @@ impl Instance { } } +impl Debug for Instance { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Instance") + .field("kind", &self.kind) + .field("def", &self.mangled_name()) + .finish() + } +} + /// Try to convert a crate item into an instance. /// The item cannot be generic in order to be converted into an instance. impl TryFrom for Instance { diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index fa932c5d81a..f0b11dce9aa 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -1,7 +1,7 @@ use super::{ mir::Safety, mir::{Body, Mutability}, - with, AllocId, DefId, Symbol, + with, AllocId, DefId, Error, Symbol, }; use crate::{Filename, Opaque}; use std::fmt::{self, Debug, Display, Formatter}; @@ -15,6 +15,21 @@ impl Debug for Ty { } } +/// Constructors for `Ty`. +impl Ty { + /// Create a new type from a given kind. + /// + /// Note that not all types may be supported at this point. + fn from_rigid_kind(kind: RigidTy) -> Ty { + with(|cx| cx.new_rigid_ty(kind)) + } + + /// Create a new array type. + pub fn try_new_array(elem_ty: Ty, size: u64) -> Result { + Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, Const::try_from_target_usize(size)?))) + } +} + impl Ty { pub fn kind(&self) -> TyKind { with(|context| context.ty_kind(*self)) @@ -47,6 +62,16 @@ impl Const { pub fn ty(&self) -> Ty { self.ty } + + /// Creates an interned usize constant. + fn try_from_target_usize(val: u64) -> Result { + with(|cx| cx.usize_to_const(val)) + } + + /// Try to evaluate to a target `usize`. + pub fn eval_target_usize(&self) -> Result { + with(|cx| cx.eval_target_usize(self)) + } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -173,6 +198,38 @@ impl TyKind { None } } + + /// Returns the type of `ty[i]` for builtin types. + pub fn builtin_index(&self) -> Option { + match self.rigid()? { + RigidTy::Array(ty, _) | RigidTy::Slice(ty) => Some(*ty), + _ => None, + } + } + + /// Returns the type and mutability of `*ty` for builtin types. + /// + /// The parameter `explicit` indicates if this is an *explicit* dereference. + /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly. + pub fn builtin_deref(&self, explicit: bool) -> Option { + match self.rigid()? { + RigidTy::Adt(def, args) if def.is_box() => { + Some(TypeAndMut { ty: *args.0.first()?.ty()?, mutability: Mutability::Not }) + } + RigidTy::Ref(_, ty, mutability) => { + Some(TypeAndMut { ty: *ty, mutability: *mutability }) + } + RigidTy::RawPtr(ty, mutability) if explicit => { + Some(TypeAndMut { ty: *ty, mutability: *mutability }) + } + _ => None, + } + } +} + +pub struct TypeAndMut { + pub ty: Ty, + pub mutability: Mutability, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -199,6 +256,12 @@ pub enum RigidTy { CoroutineWitness(CoroutineWitnessDef, GenericArgs), } +impl From for TyKind { + fn from(value: RigidTy) -> Self { + TyKind::RigidTy(value) + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum IntTy { Isize, @@ -269,6 +332,10 @@ impl AdtDef { pub fn kind(&self) -> AdtKind { with(|cx| cx.adt_kind(*self)) } + + pub fn is_box(&self) -> bool { + with(|cx| cx.adt_is_box(*self)) + } } impl Display for AdtKind { @@ -363,6 +430,14 @@ impl GenericArgKind { _ => panic!("{self:?}"), } } + + /// Return the generic argument type if applicable, otherwise return `None`. + pub fn ty(&self) -> Option<&Ty> { + match self { + GenericArgKind::Type(ty) => Some(ty), + _ => None, + } + } } #[derive(Clone, Debug, Eq, PartialEq)] diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index e5a480cd61d..976dfee774b 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -59,7 +59,8 @@ fn test_body(body: mir::Body) { for term in body.blocks.iter().map(|bb| &bb.terminator) { match &term.kind { Call { func, .. } => { - let TyKind::RigidTy(ty) = func.ty(body.locals()).kind() else { unreachable!() }; + let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else { unreachable! + () }; let RigidTy::FnDef(def, args) = ty else { unreachable!() }; let instance = Instance::resolve(def, &args).unwrap(); let mangled_name = instance.mangled_name(); diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 025ed1b6a95..4164f041022 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -124,7 +124,8 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { 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 TyKind::RigidTy(ty) = func.ty(&body.locals()).unwrap().kind() else { + unreachable!() }; let RigidTy::FnDef(def, args) = ty else { unreachable!() }; let next_func = Instance::resolve(def, &args).unwrap(); match next_func.body().unwrap().locals()[1].ty.kind() { diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index d00f17d206b..29930763591 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -22,7 +22,7 @@ extern crate stable_mir; 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::ty::{RigidTy, TyKind, UintTy}; use stable_mir::ItemKind; use std::assert_matches::assert_matches; use std::io::Write; @@ -39,7 +39,7 @@ fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> { // `s` is passed as a reference argument, and a field access for field `c`. match &body.blocks[0].statements[0].kind { StatementKind::Assign( - stable_mir::mir::Place { local: _, projection: local_proj }, + place @ stable_mir::mir::Place { local: _, projection: local_proj }, Rvalue::Ref(_, _, stable_mir::mir::Place { local: _, projection: r_proj }), ) => { // We can't match on vecs, only on slices. Comparing statements for equality wouldn't be @@ -48,10 +48,14 @@ fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> { assert!(local_proj.is_empty()); match &r_proj[..] { // Similarly we can't match against a type, only against its kind. - [ProjectionElem::Deref, ProjectionElem::Field(2, ty)] => assert_matches!( - ty.kind(), - TyKind::RigidTy(RigidTy::Uint(stable_mir::ty::UintTy::U8)) - ), + [ProjectionElem::Deref, ProjectionElem::Field(2, ty)] => { + assert_matches!( + ty.kind(), + TyKind::RigidTy(RigidTy::Uint(stable_mir::ty::UintTy::U8)) + ); + let ty = place.ty(body.locals()).unwrap(); + assert_matches!(ty.kind().rigid(), Some(RigidTy::Ref(..))); + }, other => panic!( "Unable to match against expected rvalue projection. Expected the projection \ for `s.c`, which is a Deref and u8 Field. Got: {:?}", @@ -69,7 +73,7 @@ fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> { // since `slice` is a reference, and an index. match &body.blocks[2].statements[0].kind { StatementKind::Assign( - stable_mir::mir::Place { local: _, projection: local_proj }, + place @ stable_mir::mir::Place { local: _, projection: local_proj }, Rvalue::Use(stable_mir::mir::Operand::Copy(stable_mir::mir::Place { local: _, projection: r_proj, @@ -80,6 +84,8 @@ fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> { // wildcards. assert!(local_proj.is_empty()); assert_matches!(r_proj[..], [ProjectionElem::Deref, ProjectionElem::Index(_)]); + let ty = place.ty(body.locals()).unwrap(); + assert_matches!(ty.kind().rigid(), Some(RigidTy::Uint(UintTy::U8))); } other => panic!( "Unable to match against expected Assign statement with a Use rvalue. Expected the \ diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index 3ec63efcc06..027b0e7d9e8 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -92,7 +92,8 @@ impl<'a> mir::MirVisitor for TestVisitor<'a> { fn visit_terminator(&mut self, term: &mir::Terminator, location: mir::visit::Location) { if let mir::TerminatorKind::Call { func, .. } = &term.kind { - let ty::TyKind::RigidTy(ty) = func.ty(self.body.locals()).kind() else { unreachable! + let ty::TyKind::RigidTy(ty) = func.ty(self.body.locals()).unwrap().kind() else { + unreachable! () }; let ty::RigidTy::FnDef(def, args) = ty else { unreachable!() }; self.calls.push(mir::mono::Instance::resolve(def, &args).unwrap());