diff options
| author | bors <bors@rust-lang.org> | 2023-09-06 09:50:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-09-06 09:50:13 +0000 |
| commit | c1d80ba9e28a9248158ab09fe593b0724647e642 (patch) | |
| tree | c4020ef044925a510286cd9de251ea2f3053b3f4 | |
| parent | 24bece8420cf28b12a4b11788346ac6913e23146 (diff) | |
| parent | 0f4ff52e004156cfeefbb4ebc590ffda595024c9 (diff) | |
| download | rust-c1d80ba9e28a9248158ab09fe593b0724647e642.tar.gz rust-c1d80ba9e28a9248158ab09fe593b0724647e642.zip | |
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.
| -rw-r--r-- | compiler/rustc_smir/src/rustc_smir/mod.rs | 89 | ||||
| -rw-r--r-- | compiler/rustc_smir/src/stable_mir/fold.rs | 230 | ||||
| -rw-r--r-- | compiler/rustc_smir/src/stable_mir/mir/body.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_smir/src/stable_mir/mod.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_smir/src/stable_mir/ty.rs | 66 | ||||
| -rw-r--r-- | compiler/rustc_smir/src/stable_mir/visitor.rs | 19 | ||||
| -rw-r--r-- | tests/ui-fulldeps/stable-mir/crate-info.rs | 56 |
7 files changed, 434 insertions, 40 deletions
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 52ba4bd4e57..a7640736481 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -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), + }, } } } diff --git a/compiler/rustc_smir/src/stable_mir/fold.rs b/compiler/rustc_smir/src/stable_mir/fold.rs new file mode 100644 index 00000000000..831cfb40a15 --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/fold.rs @@ -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(), + }) + } +} diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 72f719c2a5e..449ca4b8145 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -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, diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index f9eafd9de7a..9cab7230b97 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -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<'_>)); diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 1db6b1e3d28..7e344dc516b 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -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>, diff --git a/compiler/rustc_smir/src/stable_mir/visitor.rs b/compiler/rustc_smir/src/stable_mir/visitor.rs index c928eb1381f..c86063d2ed6 100644 --- a/compiler/rustc_smir/src/stable_mir/visitor.rs +++ b/compiler/rustc_smir/src/stable_mir/visitor.rs @@ -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) diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 182f97373ea..d55eae86f07 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -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 |
