about summary refs log tree commit diff
diff options
context:
space:
mode:
authorStephen Skeirik <stephen.skeirik@runtimeverification.com>2024-06-17 17:01:38 -0400
committerStephen Skeirik <stephen.skeirik@runtimeverification.com>2024-06-26 11:56:01 -0400
commit414ebeaeea13d37bcd59473d11660169286b7cd5 (patch)
tree50454f5cca0f652518baf5ed742925b398869c70
parentc290e9de32e8ba6a673ef125fde40eadd395d170 (diff)
downloadrust-414ebeaeea13d37bcd59473d11660169286b7cd5.tar.gz
rust-414ebeaeea13d37bcd59473d11660169286b7cd5.zip
add serde derive Serialize to stable_mir
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/stable_mir/Cargo.toml1
-rw-r--r--compiler/stable_mir/src/abi.rs35
-rw-r--r--compiler/stable_mir/src/crate_def.rs3
-rw-r--r--compiler/stable_mir/src/lib.rs10
-rw-r--r--compiler/stable_mir/src/mir/alloc.rs5
-rw-r--r--compiler/stable_mir/src/mir/body.rs81
-rw-r--r--compiler/stable_mir/src/mir/mono.rs10
-rw-r--r--compiler/stable_mir/src/target.rs7
-rw-r--r--compiler/stable_mir/src/ty.rs153
-rw-r--r--tests/ui-fulldeps/stable-mir/smir_serde.rs75
11 files changed, 242 insertions, 139 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 241a37588b4..24caf5cd3e6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5254,6 +5254,7 @@ name = "stable_mir"
 version = "0.1.0-preview"
 dependencies = [
  "scoped-tls",
+ "serde",
 ]
 
 [[package]]
diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml
index 4ed61152736..2edb3f140d7 100644
--- a/compiler/stable_mir/Cargo.toml
+++ b/compiler/stable_mir/Cargo.toml
@@ -5,3 +5,4 @@ edition = "2021"
 
 [dependencies]
 scoped-tls = "1.0"
+serde = { version = "1.0.125", features = [ "derive" ] }
diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs
index e1c14fe0b38..c003ec1fbc9 100644
--- a/compiler/stable_mir/src/abi.rs
+++ b/compiler/stable_mir/src/abi.rs
@@ -5,12 +5,13 @@ use crate::target::{MachineInfo, MachineSize as Size};
 use crate::ty::{Align, IndexedVal, Ty, VariantIdx};
 use crate::Error;
 use crate::Opaque;
+use serde::Serialize;
 use std::fmt::{self, Debug};
 use std::num::NonZero;
 use std::ops::RangeInclusive;
 
 /// A function ABI definition.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub struct FnAbi {
     /// The types of each argument.
     pub args: Vec<ArgAbi>,
@@ -31,7 +32,7 @@ pub struct FnAbi {
 }
 
 /// Information about the ABI of a function's argument, or return value.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub struct ArgAbi {
     pub ty: Ty,
     pub layout: Layout,
@@ -39,7 +40,7 @@ pub struct ArgAbi {
 }
 
 /// How a function argument should be passed in to the target function.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum PassMode {
     /// Ignore the argument.
     ///
@@ -60,14 +61,14 @@ pub enum PassMode {
 }
 
 /// The layout of a type, alongside the type itself.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub struct TyAndLayout {
     pub ty: Ty,
     pub layout: Layout,
 }
 
 /// The layout of a type in memory.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub struct LayoutShape {
     /// The fields location withing the layout
     pub fields: FieldsShape,
@@ -108,7 +109,7 @@ impl LayoutShape {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub struct Layout(usize);
 
 impl Layout {
@@ -127,7 +128,7 @@ impl IndexedVal for Layout {
 }
 
 /// Describes how the fields of a type are shaped in memory.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum FieldsShape {
     /// Scalar primitives and `!`, which never have fields.
     Primitive,
@@ -177,7 +178,7 @@ impl FieldsShape {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum VariantsShape {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single { index: VariantIdx },
@@ -196,7 +197,7 @@ pub enum VariantsShape {
     },
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum TagEncoding {
     /// The tag directly stores the discriminant, but possibly with a smaller layout
     /// (so converting the tag to the discriminant can require sign extension).
@@ -221,7 +222,7 @@ pub enum TagEncoding {
 
 /// Describes how values of the type are passed by target ABIs,
 /// in terms of categories of C types there are ABI rules for.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum ValueAbi {
     Uninhabited,
     Scalar(Scalar),
@@ -250,7 +251,7 @@ impl ValueAbi {
 }
 
 /// Information about one scalar component of a Rust type.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize)]
 pub enum Scalar {
     Initialized {
         /// The primitive type used to represent this value.
@@ -280,7 +281,7 @@ impl Scalar {
 }
 
 /// Fundamental unit of memory access and layout.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize)]
 pub enum Primitive {
     /// The `bool` is the signedness of the `Integer` type.
     ///
@@ -310,7 +311,7 @@ impl Primitive {
 }
 
 /// Enum representing the existing integer lengths.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
 pub enum IntegerLength {
     I8,
     I16,
@@ -320,7 +321,7 @@ pub enum IntegerLength {
 }
 
 /// Enum representing the existing float lengths.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
 pub enum FloatLength {
     F16,
     F32,
@@ -354,7 +355,7 @@ impl FloatLength {
 /// An identifier that specifies the address space that some operation
 /// should operate on. Special address spaces have an effect on code generation,
 /// depending on the target and the address spaces it implements.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
 pub struct AddressSpace(pub u32);
 
 impl AddressSpace {
@@ -369,7 +370,7 @@ impl AddressSpace {
 /// sequence:
 ///
 ///    254 (-2), 255 (-1), 0, 1, 2
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)]
 pub struct WrappingRange {
     pub start: u128,
     pub end: u128,
@@ -420,7 +421,7 @@ impl Debug for WrappingRange {
 }
 
 /// General language calling conventions.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum CallConvention {
     C,
     Rust,
diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs
index 67752a5e629..a7cebc4c132 100644
--- a/compiler/stable_mir/src/crate_def.rs
+++ b/compiler/stable_mir/src/crate_def.rs
@@ -3,9 +3,10 @@
 
 use crate::ty::{GenericArgs, Span, Ty};
 use crate::{with, Crate, Symbol};
+use serde::Serialize;
 
 /// A unique identification number for each item accessible for the current compilation unit.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)]
 pub struct DefId(pub(crate) usize);
 
 /// A trait for retrieving information about a particular definition.
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index 8385856ae53..fe745326d81 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -27,6 +27,7 @@ pub use crate::error::*;
 use crate::mir::Body;
 use crate::mir::Mutability;
 use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
+use serde::Serialize;
 
 pub mod abi;
 #[macro_use]
@@ -74,7 +75,7 @@ pub type TraitDecls = Vec<TraitDef>;
 pub type ImplTraitDecls = Vec<ImplDef>;
 
 /// Holds information about a crate.
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
 pub struct Crate {
     pub id: CrateNum,
     pub name: Symbol,
@@ -98,7 +99,7 @@ impl Crate {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)]
 pub enum ItemKind {
     Fn,
     Static,
@@ -106,7 +107,7 @@ pub enum ItemKind {
     Ctor(CtorKind),
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)]
 pub enum CtorKind {
     Const,
     Fn,
@@ -116,6 +117,7 @@ pub type Filename = String;
 
 crate_def_with_ty! {
     /// Holds information about an item in a crate.
+    #[derive(Serialize)]
     pub CrateItem;
 }
 
@@ -188,7 +190,7 @@ pub fn all_trait_impls() -> ImplTraitDecls {
 }
 
 /// A type that provides internal information but that can still be used for debug purpose.
-#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
 pub struct Opaque(String);
 
 impl std::fmt::Display for Opaque {
diff --git a/compiler/stable_mir/src/mir/alloc.rs b/compiler/stable_mir/src/mir/alloc.rs
index ef1568151f2..9e0cac67f0a 100644
--- a/compiler/stable_mir/src/mir/alloc.rs
+++ b/compiler/stable_mir/src/mir/alloc.rs
@@ -4,11 +4,12 @@ use crate::mir::mono::{Instance, StaticDef};
 use crate::target::{Endian, MachineInfo};
 use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty};
 use crate::{with, Error};
+use serde::Serialize;
 use std::io::Read;
 
 /// An allocation in the SMIR global memory can be either a function pointer,
 /// a static, or a "real" allocation with some data in it.
-#[derive(Debug, Clone, Eq, PartialEq)]
+#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
 pub enum GlobalAlloc {
     /// The alloc ID is used as a function pointer.
     Function(Instance),
@@ -41,7 +42,7 @@ impl GlobalAlloc {
 }
 
 /// A unique identification number for each provenance
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
 pub struct AllocId(usize);
 
 impl IndexedVal for AllocId {
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index e0f9e7ae67a..f7457ecd38f 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -5,10 +5,11 @@ use crate::ty::{
     TyConst, TyKind, VariantIdx,
 };
 use crate::{Error, Opaque, Span, Symbol};
+use serde::Serialize;
 use std::io;
 
 /// The SMIR representation of a single function.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
 pub struct Body {
     pub blocks: Vec<BasicBlock>,
 
@@ -104,20 +105,20 @@ impl Body {
 
 type LocalDecls = Vec<LocalDecl>;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct LocalDecl {
     pub ty: Ty,
     pub span: Span,
     pub mutability: Mutability,
 }
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
 pub struct BasicBlock {
     pub statements: Vec<Statement>,
     pub terminator: Terminator,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct Terminator {
     pub kind: TerminatorKind,
     pub span: Span,
@@ -131,7 +132,7 @@ impl Terminator {
 
 pub type Successors = Vec<BasicBlockIdx>;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum TerminatorKind {
     Goto {
         target: BasicBlockIdx,
@@ -221,7 +222,7 @@ impl TerminatorKind {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct InlineAsmOperand {
     pub in_value: Option<Operand>,
     pub out_place: Option<Place>,
@@ -230,7 +231,7 @@ pub struct InlineAsmOperand {
     pub raw_rpr: String,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum UnwindAction {
     Continue,
     Unreachable,
@@ -238,7 +239,7 @@ pub enum UnwindAction {
     Cleanup(BasicBlockIdx),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum AssertMessage {
     BoundsCheck { len: Operand, index: Operand },
     Overflow(BinOp, Operand, Operand),
@@ -307,7 +308,7 @@ impl AssertMessage {
     }
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum BinOp {
     Add,
     AddUnchecked,
@@ -342,7 +343,7 @@ impl BinOp {
     }
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum UnOp {
     Not,
     Neg,
@@ -357,20 +358,20 @@ impl UnOp {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum CoroutineKind {
     Desugared(CoroutineDesugaring, CoroutineSource),
     Coroutine(Movability),
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum CoroutineSource {
     Block,
     Closure,
     Fn,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum CoroutineDesugaring {
     Async,
 
@@ -386,7 +387,7 @@ pub(crate) type LocalDefId = Opaque;
 pub(crate) type Coverage = Opaque;
 
 /// The FakeReadCause describes the type of pattern why a FakeRead statement exists.
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum FakeReadCause {
     ForMatchGuard,
     ForMatchedPlace(LocalDefId),
@@ -396,7 +397,7 @@ pub enum FakeReadCause {
 }
 
 /// Describes what kind of retag is to be performed
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
 pub enum RetagKind {
     FnEntry,
     TwoPhase,
@@ -404,7 +405,7 @@ pub enum RetagKind {
     Default,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
 pub enum Variance {
     Covariant,
     Invariant,
@@ -412,26 +413,26 @@ pub enum Variance {
     Bivariant,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct CopyNonOverlapping {
     pub src: Operand,
     pub dst: Operand,
     pub count: Operand,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum NonDivergingIntrinsic {
     Assume(Operand),
     CopyNonOverlapping(CopyNonOverlapping),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct Statement {
     pub kind: StatementKind,
     pub span: Span,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum StatementKind {
     Assign(Place, Rvalue),
     FakeRead(FakeReadCause, Place),
@@ -448,7 +449,7 @@ pub enum StatementKind {
     Nop,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum Rvalue {
     /// Creates a pointer with the indicated mutability to the place.
     ///
@@ -622,7 +623,7 @@ impl Rvalue {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum AggregateKind {
     Array(Ty),
     Tuple,
@@ -633,14 +634,14 @@ pub enum AggregateKind {
     RawPtr(Ty, Mutability),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum Operand {
     Copy(Place),
     Move(Place),
     Constant(ConstOperand),
 }
 
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, Serialize)]
 pub struct Place {
     pub local: Local,
     /// projection out of a place (access a field, deref a pointer, etc)
@@ -653,7 +654,7 @@ impl From<Local> for Place {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct ConstOperand {
     pub span: Span,
     pub user_ty: Option<UserTypeAnnotationIndex>,
@@ -661,7 +662,7 @@ pub struct ConstOperand {
 }
 
 /// Debug information pertaining to a user variable.
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct VarDebugInfo {
     /// The variable name.
     pub name: Symbol,
@@ -703,19 +704,19 @@ impl VarDebugInfo {
 
 pub type SourceScope = u32;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct SourceInfo {
     pub span: Span,
     pub scope: SourceScope,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct VarDebugInfoFragment {
     pub ty: Ty,
     pub projection: Vec<ProjectionElem>,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum VarDebugInfoContents {
     Place(Place),
     Const(ConstOperand),
@@ -726,7 +727,7 @@ pub enum VarDebugInfoContents {
 // ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements
 // are of type ProjectionElem<(), ()>). In SMIR we don't need this generality, so we just use
 // ProjectionElem for Places.
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum ProjectionElem {
     /// Dereference projections (e.g. `*_1`) project to the address referenced by the base place.
     Deref,
@@ -800,7 +801,7 @@ pub enum ProjectionElem {
     Subtype(Ty),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct UserTypeProjection {
     pub base: UserTypeAnnotationIndex,
 
@@ -830,7 +831,7 @@ pub type FieldIdx = usize;
 type UserTypeAnnotationIndex = usize;
 
 /// The possible branch sites of a [TerminatorKind::SwitchInt].
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct SwitchTargets {
     /// The conditional branches where the first element represents the value that guards this
     /// branch, and the second element is the branch target.
@@ -867,7 +868,7 @@ impl SwitchTargets {
     }
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
     Shared,
@@ -894,14 +895,14 @@ impl BorrowKind {
     }
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum MutBorrowKind {
     Default,
     TwoPhaseBorrow,
     ClosureCapture,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum FakeBorrowKind {
     /// A shared (deep) borrow. Data must be immutable and is aliasable.
     Deep,
@@ -912,19 +913,19 @@ pub enum FakeBorrowKind {
     Shallow,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum Mutability {
     Not,
     Mut,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum Safety {
     Safe,
     Unsafe,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum PointerCoercion {
     /// Go from a fn-item type to a fn-pointer type.
     ReifyFnPointer,
@@ -951,7 +952,7 @@ pub enum PointerCoercion {
     Unsize,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum CastKind {
     // FIXME(smir-rename): rename this to PointerExposeProvenance
     PointerExposeAddress,
@@ -967,7 +968,7 @@ pub enum CastKind {
     Transmute,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum NullOp {
     /// Returns the size of a value of that type.
     SizeOf,
diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs
index 572f1499c5a..c23293388f9 100644
--- a/compiler/stable_mir/src/mir/mono.rs
+++ b/compiler/stable_mir/src/mir/mono.rs
@@ -3,17 +3,18 @@ use crate::crate_def::CrateDef;
 use crate::mir::Body;
 use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
 use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque, Symbol};
+use serde::Serialize;
 use std::fmt::{Debug, Formatter};
 use std::io;
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum MonoItem {
     Fn(Instance),
     Static(StaticDef),
     GlobalAsm(Opaque),
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize)]
 pub struct Instance {
     /// The type of instance.
     pub kind: InstanceKind,
@@ -22,7 +23,7 @@ pub struct Instance {
     pub def: InstanceDef,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum InstanceKind {
     /// A user defined item.
     Item,
@@ -240,7 +241,7 @@ impl From<StaticDef> for CrateItem {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
 pub struct InstanceDef(usize);
 
 impl CrateDef for InstanceDef {
@@ -251,6 +252,7 @@ impl CrateDef for InstanceDef {
 
 crate_def! {
     /// Holds information about a static variable definition.
+    #[derive(Serialize)]
     pub StaticDef;
 }
 
diff --git a/compiler/stable_mir/src/target.rs b/compiler/stable_mir/src/target.rs
index e00a418c540..9fb5e046abc 100644
--- a/compiler/stable_mir/src/target.rs
+++ b/compiler/stable_mir/src/target.rs
@@ -1,9 +1,10 @@
 //! Provide information about the machine that this is being compiled into.
 
 use crate::compiler_interface::with;
+use serde::Serialize;
 
 /// The properties of the target machine being compiled into.
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq, Serialize)]
 pub struct MachineInfo {
     pub endian: Endian,
     pub pointer_width: MachineSize,
@@ -23,14 +24,14 @@ impl MachineInfo {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq, Serialize)]
 pub enum Endian {
     Little,
     Big,
 }
 
 /// Represent the size of a component.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)]
 pub struct MachineSize {
     num_bits: usize,
 }
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 8c120a96e75..9c8921da52f 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -8,10 +8,11 @@ use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
 use crate::mir::mono::StaticDef;
 use crate::target::MachineInfo;
 use crate::{Filename, Opaque};
+use serde::Serialize;
 use std::fmt::{self, Debug, Display, Formatter};
 use std::ops::Range;
 
-#[derive(Copy, Clone, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)]
 pub struct Ty(usize);
 
 impl Debug for Ty {
@@ -100,13 +101,13 @@ impl Ty {
 }
 
 /// Represents a pattern in the type system
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum Pattern {
     Range { start: Option<TyConst>, end: Option<TyConst>, include_end: bool },
 }
 
 /// Represents a constant in the type system
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct TyConst {
     pub(crate) kind: TyConstKind,
     pub id: TyConstId,
@@ -133,7 +134,7 @@ impl TyConst {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum TyConstKind {
     Param(ParamConst),
     Bound(DebruijnIndex, BoundVar),
@@ -144,11 +145,11 @@ pub enum TyConstKind {
     ZSTValue(Ty),
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct TyConstId(usize);
 
 /// Represents a constant in MIR
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct MirConst {
     /// The constant kind.
     pub(crate) kind: ConstantKind,
@@ -205,17 +206,17 @@ impl MirConst {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
 pub struct MirConstId(usize);
 
 type Ident = Opaque;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct Region {
     pub kind: RegionKind,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum RegionKind {
     ReEarlyParam(EarlyParamRegion),
     ReBound(DebruijnIndex, BoundRegion),
@@ -226,7 +227,7 @@ pub enum RegionKind {
 
 pub(crate) type DebruijnIndex = u32;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct EarlyParamRegion {
     pub index: u32,
     pub name: Symbol,
@@ -234,7 +235,7 @@ pub struct EarlyParamRegion {
 
 pub(crate) type BoundVar = u32;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct BoundRegion {
     pub var: BoundVar,
     pub kind: BoundRegionKind,
@@ -242,13 +243,13 @@ pub struct BoundRegion {
 
 pub(crate) type UniverseIndex = u32;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct Placeholder<T> {
     pub universe: UniverseIndex,
     pub bound: T,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq)]
+#[derive(Clone, Copy, PartialEq, Eq, Serialize)]
 pub struct Span(usize);
 
 impl Debug for Span {
@@ -272,7 +273,7 @@ impl Span {
     }
 }
 
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, Serialize)]
 /// Information you get from `Span` in a struct form.
 /// Line and col start from 1.
 pub struct LineInfo {
@@ -282,7 +283,7 @@ pub struct LineInfo {
     pub end_col: usize,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum TyKind {
     RigidTy(RigidTy),
     Alias(AliasKind, AliasTy),
@@ -521,7 +522,7 @@ pub struct TypeAndMut {
     pub mutability: Mutability,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum RigidTy {
     Bool,
     Char,
@@ -560,7 +561,7 @@ impl From<RigidTy> for TyKind {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
 pub enum IntTy {
     Isize,
     I8,
@@ -583,7 +584,7 @@ impl IntTy {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
 pub enum UintTy {
     Usize,
     U8,
@@ -606,19 +607,20 @@ impl UintTy {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
 pub enum FloatTy {
     F32,
     F64,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
 pub enum Movability {
     Static,
     Movable,
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub ForeignModuleDef;
 }
 
@@ -641,6 +643,7 @@ impl ForeignModule {
 
 crate_def_with_ty! {
     /// Hold information about a ForeignItem in a crate.
+    #[derive(Serialize)]
     pub ForeignDef;
 }
 
@@ -650,7 +653,7 @@ impl ForeignDef {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
 pub enum ForeignItemKind {
     Fn(FnDef),
     Static(StaticDef),
@@ -659,6 +662,7 @@ pub enum ForeignItemKind {
 
 crate_def_with_ty! {
     /// Hold information about a function definition in a crate.
+    #[derive(Serialize)]
     pub FnDef;
 }
 
@@ -692,6 +696,7 @@ impl FnDef {
 }
 
 crate_def_with_ty! {
+    #[derive(Serialize)]
     pub IntrinsicDef;
 }
 
@@ -716,26 +721,31 @@ impl From<IntrinsicDef> for FnDef {
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub ClosureDef;
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub CoroutineDef;
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub ParamDef;
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub BrNamedDef;
 }
 
-crate_def_with_ty! {
+crate_def! {
+    #[derive(Serialize)]
     pub AdtDef;
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
 pub enum AdtKind {
     Enum,
     Union,
@@ -789,7 +799,7 @@ impl AdtDef {
 }
 
 /// Definition of a variant, which can be either a struct / union field or an enum variant.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
 pub struct VariantDef {
     /// The variant index.
     ///
@@ -818,7 +828,7 @@ impl VariantDef {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct FieldDef {
     /// The field definition.
     ///
@@ -869,11 +879,13 @@ impl AdtKind {
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub AliasDef;
 }
 
 crate_def! {
     /// A trait's definition.
+    #[derive(Serialize)]
     pub TraitDef;
 }
 
@@ -884,15 +896,18 @@ impl TraitDef {
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub GenericDef;
 }
 
 crate_def_with_ty! {
+    #[derive(Serialize)]
     pub ConstDef;
 }
 
 crate_def! {
     /// A trait impl definition.
+    #[derive(Serialize)]
     pub ImplDef;
 }
 
@@ -904,15 +919,17 @@ impl ImplDef {
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub RegionDef;
 }
 
 crate_def! {
+    #[derive(Serialize)]
     pub CoroutineWitnessDef;
 }
 
 /// A list of generic arguments.
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct GenericArgs(pub Vec<GenericArgKind>);
 
 impl std::ops::Index<ParamTy> for GenericArgs {
@@ -931,7 +948,7 @@ impl std::ops::Index<ParamConst> for GenericArgs {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum GenericArgKind {
     Lifetime(Region),
     Type(Ty),
@@ -968,13 +985,13 @@ impl GenericArgKind {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum TermKind {
     Type(Ty),
     Const(TyConst),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum AliasKind {
     Projection,
     Inherent,
@@ -982,13 +999,13 @@ pub enum AliasKind {
     Weak,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct AliasTy {
     pub def_id: AliasDef,
     pub args: GenericArgs,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct AliasTerm {
     pub def_id: AliasDef,
     pub args: GenericArgs,
@@ -1006,7 +1023,7 @@ impl PolyFnSig {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct FnSig {
     pub inputs_and_output: Vec<Ty>,
     pub c_variadic: bool,
@@ -1024,7 +1041,7 @@ impl FnSig {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
 pub enum Abi {
     Rust,
     C { unwind: bool },
@@ -1054,7 +1071,7 @@ pub enum Abi {
 }
 
 /// A binder represents a possibly generic type and its bound vars.
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct Binder<T> {
     pub value: T,
     pub bound_vars: Vec<BoundVariableKind>,
@@ -1094,38 +1111,38 @@ impl<T> Binder<T> {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct EarlyBinder<T> {
     pub value: T,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum BoundVariableKind {
     Ty(BoundTyKind),
     Region(BoundRegionKind),
     Const,
 }
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
 pub enum BoundTyKind {
     Anon,
     Param(ParamDef, String),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum BoundRegionKind {
     BrAnon,
     BrNamed(BrNamedDef, String),
     BrEnv,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum DynKind {
     Dyn,
     DynStar,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum ExistentialPredicate {
     Trait(ExistentialTraitRef),
     Projection(ExistentialProjection),
@@ -1135,7 +1152,7 @@ pub enum ExistentialPredicate {
 /// 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)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct ExistentialTraitRef {
     pub def_id: TraitDef,
     pub generic_args: GenericArgs,
@@ -1153,20 +1170,20 @@ impl ExistentialTraitRef {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct ExistentialProjection {
     pub def_id: TraitDef,
     pub generic_args: GenericArgs,
     pub term: TermKind,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct ParamTy {
     pub index: u32,
     pub name: String,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct BoundTy {
     pub var: usize,
     pub kind: BoundTyKind,
@@ -1177,7 +1194,7 @@ pub type Bytes = Vec<Option<u8>>;
 /// Size in bytes.
 pub type Size = usize;
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
 pub struct Prov(pub AllocId);
 
 pub type Align = u64;
@@ -1185,14 +1202,14 @@ pub type Promoted = u32;
 pub type InitMaskMaterialized = Vec<u64>;
 
 /// Stores the provenance information of pointers stored in memory.
-#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
 pub struct ProvenanceMap {
     /// Provenance in this map applies from the given offset for an entire pointer-size worth of
     /// bytes. Two entries in this map are always at least a pointer size apart.
     pub ptrs: Vec<(Size, Prov)>,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
 pub struct Allocation {
     pub bytes: Bytes,
     pub provenance: ProvenanceMap,
@@ -1268,7 +1285,7 @@ impl Allocation {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum ConstantKind {
     Ty(TyConst),
     Allocated(Allocation),
@@ -1279,27 +1296,27 @@ pub enum ConstantKind {
     ZeroSized,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct ParamConst {
     pub index: u32,
     pub name: String,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct UnevaluatedConst {
     pub def: ConstDef,
     pub args: GenericArgs,
     pub promoted: Option<Promoted>,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
 pub enum TraitSpecializationKind {
     None,
     Marker,
     AlwaysApplicable,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct TraitDecl {
     pub def_id: TraitDef,
     pub safety: Safety,
@@ -1332,7 +1349,7 @@ 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)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct TraitRef {
     pub def_id: TraitDef,
     /// The generic arguments for this definition.
@@ -1366,7 +1383,7 @@ impl TraitRef {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct Generics {
     pub parent: Option<GenericDef>,
     pub parent_count: usize,
@@ -1377,14 +1394,14 @@ pub struct Generics {
     pub host_effect_index: Option<usize>,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum GenericParamDefKind {
     Lifetime,
     Type { has_default: bool, synthetic: bool },
     Const { has_default: bool },
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct GenericParamDef {
     pub name: super::Symbol,
     pub def_id: GenericDef,
@@ -1398,7 +1415,7 @@ pub struct GenericPredicates {
     pub predicates: Vec<(PredicateKind, Span)>,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum PredicateKind {
     Clause(ClauseKind),
     ObjectSafe(TraitDef),
@@ -1409,7 +1426,7 @@ pub enum PredicateKind {
     AliasRelate(TermKind, TermKind, AliasRelationDirection),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum ClauseKind {
     Trait(TraitPredicate),
     RegionOutlives(RegionOutlivesPredicate),
@@ -1420,57 +1437,57 @@ pub enum ClauseKind {
     ConstEvaluatable(TyConst),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum ClosureKind {
     Fn,
     FnMut,
     FnOnce,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct SubtypePredicate {
     pub a: Ty,
     pub b: Ty,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct CoercePredicate {
     pub a: Ty,
     pub b: Ty,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum AliasRelationDirection {
     Equate,
     Subtype,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct TraitPredicate {
     pub trait_ref: TraitRef,
     pub polarity: PredicatePolarity,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct OutlivesPredicate<A, B>(pub A, pub B);
 
 pub type RegionOutlivesPredicate = OutlivesPredicate<Region, Region>;
 pub type TypeOutlivesPredicate = OutlivesPredicate<Ty, Region>;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub struct ProjectionPredicate {
     pub projection_term: AliasTerm,
     pub term: TermKind,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum ImplPolarity {
     Positive,
     Negative,
     Reservation,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum PredicatePolarity {
     Positive,
     Negative,
@@ -1513,7 +1530,7 @@ index_impl!(Span);
 /// `a` is in the variant with the `VariantIdx` of `0`,
 /// `c` is in the variant with the `VariantIdx` of `1`, and
 /// `g` is in the variant with the `VariantIdx` of `0`.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
 pub struct VariantIdx(usize);
 
 index_impl!(VariantIdx);
diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs
new file mode 100644
index 00000000000..957d840f7a2
--- /dev/null
+++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs
@@ -0,0 +1,75 @@
+//@ run-pass
+//! Test that users are able to use serialize stable MIR constructs.
+
+//@ ignore-stage1
+//@ ignore-cross-compile
+//@ ignore-remote
+//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
+//@ edition: 2021
+
+#![feature(rustc_private)]
+#![feature(assert_matches)]
+#![feature(control_flow_enum)]
+
+#[macro_use]
+extern crate rustc_smir;
+extern crate rustc_driver;
+extern crate rustc_interface;
+extern crate rustc_middle;
+extern crate stable_mir;
+extern crate serde;
+extern crate serde_json;
+
+use rustc_middle::ty::TyCtxt;
+use rustc_smir::rustc_internal;
+use stable_mir::mir::Body;
+use std::io::{Write, BufWriter};
+use std::ops::ControlFlow;
+use serde_json::to_string;
+
+
+const CRATE_NAME: &str = "input";
+
+fn serialize_to_json(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
+    let path = "output.json";
+    let mut writer = BufWriter::new(std::fs::File::create(path)
+        .expect("Failed to create path"));
+    let local_crate = stable_mir::local_crate();
+    let items: Vec<Body> = stable_mir::all_local_items()
+        .iter()
+        .map(|item| { item.body() })
+        .collect();
+    let crate_data = ( local_crate.name, items );
+    writer.write_all(to_string(&crate_data)
+        .expect("serde_json failed")
+        .as_bytes()).expect("JSON serialization failed");
+    ControlFlow::Continue(())
+}
+
+/// This test will generate and analyze a dummy crate using the stable mir.
+/// For that, it will first write the dummy crate into a file.
+/// Then it will create a `StableMir` using custom arguments and then
+/// it will run the compiler.
+fn main() {
+    let path = "internal_input.rs";
+    generate_input(&path).unwrap();
+    let args = vec![
+        "rustc".to_string(),
+        "--crate-name".to_string(),
+        CRATE_NAME.to_string(),
+        path.to_string(),
+    ];
+    run_with_tcx!(args, serialize_to_json).unwrap();
+}
+
+fn generate_input(path: &str) -> std::io::Result<()> {
+    let mut file = std::fs::File::create(path)?;
+    write!(
+        file,
+        r#"
+    pub fn main() {{
+    }}
+    "#
+    )?;
+    Ok(())
+}