From 2bba98b1216e21fcb18e2242c491ae7205af8308 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Fiala?= <jonas.fiala@inf.ethz.ch>
Date: Mon, 16 Oct 2023 14:29:36 +0200
Subject: [PATCH 01/38] Avoid unnecessary renumbering

---
 compiler/rustc_borrowck/src/renumber.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 5d6f5cc896782..ec0131c5349a1 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -81,6 +81,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
+        if matches!(ty_context, TyContext::ReturnTy(_)) {
+            // We will renumber the return ty when called again with `TyContext::LocalDecl`
+            return;
+        }
         *ty = self.renumber_regions(*ty, || RegionCtxt::TyContext(ty_context));
 
         debug!(?ty);

From eb31d7e7f8f0432017af3f7aa6789602a23ce3ed Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:10:30 -0700
Subject: [PATCH 02/38] FileCheck asm_unwind

---
 tests/mir-opt/inline/asm_unwind.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/asm_unwind.rs b/tests/mir-opt/inline/asm_unwind.rs
index 0cf21fda72fac..596a4592f25ff 100644
--- a/tests/mir-opt/inline/asm_unwind.rs
+++ b/tests/mir-opt/inline/asm_unwind.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // Tests inlining of `may_unwind` inline assembly.
 //
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
@@ -20,5 +19,7 @@ fn foo() {
 
 // EMIT_MIR asm_unwind.main.Inline.diff
 pub fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: (inlined foo)
     foo();
 }

From 07bb2d529674f5a2f0ab6795332dc89b4cfa1561 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:11:06 -0700
Subject: [PATCH 03/38] FileCheck caller_with_trivial_bound

---
 tests/mir-opt/inline/caller_with_trivial_bound.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/caller_with_trivial_bound.rs b/tests/mir-opt/inline/caller_with_trivial_bound.rs
index 3829cbdd30240..722c7f6724efd 100644
--- a/tests/mir-opt/inline/caller_with_trivial_bound.rs
+++ b/tests/mir-opt/inline/caller_with_trivial_bound.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // needs-unwind
 
@@ -18,6 +17,8 @@ pub fn foo<T>()
 where
     IntFactory: Factory<T>,
 {
+    // CHECK-LABEL: fn foo(
+    // CHECK-NOT: (inlined bar::<T>)
     let mut x: <IntFactory as Factory<T>>::Item = bar::<T>();
 }
 

From d9205cdf0ab06bcd00fcd495428436356fc35fce Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:11:22 -0700
Subject: [PATCH 04/38] FileCheck cycle

---
 tests/mir-opt/inline/cycle.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs
index 3e4f06834358e..8716b44b3dc02 100644
--- a/tests/mir-opt/inline/cycle.rs
+++ b/tests/mir-opt/inline/cycle.rs
@@ -1,20 +1,27 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // compile-flags: -Zinline-mir-hint-threshold=1000
 
 // EMIT_MIR cycle.f.Inline.diff
 #[inline(always)]
 fn f(g: impl Fn()) {
+    // CHECK-LABEL: fn f(
+    // CHECK-NOT: inlined
     g();
 }
 
 // EMIT_MIR cycle.g.Inline.diff
 #[inline(always)]
 fn g() {
+    // CHECK-LABEL: fn g(
+    // CHECK: (inlined f::<fn() {main}>)
+    // CHECK-NOT: inlined
     f(main);
 }
 
 // EMIT_MIR cycle.main.Inline.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: (inlined f::<fn() {g}>)
+    // CHECK-NOT: inlined
     f(g);
 }

From 820e791dbebe96d3e2510f689d00eb252e3208d1 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:11:37 -0700
Subject: [PATCH 05/38] FileCheck dont_ice_on_generic_rust_call

---
 tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
index 4147325ec44b9..3307a1408fb56 100644
--- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
+++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // compile-flags: -Zmir-enable-passes=+Inline --crate-type=lib
 
@@ -8,5 +7,7 @@ use std::marker::Tuple;
 
 // EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff
 pub fn call<I: Tuple>(mut mock: Box<dyn FnMut<I, Output = ()>>, input: I) {
+    // CHECK-LABEL: fn call(
+    // CHECK-NOT: (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut)
     mock.call_mut(input)
 }

From 2e9a7c2cf169c942ee549630931bdcfc385019b0 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:11:50 -0700
Subject: [PATCH 06/38] FileCheck dyn_trait

---
 tests/mir-opt/inline/dyn_trait.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/dyn_trait.rs b/tests/mir-opt/inline/dyn_trait.rs
index 7b41b1e1171e2..005cf155fdb93 100644
--- a/tests/mir-opt/inline/dyn_trait.rs
+++ b/tests/mir-opt/inline/dyn_trait.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 #![crate_type = "lib"]
 
@@ -20,18 +19,26 @@ pub trait Query {
 // EMIT_MIR dyn_trait.mk_cycle.Inline.diff
 #[inline(always)]
 pub fn mk_cycle<V: Debug>(c: &dyn Cache<V = V>) {
+    // CHECK-LABEL: fn mk_cycle(
+    // CHECK-NOT: (inlined <dyn Cache<V = V> as Cache>::store_nocache)
     c.store_nocache()
 }
 
 // EMIT_MIR dyn_trait.try_execute_query.Inline.diff
 #[inline(always)]
 pub fn try_execute_query<C: Cache>(c: &C) {
+    // CHECK-LABEL: fn try_execute_query(
+    // CHECK: (inlined mk_cycle::<<C as Cache>::V>)
     mk_cycle(c)
 }
 
 // EMIT_MIR dyn_trait.get_query.Inline.diff
 #[inline(always)]
 pub fn get_query<Q: Query, T>(t: &T) {
+    // CHECK-LABEL: fn get_query(
+    // CHECK-NOT: (inlined <Q as Query>::cache::<T>)
     let c = Q::cache(t);
+    // CHECK: (inlined try_execute_query::<<Q as Query>::C>)
+    // CHECK: (inlined mk_cycle::<<Q as Query>::V>)
     try_execute_query(c)
 }

From dfe047c42d1381db0012d6c60872780f07275e79 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:12:05 -0700
Subject: [PATCH 07/38] FileCheck exponential_runtime

---
 tests/mir-opt/inline/exponential_runtime.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs
index 6d3af8b9c572a..499bec33ffc9b 100644
--- a/tests/mir-opt/inline/exponential_runtime.rs
+++ b/tests/mir-opt/inline/exponential_runtime.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // Checks that code with exponential runtime does not have exponential behavior in inlining.
 
@@ -85,5 +84,13 @@ impl A for () {
 
 // EMIT_MIR exponential_runtime.main.Inline.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: (inlined <() as G>::call)
+    // CHECK: (inlined <() as F>::call)
+    // CHECK: (inlined <() as E>::call)
+    // CHECK: (inlined <() as D>::call)
+    // CHECK: (inlined <() as C>::call)
+    // CHECK: (inlined <() as B>::call)
+    // CHECK-NOT: inlined
     <() as G>::call();
 }

From 8436a4611242f3bebc0946e8afcc4e61675c6a9a Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:12:17 -0700
Subject: [PATCH 08/38] FileCheck inline_any_operand

---
 tests/mir-opt/inline/inline_any_operand.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_any_operand.rs b/tests/mir-opt/inline/inline_any_operand.rs
index e131cd6ef7ee8..659b7c3a0a1f5 100644
--- a/tests/mir-opt/inline/inline_any_operand.rs
+++ b/tests/mir-opt/inline/inline_any_operand.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // compile-flags: -Z span_free_formats
 
 // Tests that MIR inliner works for any operand
@@ -9,6 +8,8 @@ fn main() {
 
 // EMIT_MIR inline_any_operand.bar.Inline.after.mir
 fn bar() -> bool {
+    // CHECK-LABEL: fn bar(
+    // CHECK: (inlined foo)
     let f = foo;
     f(1, -1)
 }

From 359d2ab55ea970f88ea751dd9b286603ea06dc6d Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:24:38 -0700
Subject: [PATCH 09/38] FileCheck inline_box_fn

---
 tests/mir-opt/inline/inline_box_fn.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_box_fn.rs b/tests/mir-opt/inline/inline_box_fn.rs
index f6a90b92c9118..7686477c291a3 100644
--- a/tests/mir-opt/inline/inline_box_fn.rs
+++ b/tests/mir-opt/inline/inline_box_fn.rs
@@ -1,9 +1,10 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: Inline
 // compile-flags: --crate-type=lib
 
 // EMIT_MIR inline_box_fn.call.Inline.diff
 fn call(x: Box<dyn Fn(i32)>) {
+    // CHECK-LABEL: fn call(
+    // CHECK-NOT: (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call)
     x(1);
 }

From d67e934bd1f3f42ddf7b4df3d846f0785b7bf8e0 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:28:38 -0700
Subject: [PATCH 10/38] FileCheck inline_closure_borrows_arg

---
 tests/mir-opt/inline/inline_closure_borrows_arg.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.rs b/tests/mir-opt/inline/inline_closure_borrows_arg.rs
index a5cc7d1036530..1570ab057c728 100644
--- a/tests/mir-opt/inline/inline_closure_borrows_arg.rs
+++ b/tests/mir-opt/inline/inline_closure_borrows_arg.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // compile-flags: -Z span_free_formats -Zunsound-mir-opts
 
 // Tests that MIR inliner can handle closure arguments,
@@ -14,5 +13,8 @@ fn foo<T: Copy>(_t: T, q: &i32) -> i32 {
         let variable = &*r;
         *variable
     };
+
+    // CHECK-LABEL: fn foo(
+    // CHECK: (inlined foo::<T>::{closure#0})
     x(q, q)
 }

From b9015534134cb21eadd97e698a51fca0ccf017db Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:30:04 -0700
Subject: [PATCH 11/38] FileCheck inline_closure_captures

---
 tests/mir-opt/inline/inline_closure_captures.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_closure_captures.rs b/tests/mir-opt/inline/inline_closure_captures.rs
index 0d95564e5ddee..2b08b10688728 100644
--- a/tests/mir-opt/inline/inline_closure_captures.rs
+++ b/tests/mir-opt/inline/inline_closure_captures.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // compile-flags: -Z span_free_formats
 
 // Tests that MIR inliner can handle closure captures.
@@ -10,5 +9,8 @@ fn main() {
 // EMIT_MIR inline_closure_captures.foo.Inline.after.mir
 fn foo<T: Copy>(t: T, q: i32) -> (i32, T) {
     let x = |_q| (q, t);
+
+    // CHECK-LABEL: fn foo(
+    // CHECK: (inlined foo::<T>::{closure#0})
     x(q)
 }

From 149b8822bd7e02cffd7064461288aae0543cc7ad Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 11:31:05 -0700
Subject: [PATCH 12/38] FileCheck inline_closure

---
 tests/mir-opt/inline/inline_closure.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_closure.rs b/tests/mir-opt/inline/inline_closure.rs
index bd4c84ff0ca29..65f55d49a806e 100644
--- a/tests/mir-opt/inline/inline_closure.rs
+++ b/tests/mir-opt/inline/inline_closure.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // compile-flags: -Z span_free_formats
 
 // Tests that MIR inliner can handle closure arguments. (#45894)
@@ -10,5 +9,8 @@ fn main() {
 // EMIT_MIR inline_closure.foo.Inline.after.mir
 fn foo<T: Copy>(_t: T, q: i32) -> i32 {
     let x = |_t, _q| _t;
+
+    // CHECK-LABEL: fn foo(
+    // CHECK: (inlined foo::<T>::{closure#0})
     x(q, q)
 }

From 82a9ff0356a2bab2f0f5dd4e3e0d97cc41b1962a Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 14:04:52 -0700
Subject: [PATCH 13/38] FileCheck inline_compatibility

---
 tests/mir-opt/inline/inline_compatibility.rs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_compatibility.rs b/tests/mir-opt/inline/inline_compatibility.rs
index 52f4debf5dbad..17bc91c6752be 100644
--- a/tests/mir-opt/inline/inline_compatibility.rs
+++ b/tests/mir-opt/inline/inline_compatibility.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // Checks that only functions with compatible attributes are inlined.
 //
 // only-x86_64
@@ -12,22 +11,30 @@
 // EMIT_MIR inline_compatibility.inlined_target_feature.Inline.diff
 #[target_feature(enable = "sse2")]
 pub unsafe fn inlined_target_feature() {
+    // CHECK-LABEL: fn inlined_target_feature(
+    // CHECK: (inlined target_feature)
     target_feature();
 }
 
 // EMIT_MIR inline_compatibility.not_inlined_target_feature.Inline.diff
 pub unsafe fn not_inlined_target_feature() {
+    // CHECK-LABEL: fn not_inlined_target_feature(
+    // CHECK-NOT: (inlined target_feature)
     target_feature();
 }
 
 // EMIT_MIR inline_compatibility.inlined_no_sanitize.Inline.diff
 #[no_sanitize(address)]
 pub unsafe fn inlined_no_sanitize() {
+    // CHECK-LABEL: fn inlined_no_sanitize(
+    // CHECK: (inlined no_sanitize)
     no_sanitize();
 }
 
 // EMIT_MIR inline_compatibility.not_inlined_no_sanitize.Inline.diff
 pub unsafe fn not_inlined_no_sanitize() {
+    // CHECK-LABEL: fn not_inlined_no_sanitize(
+    // CHECK-NOT: (inlined no_sanitize)
     no_sanitize();
 }
 
@@ -41,6 +48,8 @@ pub unsafe fn no_sanitize() {}
 
 // EMIT_MIR inline_compatibility.not_inlined_c_variadic.Inline.diff
 pub unsafe fn not_inlined_c_variadic() {
+    // CHECK-LABEL: fn not_inlined_c_variadic(
+    // CHECK-NOT: (inlined sum)
     let s = sum(4u32, 4u32, 30u32, 200u32, 1000u32);
 }
 

From 196c9ef30aa8480c934594082265c80b8bf59208 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 18:03:13 -0700
Subject: [PATCH 14/38] FileCheck inline_diverging

---
 tests/mir-opt/inline/inline_diverging.rs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_diverging.rs b/tests/mir-opt/inline/inline_diverging.rs
index 9e50b1ead2bc0..25a5b9c5c5e72 100644
--- a/tests/mir-opt/inline/inline_diverging.rs
+++ b/tests/mir-opt/inline/inline_diverging.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // Tests inlining of diverging calls.
 //
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
@@ -7,6 +6,8 @@
 
 // EMIT_MIR inline_diverging.f.Inline.diff
 pub fn f() {
+    // CHECK-LABEL: fn f(
+    // CHECK: (inlined sleep)
     sleep();
 }
 
@@ -15,12 +16,17 @@ pub fn g(i: i32) -> u32 {
     if i > 0 {
         i as u32
     } else {
+        // CHECK-LABEL: fn g(
+        // CHECK: (inlined panic)
         panic();
     }
 }
 
 // EMIT_MIR inline_diverging.h.Inline.diff
 pub fn h() {
+    // CHECK-LABEL: fn h(
+    // CHECK: (inlined call_twice::<!, fn() -> ! {sleep}>)
+    // CHECK-NOT: inlined
     call_twice(sleep);
 }
 

From ac2278b79a9419b623c0ff4efed55953f695dd2f Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 18:15:32 -0700
Subject: [PATCH 15/38] FileCheck inline_coroutine

---
 ...ne_coroutine.main.Inline.panic-unwind.diff | 22 +++++++++----------
 tests/mir-opt/inline/inline_coroutine.rs      |  4 +++-
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
index e7d020968389f..fdb42bf3d8a0e 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
@@ -4,26 +4,26 @@
   fn main() -> () {
       let mut _0: ();
       let _1: std::ops::CoroutineState<i32, bool>;
-      let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>;
-      let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
-      let mut _4: {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
+      let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>;
+      let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
+      let mut _4: {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
 +     let mut _5: bool;
       scope 1 {
           debug _r => _1;
       }
 +     scope 2 (inlined g) {
 +     }
-+     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new) {
++     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 {
-+             scope 5 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new_unchecked) {
++             scope 5 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) {
 +                 debug pointer => _3;
 +             }
 +         }
 +     }
 +     scope 6 (inlined g::{closure#0}) {
 +         debug a => _5;
-+         let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8};
++         let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8};
 +         let mut _7: u32;
 +         let mut _8: i32;
 +     }
@@ -37,20 +37,20 @@
 -     }
 - 
 -     bb1: {
-+         _4 = {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8 (#0)};
++         _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
           _3 = &mut _4;
--         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new(move _3) -> [return: bb2, unwind: bb5];
+-         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind: bb5];
 -     }
 - 
 -     bb2: {
-+         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}> { pointer: move _3 };
++         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: move _3 };
           StorageDead(_3);
--         _1 = <{coroutine@$DIR/inline_coroutine.rs:17:5: 17:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
+-         _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
 +         StorageLive(_5);
 +         _5 = const false;
 +         StorageLive(_6);
 +         StorageLive(_7);
-+         _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8});
++         _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8});
 +         _7 = discriminant((*_6));
 +         switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11];
       }
diff --git a/tests/mir-opt/inline/inline_coroutine.rs b/tests/mir-opt/inline/inline_coroutine.rs
index d021cdac28efa..a82586bf2bfac 100644
--- a/tests/mir-opt/inline/inline_coroutine.rs
+++ b/tests/mir-opt/inline/inline_coroutine.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // compile-flags: -Zinline-mir-hint-threshold=1000
 #![feature(coroutines, coroutine_trait)]
@@ -8,6 +7,9 @@ use std::pin::Pin;
 
 // EMIT_MIR inline_coroutine.main.Inline.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: (inlined g)
+    // CHECK: (inlined g::{closure#0})
     let _r = Pin::new(&mut g()).resume(false);
 }
 

From 13138662fdeeb8557d9d32a8c2e717b6013fbb7f Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 18:21:41 -0700
Subject: [PATCH 16/38] FileCheck inline_instruction_set

---
 tests/mir-opt/inline/inline_instruction_set.rs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_instruction_set.rs b/tests/mir-opt/inline/inline_instruction_set.rs
index 4ac4d462f82de..7cb59645587b6 100644
--- a/tests/mir-opt/inline/inline_instruction_set.rs
+++ b/tests/mir-opt/inline/inline_instruction_set.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // Checks that only functions with the compatible instruction_set attributes are inlined.
 //
 // A function is "compatible" when the *callee* has the same attribute or no attribute.
@@ -47,16 +46,26 @@ fn inline_always_and_using_inline_asm() {
 // EMIT_MIR inline_instruction_set.t32.Inline.diff
 #[instruction_set(arm::t32)]
 pub fn t32() {
+    // CHECK-LABEL: fn t32(
+    // CHECK-NOT: (inlined instruction_set_a32)
     instruction_set_a32();
+    // CHECK: (inlined instruction_set_t32)
     instruction_set_t32();
+    // CHECK: (inlined instruction_set_default)
     instruction_set_default();
+    // CHECK-NOT: (inlined inline_always_and_using_inline_asm)
     inline_always_and_using_inline_asm();
 }
 
 // EMIT_MIR inline_instruction_set.default.Inline.diff
 pub fn default() {
+    // CHECK-LABEL: fn default(
+    // CHECK-NOT: (inlined instruction_set_a32)
     instruction_set_a32();
+    // CHECK-NOT: (inlined instruction_set_t32)
     instruction_set_t32();
+    // CHECK: (inlined instruction_set_default)
     instruction_set_default();
+    // CHECK: (inlined inline_always_and_using_inline_asm)
     inline_always_and_using_inline_asm();
 }

From 6e01ab9650173a18759c767d1deab95fd66986cc Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 20:33:22 -0700
Subject: [PATCH 17/38] FileCheck inline_into_box_place

---
 tests/mir-opt/inline/inline_into_box_place.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_into_box_place.rs b/tests/mir-opt/inline/inline_into_box_place.rs
index b755692afc214..65f8e2916b630 100644
--- a/tests/mir-opt/inline/inline_into_box_place.rs
+++ b/tests/mir-opt/inline/inline_into_box_place.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // ignore-endian-big
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // ignore-debug MIR alignment checks in std alter the diff, breaking the test
@@ -6,5 +5,7 @@
 
 // EMIT_MIR inline_into_box_place.main.Inline.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: (inlined Box::<Vec<u32>>::new)
     let _x: Box<Vec<u32>> = Box::new(Vec::new());
 }

From 0764c8bdb3c04948c212a7bc0ae7f04e6acd2192 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 20:34:41 -0700
Subject: [PATCH 18/38] FileCheck inline_options

---
 tests/mir-opt/inline/inline_options.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_options.rs b/tests/mir-opt/inline/inline_options.rs
index 394a8c4945cdd..b940c64f0b886 100644
--- a/tests/mir-opt/inline/inline_options.rs
+++ b/tests/mir-opt/inline/inline_options.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // Checks that inlining threshold can be controlled with
 // inline-mir-threshold and inline-hint-threshold options.
@@ -8,7 +7,10 @@
 
 // EMIT_MIR inline_options.main.Inline.after.mir
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK-NOT: (inlined not_inlined)
     not_inlined();
+    // CHECK: (inlined inlined::<u32>)
     inlined::<u32>();
 }
 

From 0a8a0132aced59a217b2fa757fa8383a69a29419 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 20:38:15 -0700
Subject: [PATCH 19/38] FileCheck inline_retag

---
 tests/mir-opt/inline/inline_retag.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_retag.rs b/tests/mir-opt/inline/inline_retag.rs
index f695b9f22e616..c90c0b819b7ba 100644
--- a/tests/mir-opt/inline/inline_retag.rs
+++ b/tests/mir-opt/inline/inline_retag.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // compile-flags: -Z span_free_formats -Z mir-emit-retag
 
 // Tests that MIR inliner fixes up `Retag`'s `fn_entry` flag
@@ -9,6 +8,8 @@ fn main() {
 
 // EMIT_MIR inline_retag.bar.Inline.after.mir
 fn bar() -> bool {
+    // CHECK-LABEL: fn bar(
+    // CHECK: (inlined foo)
     let f = foo;
     f(&1, &-1)
 }

From af6b86ee381f7699ec84bfb94c4461ce1c5319b9 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 20:40:20 -0700
Subject: [PATCH 20/38] FileCheck inline_specialization

---
 tests/mir-opt/inline/inline_specialization.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_specialization.rs b/tests/mir-opt/inline/inline_specialization.rs
index eb0cf891dad01..6453abc008129 100644
--- a/tests/mir-opt/inline/inline_specialization.rs
+++ b/tests/mir-opt/inline/inline_specialization.rs
@@ -1,9 +1,10 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 #![feature(specialization)]
 
 // EMIT_MIR inline_specialization.main.Inline.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: (inlined <Vec<()> as Foo>::bar)
     let x = <Vec::<()> as Foo>::bar();
 }
 

From ac19ff31082ef743b6c306cda68d957dbc84e2db Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 20:41:43 -0700
Subject: [PATCH 21/38] FileCheck inline_trait_method_2

---
 tests/mir-opt/inline/inline_trait_method_2.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_trait_method_2.rs b/tests/mir-opt/inline/inline_trait_method_2.rs
index e87609a8c7e00..b0b6a7b9b01de 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.rs
+++ b/tests/mir-opt/inline/inline_trait_method_2.rs
@@ -1,9 +1,11 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // compile-flags: -Z span_free_formats -Z mir-opt-level=4
 
 // EMIT_MIR inline_trait_method_2.test2.Inline.after.mir
 fn test2(x: &dyn X) -> bool {
+    // CHECK-LABEL: fn test2(
+    // CHECK: (inlined test)
+    // CHECK-NOT: (inlined <dyn X as X>::y)
     test(x)
 }
 

From 6eedec5f0e4b272127730c34d953ec4640332555 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 21:32:56 -0700
Subject: [PATCH 22/38] FileCheck inline_trait_method

---
 tests/mir-opt/inline/inline_trait_method.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/inline_trait_method.rs b/tests/mir-opt/inline/inline_trait_method.rs
index 8a95adf3713e2..ea09966a2aa94 100644
--- a/tests/mir-opt/inline/inline_trait_method.rs
+++ b/tests/mir-opt/inline/inline_trait_method.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // compile-flags: -Z span_free_formats
 
@@ -8,6 +7,8 @@ fn main() {
 
 // EMIT_MIR inline_trait_method.test.Inline.after.mir
 fn test(x: &dyn X) -> u32 {
+    // CHECK-LABEL: fn test(
+    // CHECK-NOT: (inlined <dyn X as X>::y)
     x.y()
 }
 

From 2846971ce578d20ee8cd85db1354765e8194ee5e Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 21:41:07 -0700
Subject: [PATCH 23/38] FileCheck inline_as_ref_as_mut

---
 tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs
index da779fed76fb5..4517c88d71340 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs
@@ -1,21 +1,28 @@
-// skip-filecheck
 // EMIT_MIR issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
 pub fn a<T>(x: &mut [T]) -> &mut [T] {
+    // CHECK-LABEL: fn a(
+    // CHECK: (inlined <[T] as AsMut<[T]>>::as_mut)
     x.as_mut()
 }
 
 // EMIT_MIR issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
 pub fn b<T>(x: &mut Box<T>) -> &mut T {
+    // CHECK-LABEL: fn b(
+    // CHECK: (inlined <Box<T> as AsMut<T>>::as_mut)
     x.as_mut()
 }
 
 // EMIT_MIR issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
 pub fn c<T>(x: &[T]) -> &[T] {
+    // CHECK-LABEL: fn c(
+    // CHECK: (inlined <[T] as AsRef<[T]>>::as_ref)
     x.as_ref()
 }
 
 // EMIT_MIR issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
 pub fn d<T>(x: &Box<T>) -> &T {
+    // CHECK-LABEL: fn d(
+    // CHECK: (inlined <Box<T> as AsRef<T>>::as_ref)
     x.as_ref()
 }
 

From 13fe05c2725ad8a19e9fc4b08ae49a908b068d6b Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 21:57:08 -0700
Subject: [PATCH 24/38] FileCheck inline_scopes_parenting

---
 ...ssue_76997_inline_scopes_parenting.main.Inline.after.mir | 6 +++---
 tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs | 6 +++++-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
index d28c0441f63c3..ba5eb757cf977 100644
--- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
@@ -2,8 +2,8 @@
 
 fn main() -> () {
     let mut _0: ();
-    let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:6:13: 6:16};
-    let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:6:13: 6:16};
+    let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16};
+    let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16};
     let mut _3: ((),);
     let mut _4: ();
     let mut _5: ();
@@ -19,7 +19,7 @@ fn main() -> () {
 
     bb0: {
         StorageLive(_1);
-        _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:6:13: 6:16};
+        _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16};
         StorageLive(_2);
         _2 = &_1;
         StorageLive(_3);
diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
index c7147d42df996..2a7c931a659ee 100644
--- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
+++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
@@ -1,8 +1,12 @@
-// skip-filecheck
 // Tests that MIR inliner can handle `SourceScopeData` parenting correctly. (#76997)
 
 // EMIT_MIR issue_76997_inline_scopes_parenting.main.Inline.after.mir
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: scope 2
+    // CHECK-NEXT: debug x
+    // CHECK-NEXT: scope 3
+    // CHECK-NEXT: debug y
     let f = |x| { let y = x; y };
     f(())
 }

From 1950f290f4f90507a99e7486bb7085360fcafd62 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 22:06:38 -0700
Subject: [PATCH 25/38] FileCheck issue_78442

---
 tests/mir-opt/inline/issue_78442.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/issue_78442.rs b/tests/mir-opt/inline/issue_78442.rs
index f83ed70d0db32..f9a5234283a03 100644
--- a/tests/mir-opt/inline/issue_78442.rs
+++ b/tests/mir-opt/inline/issue_78442.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // compile-flags: -Z mir-opt-level=3 -Z inline-mir
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 #![crate_type = "lib"]
@@ -9,6 +8,11 @@ pub fn bar<P>(
     // Error won't happen if "bar" is not generic
     _baz: P,
 ) {
+    // CHECK-LABEL: fn bar(
+    // CHECK: let mut {{.*}}: &fn() {foo};
+    // CHECK: let {{.*}}: fn() {foo};
+    // CHECK: (inlined hide_foo)
+    // CHECK-NOT: inlined
     hide_foo()();
 }
 

From 587926c12426c0b37f18b7ca4b0b42ceec069167 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 22:18:02 -0700
Subject: [PATCH 26/38] FileCheck unchecked_shifts

---
 tests/mir-opt/inline/unchecked_shifts.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/unchecked_shifts.rs b/tests/mir-opt/inline/unchecked_shifts.rs
index 67666f2f713f2..805195dd8b375 100644
--- a/tests/mir-opt/inline/unchecked_shifts.rs
+++ b/tests/mir-opt/inline/unchecked_shifts.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 #![crate_type = "lib"]
 #![feature(unchecked_math)]
@@ -9,23 +8,31 @@
 // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
 // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
 pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
+    // CHECK-LABEL: fn unchecked_shl_unsigned_smaller(
+    // CHECK: (inlined core::num::<impl u16>::unchecked_shl)
     a.unchecked_shl(b)
 }
 
 // EMIT_MIR unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
 // EMIT_MIR unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
 pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
+    // CHECK-LABEL: fn unchecked_shr_signed_smaller(
+    // CHECK: (inlined core::num::<impl i16>::unchecked_shr)
     a.unchecked_shr(b)
 }
 
 // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.diff
 // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.mir
 pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 {
+    // CHECK-LABEL: fn unchecked_shl_unsigned_bigger(
+    // CHECK: (inlined core::num::<impl u64>::unchecked_shl)
     a.unchecked_shl(b)
 }
 
 // EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.Inline.diff
 // EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.mir
 pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {
+    // CHECK-LABEL: fn unchecked_shr_signed_bigger(
+    // CHECK: (inlined core::num::<impl i64>::unchecked_shr)
     a.unchecked_shr(b)
 }

From 1fa26012887e6f272165bac952a0564536409f11 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 22:21:03 -0700
Subject: [PATCH 27/38] FileCheck unsized_argument

---
 tests/mir-opt/inline/unsized_argument.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/unsized_argument.rs b/tests/mir-opt/inline/unsized_argument.rs
index 22c88b83f9b1b..e8c2bc10be220 100644
--- a/tests/mir-opt/inline/unsized_argument.rs
+++ b/tests/mir-opt/inline/unsized_argument.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // needs-unwind
 #![feature(unsized_fn_params)]
 
@@ -7,6 +6,8 @@ fn callee(y: [i32]) {}
 
 // EMIT_MIR unsized_argument.caller.Inline.diff
 fn caller(x: Box<[i32]>) {
+    // CHECK-LABEL: fn caller(
+    // CHECK-NOT: (inlined callee)
     callee(*x);
 }
 

From f474cf4de596c54f7cee73749a0b54137e9635bd Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Fri, 20 Oct 2023 22:22:32 -0700
Subject: [PATCH 28/38] FileCheck unwrap_unchecked

---
 tests/mir-opt/inline/unwrap_unchecked.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/mir-opt/inline/unwrap_unchecked.rs b/tests/mir-opt/inline/unwrap_unchecked.rs
index f8964eba227a4..be133706e5c22 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.rs
+++ b/tests/mir-opt/inline/unwrap_unchecked.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 #![crate_type = "lib"]
 
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
@@ -8,5 +7,7 @@
 // EMIT_MIR unwrap_unchecked.unwrap_unchecked.Inline.diff
 // EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
 pub unsafe fn unwrap_unchecked<T>(slf: Option<T>) -> T {
+    // CHECK-LABEL: fn unwrap_unchecked(
+    // CHECK: (inlined #[track_caller] Option::<T>::unwrap_unchecked)
     slf.unwrap_unchecked()
 }

From 1f35769f994ebd00d5a93125f5e1f7856a90d1e5 Mon Sep 17 00:00:00 2001
From: Ryan Mehri <ryan.mehri1@gmail.com>
Date: Sun, 22 Oct 2023 09:27:43 -0700
Subject: [PATCH 29/38] address review comments

---
 tests/mir-opt/inline/asm_unwind.rs            |  3 +
 .../inline/caller_with_trivial_bound.rs       |  3 +
 tests/mir-opt/inline/cycle.rs                 |  2 +
 .../inline/dont_ice_on_generic_rust_call.rs   |  2 +-
 tests/mir-opt/inline/dyn_trait.rs             |  4 +-
 tests/mir-opt/inline/exponential_runtime.rs   |  1 +
 tests/mir-opt/inline/inline_box_fn.rs         |  2 +-
 .../inline/inline_retag.bar.Inline.after.mir  | 59 -----------------
 .../inline/inline_retag.bar.Inline.diff       | 65 +++++++++++++++++++
 tests/mir-opt/inline/inline_retag.rs          | 11 +++-
 tests/mir-opt/inline/inline_trait_method.rs   |  3 +-
 ...ine_scopes_parenting.main.Inline.after.mir |  6 +-
 .../issue_76997_inline_scopes_parenting.rs    |  9 ++-
 13 files changed, 100 insertions(+), 70 deletions(-)
 delete mode 100644 tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
 create mode 100644 tests/mir-opt/inline/inline_retag.bar.Inline.diff

diff --git a/tests/mir-opt/inline/asm_unwind.rs b/tests/mir-opt/inline/asm_unwind.rs
index 596a4592f25ff..0ae20e5221110 100644
--- a/tests/mir-opt/inline/asm_unwind.rs
+++ b/tests/mir-opt/inline/asm_unwind.rs
@@ -2,6 +2,7 @@
 //
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // needs-asm-support
+// needs-unwind
 // compile-flags: -Zinline-mir-hint-threshold=1000
 #![feature(asm_unwind)]
 
@@ -21,5 +22,7 @@ fn foo() {
 pub fn main() {
     // CHECK-LABEL: fn main(
     // CHECK: (inlined foo)
+    // CHECK: asm!("", options(MAY_UNWIND)) -> [return: {{bb.*}}, unwind: [[unwind:bb.*]]];
+    // CHECK: [[unwind]] (cleanup)
     foo();
 }
diff --git a/tests/mir-opt/inline/caller_with_trivial_bound.rs b/tests/mir-opt/inline/caller_with_trivial_bound.rs
index 722c7f6724efd..40f7f4bbab2f7 100644
--- a/tests/mir-opt/inline/caller_with_trivial_bound.rs
+++ b/tests/mir-opt/inline/caller_with_trivial_bound.rs
@@ -15,6 +15,9 @@ impl<T> Factory<T> for IntFactory {
 // EMIT_MIR caller_with_trivial_bound.foo.Inline.diff
 pub fn foo<T>()
 where
+    // Because of this trivial bound, the inliner fails to normalize
+    // `<IntFactory as Factory<T>>::Item`.
+    // Verify that we do not inline anything, which would cause validation ICEs.
     IntFactory: Factory<T>,
 {
     // CHECK-LABEL: fn foo(
diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs
index 8716b44b3dc02..350724235ba04 100644
--- a/tests/mir-opt/inline/cycle.rs
+++ b/tests/mir-opt/inline/cycle.rs
@@ -13,6 +13,7 @@ fn f(g: impl Fn()) {
 #[inline(always)]
 fn g() {
     // CHECK-LABEL: fn g(
+    // CHECK-NOT: inlined
     // CHECK: (inlined f::<fn() {main}>)
     // CHECK-NOT: inlined
     f(main);
@@ -21,6 +22,7 @@ fn g() {
 // EMIT_MIR cycle.main.Inline.diff
 fn main() {
     // CHECK-LABEL: fn main(
+    // CHECK-NOT: inlined
     // CHECK: (inlined f::<fn() {g}>)
     // CHECK-NOT: inlined
     f(g);
diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
index 3307a1408fb56..ce5e1855a716b 100644
--- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
+++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs
@@ -8,6 +8,6 @@ use std::marker::Tuple;
 // EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff
 pub fn call<I: Tuple>(mut mock: Box<dyn FnMut<I, Output = ()>>, input: I) {
     // CHECK-LABEL: fn call(
-    // CHECK-NOT: (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut)
+    // CHECK-NOT: inlined
     mock.call_mut(input)
 }
diff --git a/tests/mir-opt/inline/dyn_trait.rs b/tests/mir-opt/inline/dyn_trait.rs
index 005cf155fdb93..ecf220a85e6a3 100644
--- a/tests/mir-opt/inline/dyn_trait.rs
+++ b/tests/mir-opt/inline/dyn_trait.rs
@@ -20,7 +20,7 @@ pub trait Query {
 #[inline(always)]
 pub fn mk_cycle<V: Debug>(c: &dyn Cache<V = V>) {
     // CHECK-LABEL: fn mk_cycle(
-    // CHECK-NOT: (inlined <dyn Cache<V = V> as Cache>::store_nocache)
+    // CHECK-NOT: inlined
     c.store_nocache()
 }
 
@@ -36,7 +36,7 @@ pub fn try_execute_query<C: Cache>(c: &C) {
 #[inline(always)]
 pub fn get_query<Q: Query, T>(t: &T) {
     // CHECK-LABEL: fn get_query(
-    // CHECK-NOT: (inlined <Q as Query>::cache::<T>)
+    // CHECK-NOT: inlined
     let c = Q::cache(t);
     // CHECK: (inlined try_execute_query::<<Q as Query>::C>)
     // CHECK: (inlined mk_cycle::<<Q as Query>::V>)
diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs
index 499bec33ffc9b..1199ce4e5588e 100644
--- a/tests/mir-opt/inline/exponential_runtime.rs
+++ b/tests/mir-opt/inline/exponential_runtime.rs
@@ -85,6 +85,7 @@ impl A for () {
 // EMIT_MIR exponential_runtime.main.Inline.diff
 fn main() {
     // CHECK-LABEL: fn main(
+    // CHECK-NOT: inlined
     // CHECK: (inlined <() as G>::call)
     // CHECK: (inlined <() as F>::call)
     // CHECK: (inlined <() as E>::call)
diff --git a/tests/mir-opt/inline/inline_box_fn.rs b/tests/mir-opt/inline/inline_box_fn.rs
index 7686477c291a3..d2da239399235 100644
--- a/tests/mir-opt/inline/inline_box_fn.rs
+++ b/tests/mir-opt/inline/inline_box_fn.rs
@@ -5,6 +5,6 @@
 // EMIT_MIR inline_box_fn.call.Inline.diff
 fn call(x: Box<dyn Fn(i32)>) {
     // CHECK-LABEL: fn call(
-    // CHECK-NOT: (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call)
+    // CHECK-NOT: inlined
     x(1);
 }
diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
deleted file mode 100644
index 8c3f3a4589e63..0000000000000
--- a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ /dev/null
@@ -1,59 +0,0 @@
-// MIR for `bar` after Inline
-
-fn bar() -> bool {
-    let mut _0: bool;
-    let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo};
-    let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo};
-    let mut _3: &i32;
-    let _4: &i32;
-    let _5: i32;
-    let mut _6: &i32;
-    let _7: &i32;
-    let _8: i32;
-    scope 1 {
-        debug f => _1;
-        let mut _9: &i32;
-        let mut _10: &i32;
-        scope 2 (inlined foo) {
-            debug x => _3;
-            debug y => _6;
-            let mut _11: i32;
-            let mut _12: i32;
-        }
-    }
-
-    bb0: {
-        StorageLive(_1);
-        _1 = foo;
-        StorageLive(_2);
-        _2 = _1;
-        StorageLive(_3);
-        StorageLive(_4);
-        _10 = const _;
-        Retag(_10);
-        _4 = &(*_10);
-        _3 = &(*_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        _9 = const _;
-        Retag(_9);
-        _7 = &(*_9);
-        _6 = &(*_7);
-        Retag(_3);
-        Retag(_6);
-        StorageLive(_11);
-        _11 = (*_3);
-        StorageLive(_12);
-        _12 = (*_6);
-        _0 = Eq(move _11, move _12);
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_6);
-        StorageDead(_3);
-        StorageDead(_2);
-        StorageDead(_1);
-        StorageDead(_7);
-        StorageDead(_4);
-        return;
-    }
-}
diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.diff b/tests/mir-opt/inline/inline_retag.bar.Inline.diff
new file mode 100644
index 0000000000000..8f53f6342ec6d
--- /dev/null
+++ b/tests/mir-opt/inline/inline_retag.bar.Inline.diff
@@ -0,0 +1,65 @@
+- // MIR for `bar` before Inline
++ // MIR for `bar` after Inline
+  
+  fn bar() -> bool {
+      let mut _0: bool;
+      let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo};
+      let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo};
+      let mut _3: &i32;
+      let _4: &i32;
+      let _5: i32;
+      let mut _6: &i32;
+      let _7: &i32;
+      let _8: i32;
+      scope 1 {
+          debug f => _1;
+          let mut _9: &i32;
+          let mut _10: &i32;
++         scope 2 (inlined foo) {
++             debug x => _3;
++             debug y => _6;
++             let mut _11: i32;
++             let mut _12: i32;
++         }
+      }
+  
+      bb0: {
+          StorageLive(_1);
+          _1 = foo;
+          StorageLive(_2);
+          _2 = _1;
+          StorageLive(_3);
+          StorageLive(_4);
+          _10 = const _;
+          Retag(_10);
+          _4 = &(*_10);
+          _3 = &(*_4);
+          StorageLive(_6);
+          StorageLive(_7);
+          _9 = const _;
+          Retag(_9);
+          _7 = &(*_9);
+          _6 = &(*_7);
+-         _0 = move _2(move _3, move _6) -> [return: bb1, unwind continue];
+-     }
+- 
+-     bb1: {
++         Retag(_3);
++         Retag(_6);
++         StorageLive(_11);
++         _11 = (*_3);
++         StorageLive(_12);
++         _12 = (*_6);
++         _0 = Eq(move _11, move _12);
++         StorageDead(_12);
++         StorageDead(_11);
+          StorageDead(_6);
+          StorageDead(_3);
+          StorageDead(_2);
+          StorageDead(_1);
+          StorageDead(_7);
+          StorageDead(_4);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/inline/inline_retag.rs b/tests/mir-opt/inline/inline_retag.rs
index c90c0b819b7ba..b9058905892bf 100644
--- a/tests/mir-opt/inline/inline_retag.rs
+++ b/tests/mir-opt/inline/inline_retag.rs
@@ -6,10 +6,19 @@ fn main() {
     println!("{}", bar());
 }
 
-// EMIT_MIR inline_retag.bar.Inline.after.mir
+// EMIT_MIR inline_retag.bar.Inline.diff
 fn bar() -> bool {
     // CHECK-LABEL: fn bar(
     // CHECK: (inlined foo)
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: bb0: {
+    // CHECK: Retag
+    // CHECK: Retag
+    // CHECK: Retag([[x]]);
+    // CHECK: Retag([[y]]);
+    // CHECK: return;
+    // CHECK-NEXT: }
     let f = foo;
     f(&1, &-1)
 }
diff --git a/tests/mir-opt/inline/inline_trait_method.rs b/tests/mir-opt/inline/inline_trait_method.rs
index ea09966a2aa94..b39355637a1c5 100644
--- a/tests/mir-opt/inline/inline_trait_method.rs
+++ b/tests/mir-opt/inline/inline_trait_method.rs
@@ -1,3 +1,4 @@
+// Verify that we do not inline the default impl in a trait object.
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // compile-flags: -Z span_free_formats
 
@@ -8,7 +9,7 @@ fn main() {
 // EMIT_MIR inline_trait_method.test.Inline.after.mir
 fn test(x: &dyn X) -> u32 {
     // CHECK-LABEL: fn test(
-    // CHECK-NOT: (inlined <dyn X as X>::y)
+    // CHECK-NOT: inlined
     x.y()
 }
 
diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
index ba5eb757cf977..ba4f91b28d536 100644
--- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
@@ -2,8 +2,8 @@
 
 fn main() -> () {
     let mut _0: ();
-    let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16};
-    let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16};
+    let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:15:13: 15:16};
+    let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:15:13: 15:16};
     let mut _3: ((),);
     let mut _4: ();
     let mut _5: ();
@@ -19,7 +19,7 @@ fn main() -> () {
 
     bb0: {
         StorageLive(_1);
-        _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16};
+        _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:15:13: 15:16};
         StorageLive(_2);
         _2 = &_1;
         StorageLive(_3);
diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
index 2a7c931a659ee..2fb363c19044d 100644
--- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
+++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs
@@ -3,10 +3,15 @@
 // EMIT_MIR issue_76997_inline_scopes_parenting.main.Inline.after.mir
 fn main() {
     // CHECK-LABEL: fn main(
-    // CHECK: scope 2
+    // CHECK: scope 1 {
+    // CHECK-NEXT: debug f
+    // CHECK-NEXT: scope 2 (inlined main::{closure#0}) {
     // CHECK-NEXT: debug x
-    // CHECK-NEXT: scope 3
+    // CHECK-NEXT: scope 3 {
     // CHECK-NEXT: debug y
+    // CHECK-NEXT: }
+    // CHECK-NEXT: }
+    // CHECK-NEXT: }
     let f = |x| { let y = x; y };
     f(())
 }

From 66a554b04539a1319c68b3d52c7c3e027208dfec Mon Sep 17 00:00:00 2001
From: "Celina G. Val" <celinval@amazon.com>
Date: Fri, 20 Oct 2023 23:05:38 -0700
Subject: [PATCH 30/38] Add method to convert internal to stable constructs

---
 Cargo.lock                                    |   1 +
 compiler/rustc_smir/Cargo.toml                |   1 +
 compiler/rustc_smir/src/rustc_internal/mod.rs |  58 ++++-
 compiler/rustc_smir/src/rustc_smir/mod.rs     | 206 +++++++++++-------
 compiler/stable_mir/src/lib.rs                |  52 ++---
 5 files changed, 197 insertions(+), 121 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5f8d566c2d156..d0422340c5258 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4524,6 +4524,7 @@ dependencies = [
  "rustc_middle",
  "rustc_span",
  "rustc_target",
+ "scoped-tls",
  "stable_mir",
  "tracing",
 ]
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index 41c7d3a859437..47dd7372f3d18 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -9,6 +9,7 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
+scoped-tls = "1.0"
 stable_mir = {path = "../stable_mir" }
 tracing = "0.1"
 
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index f7e519570fa56..7bec946788b31 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -3,7 +3,7 @@
 //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
 //! until stable MIR is complete.
 
-use crate::rustc_smir::Tables;
+use crate::rustc_smir::{Stable, Tables, TablesWrapper};
 use rustc_data_structures::fx;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_middle::mir::interpret::AllocId;
@@ -11,13 +11,21 @@ use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::Span;
+use scoped_tls::scoped_thread_local;
 use stable_mir::ty::IndexedVal;
+use std::cell::Cell;
+use std::cell::RefCell;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::ops::Index;
+use std::rc::Rc;
 
 mod internal;
 
+pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T {
+    with_tables(|tables| item.stable(tables))
+}
+
 impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
     type Output = DefId;
 
@@ -125,18 +133,44 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
     item.id.into()
 }
 
+// A thread local variable that stores a pointer to the tables mapping between TyCtxt
+// datastructures and stable MIR datastructures
+scoped_thread_local! (static TLV: Cell<*const ()>);
+
+pub(crate) fn init<'tcx>(tables: TablesWrapper<'tcx>, f: impl FnOnce()) {
+    assert!(!TLV.is_set());
+    fn g<'a, 'tcx>(context: &'a TablesWrapper<'tcx>, f: impl FnOnce()) {
+        let ptr: *const () = &context as *const &_ as _;
+        TLV.set(&Cell::new(ptr), || {
+            f();
+        });
+    }
+    g(&tables, f);
+}
+
+/// Loads the current context and calls a function with it.
+/// Do not nest these, as that will ICE.
+pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R {
+    assert!(TLV.is_set());
+    TLV.with(|tlv| {
+        let ptr = tlv.get();
+        assert!(!ptr.is_null());
+        let wrapper = unsafe { *(ptr as *const &TablesWrapper<'tcx>) };
+        let mut tables = wrapper.0.borrow_mut();
+        f(&mut *tables)
+    })
+}
+
 pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
-    stable_mir::run(
-        Tables {
-            tcx,
-            def_ids: IndexMap::default(),
-            alloc_ids: IndexMap::default(),
-            spans: IndexMap::default(),
-            types: vec![],
-            instances: IndexMap::default(),
-        },
-        f,
-    );
+    let tables = Rc::new(RefCell::new(Tables {
+        tcx,
+        def_ids: IndexMap::default(),
+        alloc_ids: IndexMap::default(),
+        spans: IndexMap::default(),
+        types: vec![],
+        instances: IndexMap::default(),
+    }));
+    stable_mir::run(TablesWrapper(Rc::clone(&tables)), || init(TablesWrapper(tables), f));
 }
 
 #[macro_export]
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index d5379797f1c6b..19ad9898db168 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -23,27 +23,31 @@ use stable_mir::ty::{
     FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy,
 };
 use stable_mir::{self, opaque, Context, Filename};
+use std::cell::RefCell;
 use tracing::debug;
 
 mod alloc;
 mod builder;
 
-impl<'tcx> Context for Tables<'tcx> {
+impl<'tcx> Context for TablesWrapper<'tcx> {
     fn local_crate(&self) -> stable_mir::Crate {
-        smir_crate(self.tcx, LOCAL_CRATE)
+        let tables = self.0.borrow();
+        smir_crate(tables.tcx, LOCAL_CRATE)
     }
 
     fn external_crates(&self) -> Vec<stable_mir::Crate> {
-        self.tcx.crates(()).iter().map(|crate_num| smir_crate(self.tcx, *crate_num)).collect()
+        let tables = self.0.borrow();
+        tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
     }
 
     fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
+        let tables = self.0.borrow();
         let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
             .iter()
-            .chain(self.tcx.crates(()).iter())
+            .chain(tables.tcx.crates(()).iter())
             .map(|crate_num| {
-                let crate_name = self.tcx.crate_name(*crate_num).to_string();
-                (name == crate_name).then(|| smir_crate(self.tcx, *crate_num))
+                let crate_name = tables.tcx.crate_name(*crate_num).to_string();
+                (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num))
             })
             .into_iter()
             .filter_map(|c| c)
@@ -52,163 +56,197 @@ impl<'tcx> Context for Tables<'tcx> {
     }
 
     fn name_of_def_id(&self, def_id: stable_mir::DefId) -> String {
-        self.tcx.def_path_str(self[def_id])
+        let tables = self.0.borrow();
+        tables.tcx.def_path_str(tables[def_id])
     }
 
     fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
-        self.tcx.sess.source_map().span_to_diagnostic_string(self[span])
+        let tables = self.0.borrow();
+        tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
     }
 
     fn get_filename(&self, span: &Span) -> Filename {
+        let tables = self.0.borrow();
         opaque(
-            &self
+            &tables
                 .tcx
                 .sess
                 .source_map()
-                .span_to_filename(self[*span])
+                .span_to_filename(tables[*span])
                 .display(rustc_span::FileNameDisplayPreference::Local)
                 .to_string(),
         )
     }
 
     fn get_lines(&self, span: &Span) -> LineInfo {
-        let lines = &self.tcx.sess.source_map().span_to_location_info(self[*span]);
+        let tables = self.0.borrow();
+        let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]);
         LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
     }
 
-    fn def_kind(&mut self, def_id: stable_mir::DefId) -> stable_mir::DefKind {
-        self.tcx.def_kind(self[def_id]).stable(self)
+    fn def_kind(&self, def_id: stable_mir::DefId) -> stable_mir::DefKind {
+        let mut tables = self.0.borrow_mut();
+        tables.tcx.def_kind(tables[def_id]).stable(&mut *tables)
     }
 
-    fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> Span {
-        self.tcx.def_span(self[def_id]).stable(self)
+    fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
+        let mut tables = self.0.borrow_mut();
+        tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
     }
 
-    fn all_local_items(&mut self) -> stable_mir::CrateItems {
-        self.tcx.mir_keys(()).iter().map(|item| self.crate_item(item.to_def_id())).collect()
+    fn all_local_items(&self) -> stable_mir::CrateItems {
+        let mut tables = self.0.borrow_mut();
+        tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect()
     }
 
-    fn entry_fn(&mut self) -> Option<stable_mir::CrateItem> {
-        Some(self.crate_item(self.tcx.entry_fn(())?.0))
+    fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        Some(tables.crate_item(tcx.entry_fn(())?.0))
     }
 
-    fn all_trait_decls(&mut self) -> stable_mir::TraitDecls {
-        self.tcx
+    fn all_trait_decls(&self) -> stable_mir::TraitDecls {
+        let mut tables = self.0.borrow_mut();
+        tables
+            .tcx
             .traits(LOCAL_CRATE)
             .iter()
-            .map(|trait_def_id| self.trait_def(*trait_def_id))
+            .map(|trait_def_id| tables.trait_def(*trait_def_id))
             .collect()
     }
 
-    fn trait_decl(&mut self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
-        let def_id = self[trait_def.0];
-        let trait_def = self.tcx.trait_def(def_id);
-        trait_def.stable(self)
+    fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
+        let mut tables = self.0.borrow_mut();
+        let def_id = tables[trait_def.0];
+        let trait_def = tables.tcx.trait_def(def_id);
+        trait_def.stable(&mut *tables)
     }
 
-    fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls {
-        self.tcx
+    fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
+        let mut tables = self.0.borrow_mut();
+        tables
+            .tcx
             .trait_impls_in_crate(LOCAL_CRATE)
             .iter()
-            .map(|impl_def_id| self.impl_def(*impl_def_id))
+            .map(|impl_def_id| tables.impl_def(*impl_def_id))
             .collect()
     }
 
-    fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
-        let def_id = self[impl_def.0];
-        let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap();
-        impl_trait.stable(self)
+    fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
+        let mut tables = self.0.borrow_mut();
+        let def_id = tables[impl_def.0];
+        let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap();
+        impl_trait.stable(&mut *tables)
     }
 
-    fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body {
-        let def_id = self[item];
-        self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self)
+    fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
+        let mut tables = self.0.borrow_mut();
+        let def_id = tables[item];
+        tables.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(&mut tables)
     }
 
-    fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind {
-        self.types[ty.0].clone().stable(self)
+    fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
+        let mut tables = self.0.borrow_mut();
+        tables.types[ty.0].clone().stable(&mut *tables)
     }
 
-    fn mk_ty(&mut self, kind: TyKind) -> stable_mir::ty::Ty {
-        let n = self.types.len();
-        self.types.push(MaybeStable::Stable(kind));
+    fn mk_ty(&self, kind: TyKind) -> stable_mir::ty::Ty {
+        let mut tables = self.0.borrow_mut();
+        let n = tables.types.len();
+        tables.types.push(MaybeStable::Stable(kind));
         stable_mir::ty::Ty(n)
     }
 
-    fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
-        let def_id = self[def_id];
-        let generics = self.tcx.generics_of(def_id);
-        generics.stable(self)
+    fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
+        let mut tables = self.0.borrow_mut();
+        let def_id = tables[def_id];
+        let generics = tables.tcx.generics_of(def_id);
+        generics.stable(&mut *tables)
     }
 
-    fn predicates_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
-        let def_id = self[def_id];
-        let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(def_id);
+    fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
+        let mut tables = self.0.borrow_mut();
+        let def_id = tables[def_id];
+        let ty::GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
         stable_mir::ty::GenericPredicates {
-            parent: parent.map(|did| self.trait_def(did)),
+            parent: parent.map(|did| tables.trait_def(did)),
             predicates: predicates
                 .iter()
                 .map(|(clause, span)| {
-                    (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self))
+                    (
+                        clause.as_predicate().kind().skip_binder().stable(&mut *tables),
+                        span.stable(&mut *tables),
+                    )
                 })
                 .collect(),
         }
     }
 
     fn explicit_predicates_of(
-        &mut self,
+        &self,
         def_id: stable_mir::DefId,
     ) -> stable_mir::ty::GenericPredicates {
-        let def_id = self[def_id];
-        let ty::GenericPredicates { parent, predicates } = self.tcx.explicit_predicates_of(def_id);
+        let mut tables = self.0.borrow_mut();
+        let def_id = tables[def_id];
+        let ty::GenericPredicates { parent, predicates } =
+            tables.tcx.explicit_predicates_of(def_id);
         stable_mir::ty::GenericPredicates {
-            parent: parent.map(|did| self.trait_def(did)),
+            parent: parent.map(|did| tables.trait_def(did)),
             predicates: predicates
                 .iter()
                 .map(|(clause, span)| {
-                    (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self))
+                    (
+                        clause.as_predicate().kind().skip_binder().stable(&mut *tables),
+                        span.stable(&mut *tables),
+                    )
                 })
                 .collect(),
         }
     }
 
-    fn instance_body(&mut self, def: InstanceDef) -> Body {
-        let instance = self.instances[def];
-        builder::BodyBuilder::new(self.tcx, instance).build(self)
+    fn instance_body(&self, def: InstanceDef) -> Body {
+        let mut tables = self.0.borrow_mut();
+        let instance = tables.instances[def];
+        builder::BodyBuilder::new(tables.tcx, instance).build(&mut *tables)
     }
 
-    fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty {
-        let instance = self.instances[def];
-        let ty = instance.ty(self.tcx, ParamEnv::empty());
-        self.intern_ty(ty)
+    fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
+        let mut tables = self.0.borrow_mut();
+        let instance = tables.instances[def];
+        let ty = instance.ty(tables.tcx, ParamEnv::empty());
+        tables.intern_ty(ty)
     }
 
-    fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId {
-        let def_id = self.instances[def].def_id();
-        self.create_def_id(def_id)
+    fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
+        let mut tables = self.0.borrow_mut();
+        let def_id = tables.instances[def].def_id();
+        tables.create_def_id(def_id)
     }
 
-    fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
-        let def_id = self[item.0];
-        Instance::mono(self.tcx, def_id).stable(self)
+    fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
+        let mut tables = self.0.borrow_mut();
+        let def_id = tables[item.0];
+        Instance::mono(tables.tcx, def_id).stable(&mut *tables)
     }
 
     fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
-        let def_id = self[def_id];
-        let generics = self.tcx.generics_of(def_id);
-        let result = generics.requires_monomorphization(self.tcx);
+        let tables = self.0.borrow();
+        let def_id = tables[def_id];
+        let generics = tables.tcx.generics_of(def_id);
+        let result = generics.requires_monomorphization(tables.tcx);
         result
     }
 
     fn resolve_instance(
-        &mut self,
+        &self,
         def: stable_mir::ty::FnDef,
         args: &stable_mir::ty::GenericArgs,
     ) -> Option<stable_mir::mir::mono::Instance> {
-        let def_id = def.0.internal(self);
-        let args_ref = args.internal(self);
-        match Instance::resolve(self.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
-            Ok(Some(instance)) => Some(instance.stable(self)),
+        let mut tables = self.0.borrow_mut();
+        let def_id = def.0.internal(&mut *tables);
+        let args_ref = args.internal(&mut *tables);
+        match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
+            Ok(Some(instance)) => Some(instance.stable(&mut *tables)),
             Ok(None) | Err(_) => None,
         }
     }
@@ -241,13 +279,15 @@ impl<S, R: PartialEq> PartialEq<R> for MaybeStable<S, R> {
     }
 }
 
+pub(crate) struct TablesWrapper<'tcx>(pub(crate) std::rc::Rc<RefCell<Tables<'tcx>>>);
+
 pub struct Tables<'tcx> {
-    pub tcx: TyCtxt<'tcx>,
-    pub def_ids: IndexMap<DefId, stable_mir::DefId>,
-    pub alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
-    pub spans: IndexMap<rustc_span::Span, Span>,
-    pub types: Vec<MaybeStable<TyKind, Ty<'tcx>>>,
-    pub instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
+    pub(crate) tcx: TyCtxt<'tcx>,
+    pub(crate) def_ids: IndexMap<DefId, stable_mir::DefId>,
+    pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
+    pub(crate) spans: IndexMap<rustc_span::Span, Span>,
+    pub(crate) types: Vec<MaybeStable<TyKind, Ty<'tcx>>>,
+    pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
 }
 
 impl<'tcx> Tables<'tcx> {
@@ -270,7 +310,7 @@ 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<'tcx> {
+pub trait Stable<'tcx> {
     /// The stable representation of the type implementing Stable.
     type T;
     /// Converts an object to the equivalent Stable MIR representation.
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index be5ccac78c7c6..512c3fc629645 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -175,17 +175,17 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
 }
 
 pub trait Context {
-    fn entry_fn(&mut self) -> Option<CrateItem>;
+    fn entry_fn(&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: 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;
-    fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
-    fn generics_of(&mut self, def_id: DefId) -> Generics;
-    fn predicates_of(&mut self, def_id: DefId) -> GenericPredicates;
-    fn explicit_predicates_of(&mut self, def_id: DefId) -> GenericPredicates;
+    fn all_local_items(&self) -> CrateItems;
+    fn mir_body(&self, item: DefId) -> mir::Body;
+    fn all_trait_decls(&self) -> TraitDecls;
+    fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
+    fn all_trait_impls(&self) -> ImplTraitDecls;
+    fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
+    fn generics_of(&self, def_id: DefId) -> Generics;
+    fn predicates_of(&self, def_id: DefId) -> GenericPredicates;
+    fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates;
     /// Get information about the local crate.
     fn local_crate(&self) -> Crate;
     /// Retrieve a list of all external crates.
@@ -207,61 +207,61 @@ pub trait Context {
     fn get_lines(&self, span: &Span) -> LineInfo;
 
     /// Returns the `kind` of given `DefId`
-    fn def_kind(&mut self, def_id: DefId) -> DefKind;
+    fn def_kind(&self, def_id: DefId) -> DefKind;
 
     /// `Span` of an item
-    fn span_of_an_item(&mut self, def_id: DefId) -> Span;
+    fn span_of_an_item(&self, def_id: DefId) -> Span;
 
     /// Obtain the representation of a type.
-    fn ty_kind(&mut self, ty: Ty) -> TyKind;
+    fn ty_kind(&self, ty: Ty) -> TyKind;
 
     /// Create a new `Ty` from scratch without information from rustc.
-    fn mk_ty(&mut self, kind: TyKind) -> Ty;
+    fn mk_ty(&self, kind: TyKind) -> Ty;
 
     /// Get the body of an Instance.
     /// FIXME: Monomorphize the body.
-    fn instance_body(&mut self, instance: InstanceDef) -> Body;
+    fn instance_body(&self, instance: InstanceDef) -> Body;
 
     /// Get the instance type with generic substitutions applied and lifetimes erased.
-    fn instance_ty(&mut self, instance: InstanceDef) -> Ty;
+    fn instance_ty(&self, instance: InstanceDef) -> Ty;
 
     /// Get the instance.
-    fn instance_def_id(&mut self, instance: InstanceDef) -> DefId;
+    fn instance_def_id(&self, instance: InstanceDef) -> DefId;
 
     /// Convert a non-generic crate item into an instance.
     /// This function will panic if the item is generic.
-    fn mono_instance(&mut self, item: CrateItem) -> Instance;
+    fn mono_instance(&self, item: CrateItem) -> Instance;
 
     /// Item requires monomorphization.
     fn requires_monomorphization(&self, def_id: DefId) -> bool;
 
     /// Resolve an instance from the given function definition and generic arguments.
-    fn resolve_instance(&mut self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
+    fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
 }
 
 // A thread local variable that stores a pointer to the tables mapping between TyCtxt
 // datastructures and stable MIR datastructures
-scoped_thread_local! (static TLV: Cell<*mut ()>);
+scoped_thread_local! (static TLV: Cell<*const ()>);
 
-pub fn run(mut context: impl Context, f: impl FnOnce()) {
+pub fn run(context: impl Context, f: impl FnOnce()) {
     assert!(!TLV.is_set());
-    fn g<'a>(mut context: &mut (dyn Context + 'a), f: impl FnOnce()) {
-        let ptr: *mut () = &mut context as *mut &mut _ as _;
+    fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) {
+        let ptr: *const () = &context as *const &_ as _;
         TLV.set(&Cell::new(ptr), || {
             f();
         });
     }
-    g(&mut context, f);
+    g(&context, f);
 }
 
 /// Loads the current context and calls a function with it.
 /// Do not nest these, as that will ICE.
-pub fn with<R>(f: impl FnOnce(&mut dyn Context) -> R) -> R {
+pub fn with<R>(f: impl FnOnce(&dyn Context) -> R) -> R {
     assert!(TLV.is_set());
     TLV.with(|tlv| {
         let ptr = tlv.get();
         assert!(!ptr.is_null());
-        f(unsafe { *(ptr as *mut &mut dyn Context) })
+        f(unsafe { *(ptr as *const &dyn Context) })
     })
 }
 

From f613b26cfbfea5d7b1afbbad57be8e5774669775 Mon Sep 17 00:00:00 2001
From: "Celina G. Val" <celinval@amazon.com>
Date: Mon, 23 Oct 2023 12:02:17 -0700
Subject: [PATCH 31/38] Add `internal()` method counterpart to `stable()`

Note: We do not expect to provide internalizing methods for all
StableMIR constructs. They exist only to help migrating efforts to allow
users to mix StableMIR and internal constructs.
---
 compiler/rustc_smir/src/rustc_internal/mod.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 7bec946788b31..58cdcd49087e5 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -26,6 +26,10 @@ pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T {
     with_tables(|tables| item.stable(tables))
 }
 
+pub unsafe fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T {
+    with_tables(|tables| item.internal(tables))
+}
+
 impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
     type Output = DefId;
 
@@ -285,7 +289,7 @@ impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V
 /// Trait used to translate a stable construct to its rustc counterpart.
 ///
 /// This is basically a mirror of [crate::rustc_smir::Stable].
-pub(crate) trait RustcInternal<'tcx> {
+pub trait RustcInternal<'tcx> {
     type T;
     fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T;
 }

From 421631a3a1fb4fe5f12d3212c070f95ea501471e Mon Sep 17 00:00:00 2001
From: "Celina G. Val" <celinval@amazon.com>
Date: Mon, 23 Oct 2023 14:21:24 -0700
Subject: [PATCH 32/38] Remove unsafe and `Rc`

---
 compiler/rustc_smir/src/rustc_internal/mod.rs | 22 ++++++++-----------
 compiler/rustc_smir/src/rustc_smir/mod.rs     |  2 +-
 compiler/stable_mir/src/lib.rs                | 13 +++++------
 3 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 58cdcd49087e5..efbf9eba04c34 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -18,15 +18,14 @@ use std::cell::RefCell;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::ops::Index;
-use std::rc::Rc;
 
 mod internal;
 
-pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T {
+pub fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T {
     with_tables(|tables| item.stable(tables))
 }
 
-pub unsafe fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T {
+pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T {
     with_tables(|tables| item.internal(tables))
 }
 
@@ -141,15 +140,12 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
 // datastructures and stable MIR datastructures
 scoped_thread_local! (static TLV: Cell<*const ()>);
 
-pub(crate) fn init<'tcx>(tables: TablesWrapper<'tcx>, f: impl FnOnce()) {
+pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) {
     assert!(!TLV.is_set());
-    fn g<'a, 'tcx>(context: &'a TablesWrapper<'tcx>, f: impl FnOnce()) {
-        let ptr: *const () = &context as *const &_ as _;
-        TLV.set(&Cell::new(ptr), || {
-            f();
-        });
-    }
-    g(&tables, f);
+    let ptr: *const () = &tables as *const &_ as _;
+    TLV.set(&Cell::new(ptr), || {
+        f();
+    });
 }
 
 /// Loads the current context and calls a function with it.
@@ -166,7 +162,7 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R
 }
 
 pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
-    let tables = Rc::new(RefCell::new(Tables {
+    let tables = TablesWrapper(RefCell::new(Tables {
         tcx,
         def_ids: IndexMap::default(),
         alloc_ids: IndexMap::default(),
@@ -174,7 +170,7 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
         types: vec![],
         instances: IndexMap::default(),
     }));
-    stable_mir::run(TablesWrapper(Rc::clone(&tables)), || init(TablesWrapper(tables), f));
+    stable_mir::run(&tables, || init(&tables, f));
 }
 
 #[macro_export]
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 19ad9898db168..d5a5f800a40c0 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -279,7 +279,7 @@ impl<S, R: PartialEq> PartialEq<R> for MaybeStable<S, R> {
     }
 }
 
-pub(crate) struct TablesWrapper<'tcx>(pub(crate) std::rc::Rc<RefCell<Tables<'tcx>>>);
+pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell<Tables<'tcx>>);
 
 pub struct Tables<'tcx> {
     pub(crate) tcx: TyCtxt<'tcx>,
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index 512c3fc629645..8cacbdbda487f 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -243,15 +243,12 @@ pub trait Context {
 // datastructures and stable MIR datastructures
 scoped_thread_local! (static TLV: Cell<*const ()>);
 
-pub fn run(context: impl Context, f: impl FnOnce()) {
+pub fn run(context: &dyn Context, f: impl FnOnce()) {
     assert!(!TLV.is_set());
-    fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) {
-        let ptr: *const () = &context as *const &_ as _;
-        TLV.set(&Cell::new(ptr), || {
-            f();
-        });
-    }
-    g(&context, f);
+    let ptr: *const () = &context as *const &_ as _;
+    TLV.set(&Cell::new(ptr), || {
+        f();
+    });
 }
 
 /// Loads the current context and calls a function with it.

From cb618162b138be0e0472d0f5540e6fc0d5a11210 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui@loongson.cn>
Date: Thu, 19 Oct 2023 21:12:19 +0800
Subject: [PATCH 33/38] compiler: Add target features for LoongArch

---
 .../rustc_codegen_ssa/src/target_features.rs     | 16 ++++++++++++++++
 compiler/rustc_feature/src/unstable.rs           |  1 +
 compiler/rustc_span/src/symbol.rs                |  1 +
 3 files changed, 18 insertions(+)

diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index baf6b19d3f97e..13a3f432b0398 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -342,6 +342,19 @@ const CSKY_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("hard-float-abi", Some(sym::csky_target_feature)),
     // tidy-alphabetical-end
 ];
+
+const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
+    // tidy-alphabetical-start
+    ("d", Some(sym::loongarch_target_feature)),
+    ("f", Some(sym::loongarch_target_feature)),
+    ("lasx", Some(sym::loongarch_target_feature)),
+    ("lbt", Some(sym::loongarch_target_feature)),
+    ("lsx", Some(sym::loongarch_target_feature)),
+    ("lvz", Some(sym::loongarch_target_feature)),
+    ("ual", Some(sym::loongarch_target_feature)),
+    // tidy-alphabetical-end
+];
+
 /// When rustdoc is running, provide a list of all known features so that all their respective
 /// primitives may be documented.
 ///
@@ -358,6 +371,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol
         .chain(WASM_ALLOWED_FEATURES.iter())
         .chain(BPF_ALLOWED_FEATURES.iter())
         .chain(CSKY_ALLOWED_FEATURES)
+        .chain(LOONGARCH_ALLOWED_FEATURES)
         .cloned()
 }
 
@@ -373,6 +387,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
         "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
         "bpf" => BPF_ALLOWED_FEATURES,
         "csky" => CSKY_ALLOWED_FEATURES,
+        "loongarch64" => LOONGARCH_ALLOWED_FEATURES,
         _ => &[],
     }
 }
@@ -445,6 +460,7 @@ pub fn from_target_feature(
                 Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
                 Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
                 Some(sym::csky_target_feature) => rust_features.csky_target_feature,
+                Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature,
                 Some(name) => bug!("unknown target feature gate {}", name),
                 None => true,
             };
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 8185a8a3e437d..695de54eefa0a 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -288,6 +288,7 @@ declare_features! (
     (unstable, csky_target_feature, "1.73.0", Some(44839), None),
     (unstable, ermsb_target_feature, "1.49.0", Some(44839), None),
     (unstable, hexagon_target_feature, "1.27.0", Some(44839), None),
+    (unstable, loongarch_target_feature, "1.73.0", Some(44839), None),
     (unstable, mips_target_feature, "1.27.0", Some(44839), None),
     (unstable, powerpc_target_feature, "1.27.0", Some(44839), None),
     (unstable, riscv_target_feature, "1.45.0", Some(44839), None),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5b58cf8b6d629..50d969890419b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -957,6 +957,7 @@ symbols! {
         log_syntax,
         logf32,
         logf64,
+        loongarch_target_feature,
         loop_break_value,
         lt,
         macro_at_most_once_rep,

From 6cf9423770437bd6f7b4f8ab0fb81dc2ae722ac0 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui@loongson.cn>
Date: Thu, 19 Oct 2023 21:13:52 +0800
Subject: [PATCH 34/38] tests: Add features-gate for LoongArch

---
 tests/ui/target-feature/gate.rs     | 1 +
 tests/ui/target-feature/gate.stderr | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs
index 782444417a8fc..971a4654b4cec 100644
--- a/tests/ui/target-feature/gate.rs
+++ b/tests/ui/target-feature/gate.rs
@@ -18,6 +18,7 @@
 // gate-test-bpf_target_feature
 // gate-test-aarch64_ver_target_feature
 // gate-test-csky_target_feature
+// gate-test-loongarch_target_feature
 
 #[target_feature(enable = "avx512bw")]
 //~^ ERROR: currently unstable
diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr
index f56efb3bb831e..0ec7427c3c456 100644
--- a/tests/ui/target-feature/gate.stderr
+++ b/tests/ui/target-feature/gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable
-  --> $DIR/gate.rs:22:18
+  --> $DIR/gate.rs:23:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^

From 300d04dc70a28188bf34e4476eb85ecd96f6a99b Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui@loongson.cn>
Date: Tue, 24 Oct 2023 11:43:46 +0800
Subject: [PATCH 35/38] tests/ui/abi/compatibility: Set min-llvm-version to 17
 for LoongArch64

---
 tests/ui/abi/compatibility.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index 1f049b1785a62..0cdf229711ad0 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -30,6 +30,7 @@
 // revisions: loongarch64
 //[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
 //[loongarch64] needs-llvm-components: loongarch
+//[loongarch64] min-llvm-version: 17
 // revisions: wasm
 //[wasm] compile-flags: --target wasm32-unknown-unknown
 //[wasm] needs-llvm-components: webassembly

From ae86f59cc9dd7d4be3c47d9ecbc3b98ca1f514a8 Mon Sep 17 00:00:00 2001
From: "Celina G. Val" <celinval@amazon.com>
Date: Mon, 23 Oct 2023 21:35:30 -0700
Subject: [PATCH 36/38] Add test and remove double ref

---
 compiler/rustc_smir/src/rustc_internal/mod.rs |  6 +-
 .../ui-fulldeps/stable-mir/check_instance.rs  | 33 +++++-----
 tests/ui-fulldeps/stable-mir/smir_internal.rs | 64 +++++++++++++++++++
 3 files changed, 85 insertions(+), 18 deletions(-)
 create mode 100644 tests/ui-fulldeps/stable-mir/smir_internal.rs

diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index efbf9eba04c34..d3ea8cdc699a0 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -142,7 +142,7 @@ scoped_thread_local! (static TLV: Cell<*const ()>);
 
 pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) {
     assert!(!TLV.is_set());
-    let ptr: *const () = &tables as *const &_ as _;
+    let ptr = tables as *const _ as *const ();
     TLV.set(&Cell::new(ptr), || {
         f();
     });
@@ -155,8 +155,8 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R
     TLV.with(|tlv| {
         let ptr = tlv.get();
         assert!(!ptr.is_null());
-        let wrapper = unsafe { *(ptr as *const &TablesWrapper<'tcx>) };
-        let mut tables = wrapper.0.borrow_mut();
+        let wrapper = ptr as *const TablesWrapper<'tcx>;
+        let mut tables = unsafe { (*wrapper).0.borrow_mut() };
         f(&mut *tables)
     })
 }
diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs
index c6a9e08ed0260..ee82bc77aedae 100644
--- a/tests/ui-fulldeps/stable-mir/check_instance.rs
+++ b/tests/ui-fulldeps/stable-mir/check_instance.rs
@@ -1,5 +1,5 @@
 // run-pass
-// Test that users are able to use stable mir APIs to retrieve monomorphized instances
+//! Test that users are able to use stable mir APIs to retrieve monomorphized instances
 
 // ignore-stage1
 // ignore-cross-compile
@@ -14,15 +14,15 @@
 extern crate rustc_middle;
 #[macro_use]
 extern crate rustc_smir;
-extern crate stable_mir;
 extern crate rustc_driver;
 extern crate rustc_interface;
+extern crate stable_mir;
 
-use rustc_middle::ty::TyCtxt;
 use mir::{mono::Instance, TerminatorKind::*};
-use stable_mir::ty::{TyKind, RigidTy};
-use stable_mir::*;
+use rustc_middle::ty::TyCtxt;
 use rustc_smir::rustc_internal;
+use stable_mir::ty::{RigidTy, TyKind};
+use stable_mir::*;
 use std::io::Write;
 use std::ops::ControlFlow;
 
@@ -33,16 +33,16 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     let items = stable_mir::all_local_items();
 
     // Get all items and split generic vs monomorphic items.
-    let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| {
-        item.requires_monomorphization()
-    });
+    let (generic, mono): (Vec<_>, Vec<_>) =
+        items.into_iter().partition(|item| item.requires_monomorphization());
     assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant");
     assert_eq!(generic.len(), 2, "Expected 2 generic functions");
 
     // For all monomorphic items, get the correspondent instances.
-    let instances = mono.iter().filter_map(|item| {
-        mir::mono::Instance::try_from(*item).ok()
-    }).collect::<Vec<mir::mono::Instance>>();
+    let instances = mono
+        .iter()
+        .filter_map(|item| mir::mono::Instance::try_from(*item).ok())
+        .collect::<Vec<mir::mono::Instance>>();
     assert_eq!(instances.len(), mono.len());
 
     // For all generic items, try_from should fail.
@@ -58,19 +58,22 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
 fn test_body(body: mir::Body) {
     for term in body.blocks.iter().map(|bb| &bb.terminator) {
         match &term.kind {
-            Call{ func, .. } => {
+            Call { func, .. } => {
                 let TyKind::RigidTy(ty) = func.ty(&body.locals).kind() else { unreachable!() };
                 let RigidTy::FnDef(def, args) = ty else { unreachable!() };
                 let result = Instance::resolve(def, &args);
                 assert!(result.is_ok());
             }
-            Goto {..} | Assert{..} | SwitchInt{..} | Return | Drop {..} => { /* Do nothing */}
-            _ => { unreachable!("Unexpected terminator {term:?}") }
+            Goto { .. } | Assert { .. } | SwitchInt { .. } | Return | Drop { .. } => {
+                /* Do nothing */
+            }
+            _ => {
+                unreachable!("Unexpected terminator {term:?}")
+            }
         }
     }
 }
 
-
 /// 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
diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs
new file mode 100644
index 0000000000000..5ad05559cb4bb
--- /dev/null
+++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs
@@ -0,0 +1,64 @@
+// run-pass
+//! Test that users are able to use retrieve internal constructs from stable ones to help with
+//! the migration.
+
+// 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;
+
+use rustc_middle::ty::TyCtxt;
+use rustc_smir::rustc_internal;
+use std::io::Write;
+use std::ops::ControlFlow;
+
+const CRATE_NAME: &str = "input";
+
+fn test_translation(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
+    let main_fn = stable_mir::entry_fn().unwrap();
+    let body = main_fn.body();
+    let orig_ty = body.locals[0].ty;
+    let rustc_ty = rustc_internal::internal(&orig_ty);
+    assert!(rustc_ty.is_unit());
+    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!(args, tcx, test_translation(tcx)).unwrap();
+}
+
+fn generate_input(path: &str) -> std::io::Result<()> {
+    let mut file = std::fs::File::create(path)?;
+    write!(
+        file,
+        r#"
+    pub fn main() {{
+    }}
+    "#
+    )?;
+    Ok(())
+}

From 2b36547e9cf3ff0331953571201e9ce451782c44 Mon Sep 17 00:00:00 2001
From: Arpad Borsos <arpad.borsos@sentry.io>
Date: Mon, 21 Aug 2023 10:54:37 +0200
Subject: [PATCH 37/38] Introduce `-C instrument-coverage=branch` to gate
 branch coverage

This flag has to be used in combination with `-Zunstable-options`,
and is added in advance of adding branch coverage instrumentation.
---
 compiler/rustc_session/src/config.rs                      | 8 +++++++-
 compiler/rustc_session/src/options.rs                     | 5 ++++-
 compiler/rustc_session/src/session.rs                     | 4 ++++
 tests/ui/instrument-coverage/bad-value.bad.stderr         | 2 +-
 tests/ui/instrument-coverage/bad-value.blank.stderr       | 2 +-
 .../ui/instrument-coverage/except-unused-functions.stderr | 2 +-
 .../ui/instrument-coverage/except-unused-generics.stderr  | 2 +-
 7 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 462e7e85c65ac..84933588f17fe 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -169,6 +169,9 @@ pub enum MirSpanview {
 pub enum InstrumentCoverage {
     /// Default `-C instrument-coverage` or `-C instrument-coverage=statement`
     All,
+    /// Additionally, instrument branches and output branch coverage.
+    /// `-Zunstable-options -C instrument-coverage=branch`
+    Branch,
     /// `-Zunstable-options -C instrument-coverage=except-unused-generics`
     ExceptUnusedGenerics,
     /// `-Zunstable-options -C instrument-coverage=except-unused-functions`
@@ -2747,7 +2750,10 @@ pub fn build_session_options(
         }
         (Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {}
         (Some(_), _) if !unstable_opts.unstable_options => {
-            handler.early_error("`-C instrument-coverage=except-*` requires `-Z unstable-options`");
+            handler.early_error(
+                "`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \
+                require `-Z unstable-options`",
+            );
         }
         (None, None) => {}
         (None, ic) => {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index c090bcaf9d8e2..77aaf951f0db0 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -389,7 +389,7 @@ mod desc {
     pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
     pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
     pub const parse_instrument_coverage: &str =
-        "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`";
+        "`all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off`";
     pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
     pub const parse_unpretty: &str = "`string` or `string=string`";
     pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
@@ -931,6 +931,7 @@ mod parse {
 
         *slot = Some(match v {
             "all" => InstrumentCoverage::All,
+            "branch" => InstrumentCoverage::Branch,
             "except-unused-generics" | "except_unused_generics" => {
                 InstrumentCoverage::ExceptUnusedGenerics
             }
@@ -1356,6 +1357,7 @@ options! {
         reports (note, the compiler build config must include `profiler = true`); \
         implies `-C symbol-mangling-version=v0`. Optional values are:
         `=all` (implicit value)
+        `=branch`
         `=except-unused-generics`
         `=except-unused-functions`
         `=off` (default)"),
@@ -1597,6 +1599,7 @@ options! {
         reports (note, the compiler build config must include `profiler = true`); \
         implies `-C symbol-mangling-version=v0`. Optional values are:
         `=all` (implicit value)
+        `=branch`
         `=except-unused-generics`
         `=except-unused-functions`
         `=off` (default)"),
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 793074981654c..94fe38b72ad16 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -702,6 +702,10 @@ impl Session {
         self.opts.cg.instrument_coverage() != InstrumentCoverage::Off
     }
 
+    pub fn instrument_coverage_branch(&self) -> bool {
+        self.opts.cg.instrument_coverage() == InstrumentCoverage::Branch
+    }
+
     pub fn instrument_coverage_except_unused_generics(&self) -> bool {
         self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedGenerics
     }
diff --git a/tests/ui/instrument-coverage/bad-value.bad.stderr b/tests/ui/instrument-coverage/bad-value.bad.stderr
index 246c4f31a4bac..b867d169dae5b 100644
--- a/tests/ui/instrument-coverage/bad-value.bad.stderr
+++ b/tests/ui/instrument-coverage/bad-value.bad.stderr
@@ -1,2 +1,2 @@
-error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected
+error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected
 
diff --git a/tests/ui/instrument-coverage/bad-value.blank.stderr b/tests/ui/instrument-coverage/bad-value.blank.stderr
index b539c558d9ba7..e7122fb61cdfc 100644
--- a/tests/ui/instrument-coverage/bad-value.blank.stderr
+++ b/tests/ui/instrument-coverage/bad-value.blank.stderr
@@ -1,2 +1,2 @@
-error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected
+error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected
 
diff --git a/tests/ui/instrument-coverage/except-unused-functions.stderr b/tests/ui/instrument-coverage/except-unused-functions.stderr
index 82c1c630cbf23..acc633a2a6d2f 100644
--- a/tests/ui/instrument-coverage/except-unused-functions.stderr
+++ b/tests/ui/instrument-coverage/except-unused-functions.stderr
@@ -1,2 +1,2 @@
-error: `-C instrument-coverage=except-*` requires `-Z unstable-options`
+error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options`
 
diff --git a/tests/ui/instrument-coverage/except-unused-generics.stderr b/tests/ui/instrument-coverage/except-unused-generics.stderr
index 82c1c630cbf23..acc633a2a6d2f 100644
--- a/tests/ui/instrument-coverage/except-unused-generics.stderr
+++ b/tests/ui/instrument-coverage/except-unused-generics.stderr
@@ -1,2 +1,2 @@
-error: `-C instrument-coverage=except-*` requires `-Z unstable-options`
+error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options`
 

From 68f5536667ca2d60ac8275fe3bf5b6549f96d2f2 Mon Sep 17 00:00:00 2001
From: Obei Sideg <obei.sideg@gmail.com>
Date: Tue, 3 Oct 2023 20:17:40 +0300
Subject: [PATCH 38/38] Migrate diagnostics in
 `rustc_hir_analysis/src/coherence/orphan.rs`

---
 compiler/rustc_hir_analysis/messages.ftl      |  41 +++
 .../src/coherence/orphan.rs                   | 291 ++++++++----------
 compiler/rustc_hir_analysis/src/errors.rs     | 172 ++++++++++-
 3 files changed, 341 insertions(+), 163 deletions(-)

diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 6bf6650986a67..e8d9918be22d2 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -72,6 +72,12 @@ hir_analysis_copy_impl_on_type_with_dtor =
     the trait `Copy` cannot be implemented for this type; the type has a destructor
     .label = `Copy` not allowed on types with destructors
 
+hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}`
+    .label = can't implement cross-crate trait with a default impl for non-struct/enum type
+
+hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate
+    .label = can't implement cross-crate trait for type in another crate
+
 hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions
     .note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
     .coercions_note = currently, {$number} fields need coercions: {$coercions}
@@ -237,6 +243,28 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
 
 hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
 
+hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types
+
+hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait
+
+hir_analysis_only_current_traits_label = impl doesn't use only types from inside the current crate
+
+hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign
+
+hir_analysis_only_current_traits_note = define and implement a trait or new type instead
+
+hir_analysis_only_current_traits_opaque = type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate
+
+hir_analysis_only_current_traits_outside = only traits defined in the current crate can be implemented for types defined outside of the crate
+
+hir_analysis_only_current_traits_pointer = `{$pointer}` is not defined in the current crate because raw pointers are always foreign
+
+hir_analysis_only_current_traits_pointer_sugg = consider introducing a new wrapper type
+
+hir_analysis_only_current_traits_primitive = only traits defined in the current crate can be implemented for primitive types
+
+hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate
+
 hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
     .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
 
@@ -326,6 +354,9 @@ hir_analysis_trait_object_declared_with_no_traits =
     at least one trait is required for an object type
     .alias_span = this alias does not contain a trait
 
+hir_analysis_traits_with_defualt_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}`
+    .note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds
+
 hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
     .label = needs exactly one variant, but has {$number}
     .many_label = too many variants in `{$path}`
@@ -339,6 +370,16 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de
     .label = needs at most one field with non-trivial size or alignment, but has {$field_count}
     .labels = this field has non-zero size or requires alignment
 
+hir_analysis_ty_param_first_local = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`)
+    .label = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`)
+    .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
+    .case_note = in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
+
+hir_analysis_ty_param_some = type parameter `{$param_ty}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param_ty}>`)
+    .label = type parameter `{$param_ty}` must be used as the type parameter for some local type
+    .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
+    .only_note = only traits defined in the current crate can be implemented for a type parameter
+
 hir_analysis_type_of = {$type_of}
 
 hir_analysis_typeof_reserved_keyword_used =
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index faddb0c38298c..7eeb7837467fd 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -2,8 +2,7 @@
 //! crate or pertains to a type defined in this crate.
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{struct_span_err, DelayDm};
-use rustc_errors::{Diagnostic, ErrorGuaranteed};
+use rustc_errors::{DelayDm, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_middle::ty::util::CheckRegions;
 use rustc_middle::ty::GenericArgs;
@@ -17,6 +16,8 @@ use rustc_span::Span;
 use rustc_trait_selection::traits;
 use std::ops::ControlFlow;
 
+use crate::errors;
+
 #[instrument(skip(tcx), level = "debug")]
 pub(crate) fn orphan_check_impl(
     tcx: TyCtxt<'_>,
@@ -259,49 +260,30 @@ fn do_orphan_check_impl<'tcx>(
             match local_impl {
                 LocalImpl::Allow => {}
                 LocalImpl::Disallow { problematic_kind } => {
-                    let msg = format!(
-                        "traits with a default impl, like `{trait}`, \
-                                cannot be implemented for {problematic_kind} `{self_ty}`",
-                        trait = tcx.def_path_str(trait_def_id),
-                    );
-                    let label = format!(
-                        "a trait object implements `{trait}` if and only if `{trait}` \
-                                is one of the trait object's trait bounds",
-                        trait = tcx.def_path_str(trait_def_id),
-                    );
-                    let sp = tcx.def_span(def_id);
-                    let reported =
-                        struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit();
-                    return Err(reported);
+                    return Err(tcx.sess.emit_err(errors::TraitsWithDefaultImpl {
+                        span: tcx.def_span(def_id),
+                        traits: tcx.def_path_str(trait_def_id),
+                        problematic_kind,
+                        self_ty,
+                    }));
                 }
             }
         } else {
-            if let Some((msg, label)) = match nonlocal_impl {
-                NonlocalImpl::Allow => None,
-                NonlocalImpl::DisallowBecauseNonlocal => Some((
-                    format!(
-                        "cross-crate traits with a default impl, like `{}`, \
-                                can only be implemented for a struct/enum type \
-                                defined in the current crate",
-                        tcx.def_path_str(trait_def_id)
-                    ),
-                    "can't implement cross-crate trait for type in another crate",
-                )),
-                NonlocalImpl::DisallowOther => Some((
-                    format!(
-                        "cross-crate traits with a default impl, like `{}`, can \
-                                only be implemented for a struct/enum type, not `{}`",
-                        tcx.def_path_str(trait_def_id),
-                        self_ty
-                    ),
-                    "can't implement cross-crate trait with a default impl for \
-                            non-struct/enum type",
-                )),
-            } {
-                let sp = tcx.def_span(def_id);
-                let reported =
-                    struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
-                return Err(reported);
+            match nonlocal_impl {
+                NonlocalImpl::Allow => {}
+                NonlocalImpl::DisallowBecauseNonlocal => {
+                    return Err(tcx.sess.emit_err(errors::CrossCrateTraitsDefined {
+                        span: tcx.def_span(def_id),
+                        traits: tcx.def_path_str(trait_def_id),
+                    }));
+                }
+                NonlocalImpl::DisallowOther => {
+                    return Err(tcx.sess.emit_err(errors::CrossCrateTraits {
+                        span: tcx.def_span(def_id),
+                        traits: tcx.def_path_str(trait_def_id),
+                        self_ty,
+                    }));
+                }
             }
         }
     }
@@ -322,19 +304,18 @@ fn emit_orphan_check_error<'tcx>(
     let self_ty = trait_ref.self_ty();
     Err(match err {
         traits::OrphanCheckErr::NonLocalInputType(tys) => {
-            let msg = match self_ty.kind() {
-                ty::Adt(..) => "can be implemented for types defined outside of the crate",
-                _ if self_ty.is_primitive() => "can be implemented for primitive types",
-                _ => "can be implemented for arbitrary types",
-            };
-            let mut err = struct_span_err!(
-                tcx.sess,
-                sp,
-                E0117,
-                "only traits defined in the current crate {msg}"
-            );
-            err.span_label(sp, "impl doesn't use only types from inside the current crate");
+            let (mut opaque, mut foreign, mut name, mut pointer, mut ty_diag) =
+                (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new());
+            let mut sugg = None;
             for &(mut ty, is_target_ty) in &tys {
+                let span = if is_target_ty {
+                    // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
+                    self_ty_span
+                } else {
+                    // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
+                    trait_span
+                };
+
                 ty = tcx.erase_regions(ty);
                 ty = match ty.kind() {
                     // Remove the type arguments from the output, as they are not relevant.
@@ -345,50 +326,103 @@ fn emit_orphan_check_error<'tcx>(
                     ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()),
                     _ => ty,
                 };
-                let msg = |ty: &str, postfix: &str| {
-                    format!("{ty} is not defined in the current crate{postfix}")
-                };
 
-                let this = |name: &str| {
-                    if !trait_ref.def_id.is_local() && !is_target_ty {
-                        msg("this", " because this is a foreign trait")
+                fn push_to_foreign_or_name<'tcx>(
+                    is_foreign: bool,
+                    foreign: &mut Vec<errors::OnlyCurrentTraitsForeign>,
+                    name: &mut Vec<errors::OnlyCurrentTraitsName<'tcx>>,
+                    span: Span,
+                    sname: &'tcx str,
+                ) {
+                    if is_foreign {
+                        foreign.push(errors::OnlyCurrentTraitsForeign { span })
                     } else {
-                        msg("this", &format!(" because {name} are always foreign"))
+                        name.push(errors::OnlyCurrentTraitsName { span, name: sname });
+                    }
+                }
+
+                let is_foreign = !trait_ref.def_id.is_local() && !is_target_ty;
+
+                match &ty.kind() {
+                    ty::Slice(_) => {
+                        push_to_foreign_or_name(
+                            is_foreign,
+                            &mut foreign,
+                            &mut name,
+                            span,
+                            "slices",
+                        );
+                    }
+                    ty::Array(..) => {
+                        push_to_foreign_or_name(
+                            is_foreign,
+                            &mut foreign,
+                            &mut name,
+                            span,
+                            "arrays",
+                        );
+                    }
+                    ty::Tuple(..) => {
+                        push_to_foreign_or_name(
+                            is_foreign,
+                            &mut foreign,
+                            &mut name,
+                            span,
+                            "tuples",
+                        );
                     }
-                };
-                let msg = match &ty.kind() {
-                    ty::Slice(_) => this("slices"),
-                    ty::Array(..) => this("arrays"),
-                    ty::Tuple(..) => this("tuples"),
                     ty::Alias(ty::Opaque, ..) => {
-                        "type alias impl trait is treated as if it were foreign, \
-                        because its hidden type could be from a foreign crate"
-                            .to_string()
+                        opaque.push(errors::OnlyCurrentTraitsOpaque { span })
                     }
                     ty::RawPtr(ptr_ty) => {
-                        emit_newtype_suggestion_for_raw_ptr(
-                            full_impl_span,
-                            self_ty,
-                            self_ty_span,
-                            ptr_ty,
-                            &mut err,
-                        );
-
-                        msg(&format!("`{ty}`"), " because raw pointers are always foreign")
+                        if !self_ty.has_param() {
+                            let mut_key = ptr_ty.mutbl.prefix_str();
+                            sugg = Some(errors::OnlyCurrentTraitsPointerSugg {
+                                wrapper_span: self_ty_span,
+                                struct_span: full_impl_span.shrink_to_lo(),
+                                mut_key,
+                                ptr_ty: ptr_ty.ty,
+                            });
+                        }
+                        pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty });
                     }
-                    _ => msg(&format!("`{ty}`"), ""),
-                };
-
-                if is_target_ty {
-                    // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
-                    err.span_label(self_ty_span, msg);
-                } else {
-                    // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
-                    err.span_label(trait_span, msg);
+                    _ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }),
                 }
             }
-            err.note("define and implement a trait or new type instead");
-            err.emit()
+
+            let err_struct = match self_ty.kind() {
+                ty::Adt(..) => errors::OnlyCurrentTraits::Outside {
+                    span: sp,
+                    note: (),
+                    opaque,
+                    foreign,
+                    name,
+                    pointer,
+                    ty: ty_diag,
+                    sugg,
+                },
+                _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive {
+                    span: sp,
+                    note: (),
+                    opaque,
+                    foreign,
+                    name,
+                    pointer,
+                    ty: ty_diag,
+                    sugg,
+                },
+                _ => errors::OnlyCurrentTraits::Arbitrary {
+                    span: sp,
+                    note: (),
+                    opaque,
+                    foreign,
+                    name,
+                    pointer,
+                    ty: ty_diag,
+                    sugg,
+                },
+            };
+            tcx.sess.emit_err(err_struct)
         }
         traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => {
             let mut sp = sp;
@@ -399,85 +433,18 @@ fn emit_orphan_check_error<'tcx>(
             }
 
             match local_type {
-                Some(local_type) => struct_span_err!(
-                    tcx.sess,
-                    sp,
-                    E0210,
-                    "type parameter `{}` must be covered by another type \
-                    when it appears before the first local type (`{}`)",
-                    param_ty,
-                    local_type
-                )
-                .span_label(
-                    sp,
-                    format!(
-                        "type parameter `{param_ty}` must be covered by another type \
-                    when it appears before the first local type (`{local_type}`)"
-                    ),
-                )
-                .note(
-                    "implementing a foreign trait is only possible if at \
-                        least one of the types for which it is implemented is local, \
-                        and no uncovered type parameters appear before that first \
-                        local type",
-                )
-                .note(
-                    "in this case, 'before' refers to the following order: \
-                        `impl<..> ForeignTrait<T1, ..., Tn> for T0`, \
-                        where `T0` is the first and `Tn` is the last",
-                )
-                .emit(),
-                None => struct_span_err!(
-                    tcx.sess,
-                    sp,
-                    E0210,
-                    "type parameter `{}` must be used as the type parameter for some \
-                    local type (e.g., `MyStruct<{}>`)",
+                Some(local_type) => tcx.sess.emit_err(errors::TyParamFirstLocal {
+                    span: sp,
+                    note: (),
                     param_ty,
-                    param_ty
-                )
-                .span_label(
-                    sp,
-                    format!(
-                        "type parameter `{param_ty}` must be used as the type parameter for some \
-                    local type",
-                    ),
-                )
-                .note(
-                    "implementing a foreign trait is only possible if at \
-                        least one of the types for which it is implemented is local",
-                )
-                .note(
-                    "only traits defined in the current crate can be \
-                        implemented for a type parameter",
-                )
-                .emit(),
+                    local_type,
+                }),
+                None => tcx.sess.emit_err(errors::TyParamSome { span: sp, note: (), param_ty }),
             }
         }
     })
 }
 
-fn emit_newtype_suggestion_for_raw_ptr(
-    full_impl_span: Span,
-    self_ty: Ty<'_>,
-    self_ty_span: Span,
-    ptr_ty: &ty::TypeAndMut<'_>,
-    diag: &mut Diagnostic,
-) {
-    if !self_ty.has_param() {
-        let mut_key = ptr_ty.mutbl.prefix_str();
-        let msg_sugg = "consider introducing a new wrapper type".to_owned();
-        let sugg = vec![
-            (
-                full_impl_span.shrink_to_lo(),
-                format!("struct WrapperType(*{}{});\n\n", mut_key, ptr_ty.ty),
-            ),
-            (self_ty_span, "WrapperType".to_owned()),
-        ];
-        diag.multipart_suggestion(msg_sugg, sugg, rustc_errors::Applicability::MaybeIncorrect);
-    }
-}
-
 /// Lint impls of auto traits if they are likely to have
 /// unsound or surprising effects on auto impls.
 fn lint_auto_trait_impl<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 189564d4e3392..6a2db1d06276c 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -683,7 +683,6 @@ pub(crate) struct SIMDFFIHighlyExperimental {
 }
 
 #[derive(Diagnostic)]
-
 pub enum ImplNotMarkedDefault {
     #[diag(hir_analysis_impl_not_marked_default, code = "E0520")]
     #[note]
@@ -1159,3 +1158,174 @@ pub struct ImplForTyRequires {
     pub trait_name: String,
     pub ty: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_traits_with_defualt_impl, code = "E0321")]
+#[note]
+pub struct TraitsWithDefaultImpl<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub traits: String,
+    pub problematic_kind: &'a str,
+    pub self_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_cross_crate_traits, code = "E0321")]
+pub struct CrossCrateTraits<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub traits: String,
+    pub self_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_cross_crate_traits_defined, code = "E0321")]
+pub struct CrossCrateTraitsDefined {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub traits: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_ty_param_first_local, code = "E0210")]
+#[note]
+pub struct TyParamFirstLocal<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[note(hir_analysis_case_note)]
+    pub note: (),
+    pub param_ty: Ty<'a>,
+    pub local_type: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_ty_param_some, code = "E0210")]
+#[note]
+pub struct TyParamSome<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[note(hir_analysis_only_note)]
+    pub note: (),
+    pub param_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+pub enum OnlyCurrentTraits<'a> {
+    #[diag(hir_analysis_only_current_traits_outside, code = "E0117")]
+    Outside {
+        #[primary_span]
+        #[label(hir_analysis_only_current_traits_label)]
+        span: Span,
+        #[note(hir_analysis_only_current_traits_note)]
+        note: (),
+        #[subdiagnostic]
+        opaque: Vec<OnlyCurrentTraitsOpaque>,
+        #[subdiagnostic]
+        foreign: Vec<OnlyCurrentTraitsForeign>,
+        #[subdiagnostic]
+        name: Vec<OnlyCurrentTraitsName<'a>>,
+        #[subdiagnostic]
+        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
+        #[subdiagnostic]
+        ty: Vec<OnlyCurrentTraitsTy<'a>>,
+        #[subdiagnostic]
+        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
+    },
+    #[diag(hir_analysis_only_current_traits_primitive, code = "E0117")]
+    Primitive {
+        #[primary_span]
+        #[label(hir_analysis_only_current_traits_label)]
+        span: Span,
+        #[note(hir_analysis_only_current_traits_note)]
+        note: (),
+        #[subdiagnostic]
+        opaque: Vec<OnlyCurrentTraitsOpaque>,
+        #[subdiagnostic]
+        foreign: Vec<OnlyCurrentTraitsForeign>,
+        #[subdiagnostic]
+        name: Vec<OnlyCurrentTraitsName<'a>>,
+        #[subdiagnostic]
+        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
+        #[subdiagnostic]
+        ty: Vec<OnlyCurrentTraitsTy<'a>>,
+        #[subdiagnostic]
+        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
+    },
+    #[diag(hir_analysis_only_current_traits_arbitrary, code = "E0117")]
+    Arbitrary {
+        #[primary_span]
+        #[label(hir_analysis_only_current_traits_label)]
+        span: Span,
+        #[note(hir_analysis_only_current_traits_note)]
+        note: (),
+        #[subdiagnostic]
+        opaque: Vec<OnlyCurrentTraitsOpaque>,
+        #[subdiagnostic]
+        foreign: Vec<OnlyCurrentTraitsForeign>,
+        #[subdiagnostic]
+        name: Vec<OnlyCurrentTraitsName<'a>>,
+        #[subdiagnostic]
+        pointer: Vec<OnlyCurrentTraitsPointer<'a>>,
+        #[subdiagnostic]
+        ty: Vec<OnlyCurrentTraitsTy<'a>>,
+        #[subdiagnostic]
+        sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
+    },
+}
+
+#[derive(Subdiagnostic)]
+#[label(hir_analysis_only_current_traits_opaque)]
+pub struct OnlyCurrentTraitsOpaque {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[label(hir_analysis_only_current_traits_foreign)]
+pub struct OnlyCurrentTraitsForeign {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[label(hir_analysis_only_current_traits_name)]
+pub struct OnlyCurrentTraitsName<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: &'a str,
+}
+
+#[derive(Subdiagnostic)]
+#[label(hir_analysis_only_current_traits_pointer)]
+pub struct OnlyCurrentTraitsPointer<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub pointer: Ty<'a>,
+}
+
+#[derive(Subdiagnostic)]
+#[label(hir_analysis_only_current_traits_ty)]
+pub struct OnlyCurrentTraitsTy<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'a>,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    hir_analysis_only_current_traits_pointer_sugg,
+    applicability = "maybe-incorrect"
+)]
+pub struct OnlyCurrentTraitsPointerSugg<'a> {
+    #[suggestion_part(code = "WrapperType")]
+    pub wrapper_span: Span,
+    #[suggestion_part(code = "struct WrapperType(*{mut_key}{ptr_ty});\n\n")]
+    pub struct_span: Span,
+    pub mut_key: &'a str,
+    pub ptr_ty: Ty<'a>,
+}