about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-06 09:50:13 +0000
committerbors <bors@rust-lang.org>2023-09-06 09:50:13 +0000
commitc1d80ba9e28a9248158ab09fe593b0724647e642 (patch)
treec4020ef044925a510286cd9de251ea2f3053b3f4
parent24bece8420cf28b12a4b11788346ac6913e23146 (diff)
parent0f4ff52e004156cfeefbb4ebc590ffda595024c9 (diff)
downloadrust-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.rs89
-rw-r--r--compiler/rustc_smir/src/stable_mir/fold.rs230
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir/body.rs6
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs8
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs66
-rw-r--r--compiler/rustc_smir/src/stable_mir/visitor.rs19
-rw-r--r--tests/ui-fulldeps/stable-mir/crate-info.rs56
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(&param)),
+                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