From cbabd00c12f83ec5ea963d1686bb99342ba28607 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Thu, 20 Jul 2023 22:20:53 -0300
Subject: [PATCH 1/4] Add tables to Stable::stable

---
 compiler/rustc_smir/src/rustc_smir/mod.rs | 208 ++++++++++++----------
 1 file changed, 111 insertions(+), 97 deletions(-)

diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index f512a98f41a4d..8999d44133dd9 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -49,8 +49,12 @@ impl<'tcx> Context for Tables<'tcx> {
                 .basic_blocks
                 .iter()
                 .map(|block| stable_mir::mir::BasicBlock {
-                    terminator: block.terminator().stable(),
-                    statements: block.statements.iter().map(mir::Statement::stable).collect(),
+                    terminator: block.terminator().stable(self),
+                    statements: block
+                        .statements
+                        .iter()
+                        .map(|statement| statement.stable(self))
+                        .collect(),
                 })
                 .collect(),
             locals: mir.local_decls.iter().map(|decl| self.intern_ty(decl.ty)).collect(),
@@ -110,11 +114,13 @@ impl<'tcx> Tables<'tcx> {
             }
             ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(self.intern_ty(*ty))),
             ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
-                TyKind::RigidTy(RigidTy::RawPtr(self.intern_ty(*ty), mutbl.stable()))
-            }
-            ty::Ref(region, ty, mutbl) => {
-                TyKind::RigidTy(RigidTy::Ref(opaque(region), self.intern_ty(*ty), mutbl.stable()))
+                TyKind::RigidTy(RigidTy::RawPtr(self.intern_ty(*ty), mutbl.stable(self)))
             }
+            ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
+                opaque(region),
+                self.intern_ty(*ty),
+                mutbl.stable(self),
+            )),
             ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
                 rustc_internal::fn_def(*def_id),
                 self.generic_args(generic_args),
@@ -187,20 +193,20 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
 }
 
 /// Trait used to convert between an internal MIR type to a Stable MIR type.
-pub(crate) trait Stable {
+pub(crate) trait Stable<'tcx> {
     /// The stable representation of the type implementing Stable.
     type T;
     /// Converts an object to the equivalent Stable MIR representation.
-    fn stable(&self) -> Self::T;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T;
 }
 
-impl<'tcx> Stable for mir::Statement<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
     type T = stable_mir::mir::Statement;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use rustc_middle::mir::StatementKind::*;
         match &self.kind {
             Assign(assign) => {
-                stable_mir::mir::Statement::Assign(assign.0.stable(), assign.1.stable())
+                stable_mir::mir::Statement::Assign(assign.0.stable(tables), assign.1.stable(tables))
             }
             FakeRead(_) => todo!(),
             SetDiscriminant { .. } => todo!(),
@@ -218,45 +224,51 @@ impl<'tcx> Stable for mir::Statement<'tcx> {
     }
 }
 
-impl<'tcx> Stable for mir::Rvalue<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
     type T = stable_mir::mir::Rvalue;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use mir::Rvalue::*;
         match self {
-            Use(op) => stable_mir::mir::Rvalue::Use(op.stable()),
+            Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
             Repeat(_, _) => todo!(),
-            Ref(region, kind, place) => {
-                stable_mir::mir::Rvalue::Ref(opaque(region), kind.stable(), place.stable())
-            }
+            Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
+                opaque(region),
+                kind.stable(tables),
+                place.stable(tables),
+            ),
             ThreadLocalRef(def_id) => {
                 stable_mir::mir::Rvalue::ThreadLocalRef(rustc_internal::crate_item(*def_id))
             }
             AddressOf(mutability, place) => {
-                stable_mir::mir::Rvalue::AddressOf(mutability.stable(), place.stable())
+                stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables))
             }
-            Len(place) => stable_mir::mir::Rvalue::Len(place.stable()),
+            Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)),
             Cast(_, _, _) => todo!(),
-            BinaryOp(bin_op, ops) => {
-                stable_mir::mir::Rvalue::BinaryOp(bin_op.stable(), ops.0.stable(), ops.1.stable())
-            }
+            BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp(
+                bin_op.stable(tables),
+                ops.0.stable(tables),
+                ops.1.stable(tables),
+            ),
             CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
-                bin_op.stable(),
-                ops.0.stable(),
-                ops.1.stable(),
+                bin_op.stable(tables),
+                ops.0.stable(tables),
+                ops.1.stable(tables),
             ),
             NullaryOp(_, _) => todo!(),
-            UnaryOp(un_op, op) => stable_mir::mir::Rvalue::UnaryOp(un_op.stable(), op.stable()),
-            Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable()),
+            UnaryOp(un_op, op) => {
+                stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables))
+            }
+            Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables)),
             Aggregate(_, _) => todo!(),
             ShallowInitBox(_, _) => todo!(),
-            CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable()),
+            CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables)),
         }
     }
 }
 
-impl Stable for mir::Mutability {
+impl<'tcx> Stable<'tcx> for mir::Mutability {
     type T = stable_mir::mir::Mutability;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         use mir::Mutability::*;
         match *self {
             Not => stable_mir::mir::Mutability::Not,
@@ -265,21 +277,21 @@ impl Stable for mir::Mutability {
     }
 }
 
-impl Stable for mir::BorrowKind {
+impl<'tcx> Stable<'tcx> for mir::BorrowKind {
     type T = stable_mir::mir::BorrowKind;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use mir::BorrowKind::*;
         match *self {
             Shared => stable_mir::mir::BorrowKind::Shared,
             Shallow => stable_mir::mir::BorrowKind::Shallow,
-            Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable() },
+            Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
         }
     }
 }
 
-impl Stable for mir::MutBorrowKind {
+impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
     type T = stable_mir::mir::MutBorrowKind;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         use mir::MutBorrowKind::*;
         match *self {
             Default => stable_mir::mir::MutBorrowKind::Default,
@@ -289,28 +301,28 @@ impl Stable for mir::MutBorrowKind {
     }
 }
 
-impl<'tcx> Stable for mir::NullOp<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
     type T = stable_mir::mir::NullOp;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use mir::NullOp::*;
         match self {
             SizeOf => stable_mir::mir::NullOp::SizeOf,
             AlignOf => stable_mir::mir::NullOp::AlignOf,
-            OffsetOf(indices) => {
-                stable_mir::mir::NullOp::OffsetOf(indices.iter().map(|idx| idx.stable()).collect())
-            }
+            OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf(
+                indices.iter().map(|idx| idx.stable(tables)).collect(),
+            ),
         }
     }
 }
 
-impl Stable for mir::CastKind {
+impl<'tcx> Stable<'tcx> for mir::CastKind {
     type T = stable_mir::mir::CastKind;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use mir::CastKind::*;
         match self {
             PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress,
             PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress,
-            PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable()),
+            PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
             DynStar => stable_mir::mir::CastKind::DynStar,
             IntToInt => stable_mir::mir::CastKind::IntToInt,
             FloatToInt => stable_mir::mir::CastKind::FloatToInt,
@@ -323,15 +335,15 @@ impl Stable for mir::CastKind {
     }
 }
 
-impl Stable for ty::adjustment::PointerCoercion {
+impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
     type T = stable_mir::mir::PointerCoercion;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use ty::adjustment::PointerCoercion;
         match self {
             PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer,
             PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer,
             PointerCoercion::ClosureFnPointer(unsafety) => {
-                stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable())
+                stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable(tables))
             }
             PointerCoercion::MutToConstPointer => {
                 stable_mir::mir::PointerCoercion::MutToConstPointer
@@ -342,9 +354,9 @@ impl Stable for ty::adjustment::PointerCoercion {
     }
 }
 
-impl Stable for rustc_hir::Unsafety {
+impl<'tcx> Stable<'tcx> for rustc_hir::Unsafety {
     type T = stable_mir::mir::Safety;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         match self {
             rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe,
             rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal,
@@ -352,28 +364,28 @@ impl Stable for rustc_hir::Unsafety {
     }
 }
 
-impl Stable for FieldIdx {
+impl<'tcx> Stable<'tcx> for FieldIdx {
     type T = usize;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         self.as_usize()
     }
 }
 
-impl<'tcx> Stable for mir::Operand<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
     type T = stable_mir::mir::Operand;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use mir::Operand::*;
         match self {
-            Copy(place) => stable_mir::mir::Operand::Copy(place.stable()),
-            Move(place) => stable_mir::mir::Operand::Move(place.stable()),
+            Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)),
+            Move(place) => stable_mir::mir::Operand::Move(place.stable(tables)),
             Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()),
         }
     }
 }
 
-impl<'tcx> Stable for mir::Place<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
     type T = stable_mir::mir::Place;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         stable_mir::mir::Place {
             local: self.local.as_usize(),
             projection: format!("{:?}", self.projection),
@@ -381,9 +393,9 @@ impl<'tcx> Stable for mir::Place<'tcx> {
     }
 }
 
-impl Stable for mir::UnwindAction {
+impl<'tcx> Stable<'tcx> for mir::UnwindAction {
     type T = stable_mir::mir::UnwindAction;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         use rustc_middle::mir::UnwindAction;
         match self {
             UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
@@ -394,46 +406,48 @@ impl Stable for mir::UnwindAction {
     }
 }
 
-impl<'tcx> Stable for mir::AssertMessage<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
     type T = stable_mir::mir::AssertMessage;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use rustc_middle::mir::AssertKind;
         match self {
             AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
-                len: len.stable(),
-                index: index.stable(),
+                len: len.stable(tables),
+                index: index.stable(tables),
             },
             AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
-                bin_op.stable(),
-                op1.stable(),
-                op2.stable(),
+                bin_op.stable(tables),
+                op1.stable(tables),
+                op2.stable(tables),
             ),
-            AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()),
+            AssertKind::OverflowNeg(op) => {
+                stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables))
+            }
             AssertKind::DivisionByZero(op) => {
-                stable_mir::mir::AssertMessage::DivisionByZero(op.stable())
+                stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables))
             }
             AssertKind::RemainderByZero(op) => {
-                stable_mir::mir::AssertMessage::RemainderByZero(op.stable())
+                stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
             }
             AssertKind::ResumedAfterReturn(generator) => {
-                stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable())
+                stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable(tables))
             }
             AssertKind::ResumedAfterPanic(generator) => {
-                stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable())
+                stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable(tables))
             }
             AssertKind::MisalignedPointerDereference { required, found } => {
                 stable_mir::mir::AssertMessage::MisalignedPointerDereference {
-                    required: required.stable(),
-                    found: found.stable(),
+                    required: required.stable(tables),
+                    found: found.stable(tables),
                 }
             }
         }
     }
 }
 
-impl Stable for mir::BinOp {
+impl<'tcx> Stable<'tcx> for mir::BinOp {
     type T = stable_mir::mir::BinOp;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         use mir::BinOp;
         match self {
             BinOp::Add => stable_mir::mir::BinOp::Add,
@@ -462,9 +476,9 @@ impl Stable for mir::BinOp {
     }
 }
 
-impl Stable for mir::UnOp {
+impl<'tcx> Stable<'tcx> for mir::UnOp {
     type T = stable_mir::mir::UnOp;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         use mir::UnOp;
         match self {
             UnOp::Not => stable_mir::mir::UnOp::Not,
@@ -473,9 +487,9 @@ impl Stable for mir::UnOp {
     }
 }
 
-impl Stable for rustc_hir::GeneratorKind {
+impl<'tcx> Stable<'tcx> for rustc_hir::GeneratorKind {
     type T = stable_mir::mir::GeneratorKind;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
         use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
         match self {
             GeneratorKind::Async(async_gen) => {
@@ -491,16 +505,16 @@ impl Stable for rustc_hir::GeneratorKind {
     }
 }
 
-impl<'tcx> Stable for mir::InlineAsmOperand<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
     type T = stable_mir::mir::InlineAsmOperand;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use rustc_middle::mir::InlineAsmOperand;
 
         let (in_value, out_place) = match self {
-            InlineAsmOperand::In { value, .. } => (Some(value.stable()), None),
-            InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable())),
+            InlineAsmOperand::In { value, .. } => (Some(value.stable(tables)), None),
+            InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable(tables))),
             InlineAsmOperand::InOut { in_value, out_place, .. } => {
-                (Some(in_value.stable()), out_place.map(|place| place.stable()))
+                (Some(in_value.stable(tables)), out_place.map(|place| place.stable(tables)))
             }
             InlineAsmOperand::Const { .. }
             | InlineAsmOperand::SymFn { .. }
@@ -511,15 +525,15 @@ impl<'tcx> Stable for mir::InlineAsmOperand<'tcx> {
     }
 }
 
-impl<'tcx> Stable for mir::Terminator<'tcx> {
+impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
     type T = stable_mir::mir::Terminator;
-    fn stable(&self) -> Self::T {
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use rustc_middle::mir::TerminatorKind::*;
         use stable_mir::mir::Terminator;
         match &self.kind {
             Goto { target } => Terminator::Goto { target: target.as_usize() },
             SwitchInt { discr, targets } => Terminator::SwitchInt {
-                discr: discr.stable(),
+                discr: discr.stable(tables),
                 targets: targets
                     .iter()
                     .map(|(value, target)| stable_mir::mir::SwitchTarget {
@@ -534,34 +548,34 @@ impl<'tcx> Stable for mir::Terminator<'tcx> {
             Return => Terminator::Return,
             Unreachable => Terminator::Unreachable,
             Drop { place, target, unwind, replace: _ } => Terminator::Drop {
-                place: place.stable(),
+                place: place.stable(tables),
                 target: target.as_usize(),
-                unwind: unwind.stable(),
+                unwind: unwind.stable(tables),
             },
             Call { func, args, destination, target, unwind, call_source: _, fn_span: _ } => {
                 Terminator::Call {
-                    func: func.stable(),
-                    args: args.iter().map(|arg| arg.stable()).collect(),
-                    destination: destination.stable(),
+                    func: func.stable(tables),
+                    args: args.iter().map(|arg| arg.stable(tables)).collect(),
+                    destination: destination.stable(tables),
                     target: target.map(|t| t.as_usize()),
-                    unwind: unwind.stable(),
+                    unwind: unwind.stable(tables),
                 }
             }
             Assert { cond, expected, msg, target, unwind } => Terminator::Assert {
-                cond: cond.stable(),
+                cond: cond.stable(tables),
                 expected: *expected,
-                msg: msg.stable(),
+                msg: msg.stable(tables),
                 target: target.as_usize(),
-                unwind: unwind.stable(),
+                unwind: unwind.stable(tables),
             },
             InlineAsm { template, operands, options, line_spans, destination, unwind } => {
                 Terminator::InlineAsm {
                     template: format!("{:?}", template),
-                    operands: operands.iter().map(|operand| operand.stable()).collect(),
+                    operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
                     options: format!("{:?}", options),
                     line_spans: format!("{:?}", line_spans),
                     destination: destination.map(|d| d.as_usize()),
-                    unwind: unwind.stable(),
+                    unwind: unwind.stable(tables),
                 }
             }
             Yield { .. } | GeneratorDrop | FalseEdge { .. } | FalseUnwind { .. } => unreachable!(),

From 93bcc2ef98264de8acb8e9f623a5efadd6bb09d2 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Thu, 20 Jul 2023 22:33:37 -0300
Subject: [PATCH 2/4] Implement Stable for ty::GenericArgs

---
 compiler/rustc_smir/src/rustc_smir/mod.rs | 49 +++++++++++------------
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 8999d44133dd9..b6ef92575d22b 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -8,9 +8,7 @@
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
 use crate::rustc_internal::{self, opaque};
-use crate::stable_mir::ty::{
-    FloatTy, GenericArgKind, GenericArgs, IntTy, Movability, RigidTy, TyKind, UintTy,
-};
+use crate::stable_mir::ty::{FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy};
 use crate::stable_mir::{self, Context};
 use rustc_hir as hir;
 use rustc_middle::mir;
@@ -103,7 +101,7 @@ impl<'tcx> Tables<'tcx> {
             },
             ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
                 rustc_internal::adt_def(adt_def.did()),
-                self.generic_args(generic_args),
+                generic_args.stable(self),
             )),
             ty::Foreign(def_id) => {
                 TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id)))
@@ -123,17 +121,17 @@ impl<'tcx> Tables<'tcx> {
             )),
             ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
                 rustc_internal::fn_def(*def_id),
-                self.generic_args(generic_args),
+                generic_args.stable(self),
             )),
             ty::FnPtr(_) => todo!(),
             ty::Dynamic(_, _, _) => todo!(),
             ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
                 rustc_internal::closure_def(*def_id),
-                self.generic_args(generic_args),
+                generic_args.stable(self),
             )),
             ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
                 rustc_internal::generator_def(*def_id),
-                self.generic_args(generic_args),
+                generic_args.stable(self),
                 match movability {
                     hir::Movability::Static => Movability::Static,
                     hir::Movability::Movable => Movability::Movable,
@@ -164,24 +162,6 @@ impl<'tcx> Tables<'tcx> {
         self.types.push(ty);
         stable_mir::ty::Ty(id)
     }
-
-    fn generic_args(
-        &mut self,
-        generic_args: &ty::GenericArgs<'tcx>,
-    ) -> stable_mir::ty::GenericArgs {
-        GenericArgs(
-            generic_args
-                .iter()
-                .map(|arg| match arg.unpack() {
-                    ty::GenericArgKind::Lifetime(region) => {
-                        GenericArgKind::Lifetime(opaque(&region))
-                    }
-                    ty::GenericArgKind::Type(ty) => GenericArgKind::Type(self.intern_ty(ty)),
-                    ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)),
-                })
-                .collect(),
-        )
-    }
 }
 
 /// Build a stable mir crate from a given crate number.
@@ -582,3 +562,22 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
         }
     }
 }
+
+impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
+    type T = stable_mir::ty::GenericArgs;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::{GenericArgKind, GenericArgs};
+
+        GenericArgs(
+            self.iter()
+                .map(|arg| match arg.unpack() {
+                    ty::GenericArgKind::Lifetime(region) => {
+                        GenericArgKind::Lifetime(opaque(&region))
+                    }
+                    ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(ty)),
+                    ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)),
+                })
+                .collect(),
+        )
+    }
+}

From 17b8977f9b3f696c71771224888595367bc96deb Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Thu, 20 Jul 2023 23:16:55 -0300
Subject: [PATCH 3/4] Add FnPtr ty to SMIR

---
 compiler/rustc_smir/src/rustc_internal/mod.rs | 16 +++
 compiler/rustc_smir/src/rustc_smir/mod.rs     | 97 ++++++++++++++++++-
 compiler/rustc_smir/src/stable_mir/ty.rs      | 79 +++++++++++++++
 3 files changed, 191 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index ccb12c27107e4..a918bc981c03c 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -47,6 +47,14 @@ pub fn generator_def(did: DefId) -> stable_mir::ty::GeneratorDef {
     with_tables(|t| t.generator_def(did))
 }
 
+pub fn param_def(did: DefId) -> stable_mir::ty::ParamDef {
+    with_tables(|t| t.param_def(did))
+}
+
+pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef {
+    with_tables(|t| t.br_named_def(did))
+}
+
 impl<'tcx> Tables<'tcx> {
     pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
         self.def_ids[item.0]
@@ -76,6 +84,14 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::GeneratorDef(self.create_def_id(did))
     }
 
+    pub fn param_def(&mut self, did: DefId) -> stable_mir::ty::ParamDef {
+        stable_mir::ty::ParamDef(self.create_def_id(did))
+    }
+
+    pub fn br_named_def(&mut self, did: DefId) -> stable_mir::ty::BrNamedDef {
+        stable_mir::ty::BrNamedDef(self.create_def_id(did))
+    }
+
     fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
         // FIXME: this becomes inefficient when we have too many ids
         for (i, &d) in self.def_ids.iter().enumerate() {
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index b6ef92575d22b..ced9a102c9a80 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -123,7 +123,7 @@ impl<'tcx> Tables<'tcx> {
                 rustc_internal::fn_def(*def_id),
                 generic_args.stable(self),
             )),
-            ty::FnPtr(_) => todo!(),
+            ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(self))),
             ty::Dynamic(_, _, _) => todo!(),
             ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
                 rustc_internal::closure_def(*def_id),
@@ -581,3 +581,98 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
         )
     }
 }
+
+impl<'tcx> Stable<'tcx> for ty::PolyFnSig<'tcx> {
+    type T = stable_mir::ty::PolyFnSig;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::Binder;
+
+        Binder {
+            value: self.skip_binder().stable(tables),
+            bound_vars: self
+                .bound_vars()
+                .iter()
+                .map(|bound_var| bound_var.stable(tables))
+                .collect(),
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
+    type T = stable_mir::ty::FnSig;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use rustc_target::spec::abi;
+        use stable_mir::ty::{Abi, FnSig, Unsafety};
+
+        FnSig {
+            inputs_and_output: self
+                .inputs_and_output
+                .iter()
+                .map(|ty| tables.intern_ty(ty))
+                .collect(),
+            c_variadic: self.c_variadic,
+            unsafety: match self.unsafety {
+                hir::Unsafety::Normal => Unsafety::Normal,
+                hir::Unsafety::Unsafe => Unsafety::Unsafe,
+            },
+            abi: match self.abi {
+                abi::Abi::Rust => Abi::Rust,
+                abi::Abi::C { unwind } => Abi::C { unwind },
+                abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind },
+                abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind },
+                abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind },
+                abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind },
+                abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind },
+                abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind },
+                abi::Abi::Win64 { unwind } => Abi::Win64 { unwind },
+                abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind },
+                abi::Abi::PtxKernel => Abi::PtxKernel,
+                abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt,
+                abi::Abi::X86Interrupt => Abi::X86Interrupt,
+                abi::Abi::AmdGpuKernel => Abi::AmdGpuKernel,
+                abi::Abi::EfiApi => Abi::EfiApi,
+                abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
+                abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
+                abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
+                abi::Abi::Wasm => Abi::Wasm,
+                abi::Abi::System { unwind } => Abi::System { unwind },
+                abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
+                abi::Abi::RustCall => Abi::RustCall,
+                abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
+                abi::Abi::Unadjusted => Abi::Unadjusted,
+                abi::Abi::RustCold => Abi::RustCold,
+            },
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
+    type T = stable_mir::ty::BoundVariableKind;
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::{BoundRegionKind, BoundTyKind, BoundVariableKind};
+
+        match self {
+            ty::BoundVariableKind::Ty(bound_ty_kind) => {
+                BoundVariableKind::Ty(match bound_ty_kind {
+                    ty::BoundTyKind::Anon => BoundTyKind::Anon,
+                    ty::BoundTyKind::Param(def_id, symbol) => {
+                        BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string())
+                    }
+                })
+            }
+            ty::BoundVariableKind::Region(bound_region_kind) => {
+                BoundVariableKind::Region(match bound_region_kind {
+                    ty::BoundRegionKind::BrAnon(option_span) => {
+                        BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span)))
+                    }
+                    ty::BoundRegionKind::BrNamed(def_id, symbol) => BoundRegionKind::BrNamed(
+                        rustc_internal::br_named_def(*def_id),
+                        symbol.to_string(),
+                    ),
+                    ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv,
+                })
+            }
+            ty::BoundVariableKind::Const => BoundVariableKind::Const,
+        }
+    }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index ba120be04b2f5..2b762eab5ef20 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -12,6 +12,7 @@ impl Ty {
 
 type Const = Opaque;
 pub(crate) type Region = Opaque;
+type Span = Opaque;
 
 #[derive(Clone, Debug)]
 pub enum TyKind {
@@ -33,6 +34,7 @@ pub enum RigidTy {
     RawPtr(Ty, Mutability),
     Ref(Region, Ty, Mutability),
     FnDef(FnDef, GenericArgs),
+    FnPtr(PolyFnSig),
     Closure(ClosureDef, GenericArgs),
     Generator(GeneratorDef, GenericArgs, Movability),
     Never,
@@ -83,6 +85,12 @@ pub struct ClosureDef(pub(crate) DefId);
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct GeneratorDef(pub(crate) DefId);
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ParamDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct BrNamedDef(pub(crate) DefId);
+
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct AdtDef(pub(crate) DefId);
 
@@ -95,3 +103,74 @@ pub enum GenericArgKind {
     Type(Ty),
     Const(Const),
 }
+
+pub type PolyFnSig = Binder<FnSig>;
+
+#[derive(Clone, Debug)]
+pub struct FnSig {
+    pub inputs_and_output: Vec<Ty>,
+    pub c_variadic: bool,
+    pub unsafety: Unsafety,
+    pub abi: Abi,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum Unsafety {
+    Unsafe,
+    Normal,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum Abi {
+    Rust,
+    C { unwind: bool },
+    Cdecl { unwind: bool },
+    Stdcall { unwind: bool },
+    Fastcall { unwind: bool },
+    Vectorcall { unwind: bool },
+    Thiscall { unwind: bool },
+    Aapcs { unwind: bool },
+    Win64 { unwind: bool },
+    SysV64 { unwind: bool },
+    PtxKernel,
+    Msp430Interrupt,
+    X86Interrupt,
+    AmdGpuKernel,
+    EfiApi,
+    AvrInterrupt,
+    AvrNonBlockingInterrupt,
+    CCmseNonSecureCall,
+    Wasm,
+    System { unwind: bool },
+    RustIntrinsic,
+    RustCall,
+    PlatformIntrinsic,
+    Unadjusted,
+    RustCold,
+}
+
+#[derive(Clone, Debug)]
+pub struct Binder<T> {
+    pub value: T,
+    pub bound_vars: Vec<BoundVariableKind>,
+}
+
+#[derive(Clone, Debug)]
+pub enum BoundVariableKind {
+    Ty(BoundTyKind),
+    Region(BoundRegionKind),
+    Const,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum BoundTyKind {
+    Anon,
+    Param(ParamDef, String),
+}
+
+#[derive(Clone, Debug)]
+pub enum BoundRegionKind {
+    BrAnon(Option<Span>),
+    BrNamed(BrNamedDef, String),
+    BrEnv,
+}

From 634db101eccf03e4b66d10a39a1fdec0bb0f7bbd Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 21 Jul 2023 11:56:49 -0300
Subject: [PATCH 4/4] Implement Stable for ty::Ty

---
 compiler/rustc_smir/src/rustc_smir/mod.rs | 164 +++++++++++-----------
 1 file changed, 84 insertions(+), 80 deletions(-)

diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index ced9a102c9a80..c9da752ab773f 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -64,7 +64,8 @@ impl<'tcx> Context for Tables<'tcx> {
     }
 
     fn ty_kind(&mut self, ty: crate::stable_mir::ty::Ty) -> TyKind {
-        self.rustc_ty_to_ty(self.types[ty.0])
+        let ty = self.types[ty.0];
+        ty.stable(self)
     }
 }
 
@@ -75,85 +76,6 @@ pub struct Tables<'tcx> {
 }
 
 impl<'tcx> Tables<'tcx> {
-    fn rustc_ty_to_ty(&mut self, ty: Ty<'tcx>) -> TyKind {
-        match ty.kind() {
-            ty::Bool => TyKind::RigidTy(RigidTy::Bool),
-            ty::Char => TyKind::RigidTy(RigidTy::Char),
-            ty::Int(int_ty) => match int_ty {
-                ty::IntTy::Isize => TyKind::RigidTy(RigidTy::Int(IntTy::Isize)),
-                ty::IntTy::I8 => TyKind::RigidTy(RigidTy::Int(IntTy::I8)),
-                ty::IntTy::I16 => TyKind::RigidTy(RigidTy::Int(IntTy::I16)),
-                ty::IntTy::I32 => TyKind::RigidTy(RigidTy::Int(IntTy::I32)),
-                ty::IntTy::I64 => TyKind::RigidTy(RigidTy::Int(IntTy::I64)),
-                ty::IntTy::I128 => TyKind::RigidTy(RigidTy::Int(IntTy::I128)),
-            },
-            ty::Uint(uint_ty) => match uint_ty {
-                ty::UintTy::Usize => TyKind::RigidTy(RigidTy::Uint(UintTy::Usize)),
-                ty::UintTy::U8 => TyKind::RigidTy(RigidTy::Uint(UintTy::U8)),
-                ty::UintTy::U16 => TyKind::RigidTy(RigidTy::Uint(UintTy::U16)),
-                ty::UintTy::U32 => TyKind::RigidTy(RigidTy::Uint(UintTy::U32)),
-                ty::UintTy::U64 => TyKind::RigidTy(RigidTy::Uint(UintTy::U64)),
-                ty::UintTy::U128 => TyKind::RigidTy(RigidTy::Uint(UintTy::U128)),
-            },
-            ty::Float(float_ty) => match float_ty {
-                ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
-                ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
-            },
-            ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
-                rustc_internal::adt_def(adt_def.did()),
-                generic_args.stable(self),
-            )),
-            ty::Foreign(def_id) => {
-                TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id)))
-            }
-            ty::Str => TyKind::RigidTy(RigidTy::Str),
-            ty::Array(ty, constant) => {
-                TyKind::RigidTy(RigidTy::Array(self.intern_ty(*ty), opaque(constant)))
-            }
-            ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(self.intern_ty(*ty))),
-            ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
-                TyKind::RigidTy(RigidTy::RawPtr(self.intern_ty(*ty), mutbl.stable(self)))
-            }
-            ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
-                opaque(region),
-                self.intern_ty(*ty),
-                mutbl.stable(self),
-            )),
-            ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
-                rustc_internal::fn_def(*def_id),
-                generic_args.stable(self),
-            )),
-            ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(self))),
-            ty::Dynamic(_, _, _) => todo!(),
-            ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
-                rustc_internal::closure_def(*def_id),
-                generic_args.stable(self),
-            )),
-            ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
-                rustc_internal::generator_def(*def_id),
-                generic_args.stable(self),
-                match movability {
-                    hir::Movability::Static => Movability::Static,
-                    hir::Movability::Movable => Movability::Movable,
-                },
-            )),
-            ty::Never => TyKind::RigidTy(RigidTy::Never),
-            ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
-                fields.iter().map(|ty| self.intern_ty(ty)).collect(),
-            )),
-            ty::Alias(_, _) => todo!(),
-            ty::Param(_) => todo!(),
-            ty::Bound(_, _) => todo!(),
-            ty::Placeholder(..)
-            | ty::GeneratorWitness(_)
-            | ty::GeneratorWitnessMIR(_, _)
-            | ty::Infer(_)
-            | ty::Error(_) => {
-                unreachable!();
-            }
-        }
-    }
-
     fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
         if let Some(id) = self.types.iter().position(|&t| t == ty) {
             return stable_mir::ty::Ty(id);
@@ -676,3 +598,85 @@ impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
         }
     }
 }
+
+impl<'tcx> Stable<'tcx> for Ty<'tcx> {
+    type T = stable_mir::ty::TyKind;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        match self.kind() {
+            ty::Bool => TyKind::RigidTy(RigidTy::Bool),
+            ty::Char => TyKind::RigidTy(RigidTy::Char),
+            ty::Int(int_ty) => match int_ty {
+                ty::IntTy::Isize => TyKind::RigidTy(RigidTy::Int(IntTy::Isize)),
+                ty::IntTy::I8 => TyKind::RigidTy(RigidTy::Int(IntTy::I8)),
+                ty::IntTy::I16 => TyKind::RigidTy(RigidTy::Int(IntTy::I16)),
+                ty::IntTy::I32 => TyKind::RigidTy(RigidTy::Int(IntTy::I32)),
+                ty::IntTy::I64 => TyKind::RigidTy(RigidTy::Int(IntTy::I64)),
+                ty::IntTy::I128 => TyKind::RigidTy(RigidTy::Int(IntTy::I128)),
+            },
+            ty::Uint(uint_ty) => match uint_ty {
+                ty::UintTy::Usize => TyKind::RigidTy(RigidTy::Uint(UintTy::Usize)),
+                ty::UintTy::U8 => TyKind::RigidTy(RigidTy::Uint(UintTy::U8)),
+                ty::UintTy::U16 => TyKind::RigidTy(RigidTy::Uint(UintTy::U16)),
+                ty::UintTy::U32 => TyKind::RigidTy(RigidTy::Uint(UintTy::U32)),
+                ty::UintTy::U64 => TyKind::RigidTy(RigidTy::Uint(UintTy::U64)),
+                ty::UintTy::U128 => TyKind::RigidTy(RigidTy::Uint(UintTy::U128)),
+            },
+            ty::Float(float_ty) => match float_ty {
+                ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)),
+                ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)),
+            },
+            ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
+                rustc_internal::adt_def(adt_def.did()),
+                generic_args.stable(tables),
+            )),
+            ty::Foreign(def_id) => {
+                TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id)))
+            }
+            ty::Str => TyKind::RigidTy(RigidTy::Str),
+            ty::Array(ty, constant) => {
+                TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), opaque(constant)))
+            }
+            ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(tables.intern_ty(*ty))),
+            ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
+                TyKind::RigidTy(RigidTy::RawPtr(tables.intern_ty(*ty), mutbl.stable(tables)))
+            }
+            ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
+                opaque(region),
+                tables.intern_ty(*ty),
+                mutbl.stable(tables),
+            )),
+            ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef(
+                rustc_internal::fn_def(*def_id),
+                generic_args.stable(tables),
+            )),
+            ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
+            ty::Dynamic(_, _, _) => todo!(),
+            ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
+                rustc_internal::closure_def(*def_id),
+                generic_args.stable(tables),
+            )),
+            ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator(
+                rustc_internal::generator_def(*def_id),
+                generic_args.stable(tables),
+                match movability {
+                    hir::Movability::Static => Movability::Static,
+                    hir::Movability::Movable => Movability::Movable,
+                },
+            )),
+            ty::Never => TyKind::RigidTy(RigidTy::Never),
+            ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple(
+                fields.iter().map(|ty| tables.intern_ty(ty)).collect(),
+            )),
+            ty::Alias(_, _) => todo!(),
+            ty::Param(_) => todo!(),
+            ty::Bound(_, _) => todo!(),
+            ty::Placeholder(..)
+            | ty::GeneratorWitness(_)
+            | ty::GeneratorWitnessMIR(_, _)
+            | ty::Infer(_)
+            | ty::Error(_) => {
+                unreachable!();
+            }
+        }
+    }
+}