From 59be3e856f218f55be0f73bcfed6265772437ec7 Mon Sep 17 00:00:00 2001
From: Chase Wilson <me@chasewilson.dev>
Date: Fri, 17 Jun 2022 11:39:59 -0500
Subject: [PATCH 01/14] Stabilized Option::unzip()

---
 library/core/src/option.rs | 11 +++++++----
 library/core/tests/lib.rs  |  1 -
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 28ea45ed235dc..1d6784af2a5cd 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1711,8 +1711,6 @@ impl<T, U> Option<(T, U)> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(unzip_option)]
-    ///
     /// let x = Some((1, "hi"));
     /// let y = None::<(u8, u32)>;
     ///
@@ -1720,8 +1718,13 @@ impl<T, U> Option<(T, U)> {
     /// assert_eq!(y.unzip(), (None, None));
     /// ```
     #[inline]
-    #[unstable(feature = "unzip_option", issue = "87800", reason = "recently added")]
-    pub const fn unzip(self) -> (Option<T>, Option<U>) {
+    #[stable(feature = "unzip_option", since = "1.63.0")]
+    #[rustc_const_unstable(feature = "const_option", issue = "67441")]
+    pub const fn unzip(self) -> (Option<T>, Option<U>)
+    where
+        T: ~const Destruct,
+        U: ~const Destruct,
+    {
         match self {
             Some((a, b)) => (Some(a), Some(b)),
             None => (None, None),
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 63c9602abe75c..30b9cb4dadc8a 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -91,7 +91,6 @@
 #![feature(strict_provenance)]
 #![feature(trusted_random_access)]
 #![feature(unsize)]
-#![feature(unzip_option)]
 #![feature(const_array_from_ref)]
 #![feature(const_slice_from_ref)]
 #![feature(waker_getters)]

From df8a62d4f380d656444a6fc4e704bcd3693f4b9a Mon Sep 17 00:00:00 2001
From: Chase Wilson <buckshot1233@gmail.com>
Date: Wed, 7 Sep 2022 10:27:42 -0500
Subject: [PATCH 02/14] Use `CURRENT_RUSTC_VERSION`

---
 library/core/src/option.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 1d6784af2a5cd..df5a20869a3fb 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1718,7 +1718,7 @@ impl<T, U> Option<(T, U)> {
     /// assert_eq!(y.unzip(), (None, None));
     /// ```
     #[inline]
-    #[stable(feature = "unzip_option", since = "1.63.0")]
+    #[stable(feature = "unzip_option", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_const_unstable(feature = "const_option", issue = "67441")]
     pub const fn unzip(self) -> (Option<T>, Option<U>)
     where

From 093b075d327d1c7c7e0730e46f1d5c2d4aa47f5a Mon Sep 17 00:00:00 2001
From: Martin Nordholts <enselic@gmail.com>
Date: Sun, 2 Oct 2022 17:31:43 +0200
Subject: [PATCH 03/14] rustc: Use `unix_sigpipe` instead of
 `rustc_driver::set_sigpipe_handler`

This is the first (known) step towards starting to use `unix_sigpipe` in
the wild. Eventually, `rustc_driver::set_sigpipe_handler` can be removed
and all clients can use `unix_sigpipe` instead.

For now we just start using `unix_sigpipe` in once place: `rustc`
itself.

It is easy to manually verify this change. If you remove
`#[unix_sigpipe = "sig_dfl"]` and run `./x.py build` you will get an ICE
when you do `./build/x86_64-unknown-linux-gnu/stage1/bin/rustc --help |
false`. Add back `#[unix_sigpipe = "sig_dfl"]` and the ICE disappears
again.
---
 compiler/rustc/src/main.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index 0de1a78191353..e21c9b6604440 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -1,3 +1,5 @@
+#![feature(unix_sigpipe)]
+
 // A note about jemalloc: rustc uses jemalloc when built for CI and
 // distribution. The obvious way to do this is with the `#[global_allocator]`
 // mechanism. However, for complicated reasons (see
@@ -23,6 +25,7 @@
 // libraries. So we must reference jemalloc symbols one way or another, because
 // this file is the only object code in the rustc executable.
 
+#[unix_sigpipe = "sig_dfl"]
 fn main() {
     // See the comment at the top of this file for an explanation of this.
     #[cfg(feature = "jemalloc-sys")]
@@ -58,6 +61,5 @@ fn main() {
         }
     }
 
-    rustc_driver::set_sigpipe_handler();
     rustc_driver::main()
 }

From 7280f3d28aa139cec0c75072a3e66294b7f99b59 Mon Sep 17 00:00:00 2001
From: Josh Stone <jistone@redhat.com>
Date: Fri, 21 Oct 2022 17:44:35 -0700
Subject: [PATCH 04/14] Truncate thread names on Linux and Apple targets

These targets have system limits on the thread names, 16 and 64 bytes
respectively, and `pthread_setname_np` returns an error if the name is
longer. However, we're not in a context that can propagate errors when
we call this, and we used to implicitly truncate on Linux with `prctl`,
so now we manually truncate these names ahead of time.
---
 library/std/src/sys/unix/thread.rs | 43 ++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 42ac6fcd8bf36..6a533854fad3d 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -132,8 +132,11 @@ impl Thread {
 
     #[cfg(target_os = "linux")]
     pub fn set_name(name: &CStr) {
+        const TASK_COMM_LEN: usize = 16;
+
         unsafe {
             // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
+            let name = truncate_cstr(name, TASK_COMM_LEN);
             libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
         }
     }
@@ -148,6 +151,7 @@ impl Thread {
     #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
     pub fn set_name(name: &CStr) {
         unsafe {
+            let name = truncate_cstr(name, libc::MAXTHREADNAMESIZE);
             libc::pthread_setname_np(name.as_ptr());
         }
     }
@@ -276,6 +280,20 @@ impl Drop for Thread {
     }
 }
 
+#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
+fn truncate_cstr(cstr: &CStr, max_with_nul: usize) -> crate::borrow::Cow<'_, CStr> {
+    use crate::{borrow::Cow, ffi::CString};
+
+    if cstr.to_bytes_with_nul().len() > max_with_nul {
+        let bytes = cstr.to_bytes()[..max_with_nul - 1].to_vec();
+        // SAFETY: the non-nul bytes came straight from a CStr.
+        // (CString will add the terminating nul.)
+        Cow::Owned(unsafe { CString::from_vec_unchecked(bytes) })
+    } else {
+        Cow::Borrowed(cstr)
+    }
+}
+
 pub fn available_parallelism() -> io::Result<NonZeroUsize> {
     cfg_if::cfg_if! {
         if #[cfg(any(
@@ -902,3 +920,28 @@ fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
 fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
     2048 // just a guess
 }
+
+#[test]
+#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
+fn test_named_thread_truncation() {
+    use crate::thread::{self, Builder};
+
+    let long_name = crate::iter::once("test_named_thread_truncation")
+        .chain(crate::iter::repeat(" yada").take(100))
+        .collect::<String>();
+
+    let result = Builder::new().name(long_name.clone()).spawn(move || {
+        // Rust remembers the full thread name itself.
+        assert_eq!(thread::current().name(), Some(long_name.as_str()));
+
+        // But the kernel is limited -- make sure we successfully set a truncation.
+        let mut buf = vec![0u8; long_name.len() + 1];
+        unsafe {
+            libc::pthread_getname_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len());
+        }
+        let cstr = CStr::from_bytes_until_nul(&buf).unwrap();
+        assert!(cstr.to_bytes().len() > 0);
+        assert!(long_name.as_bytes().starts_with(cstr.to_bytes()));
+    });
+    result.unwrap().join().unwrap();
+}

From 12e45846ebbc32bd6a56f2de2658d3d9ad459032 Mon Sep 17 00:00:00 2001
From: Josh Stone <jistone@redhat.com>
Date: Fri, 21 Oct 2022 18:13:22 -0700
Subject: [PATCH 05/14] Move truncation next to other thread tests for tidy

---
 library/std/src/sys/unix/thread.rs | 25 -------------------------
 library/std/src/thread/tests.rs    | 25 +++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 6a533854fad3d..69cd2b500a1f0 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -920,28 +920,3 @@ fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
 fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
     2048 // just a guess
 }
-
-#[test]
-#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
-fn test_named_thread_truncation() {
-    use crate::thread::{self, Builder};
-
-    let long_name = crate::iter::once("test_named_thread_truncation")
-        .chain(crate::iter::repeat(" yada").take(100))
-        .collect::<String>();
-
-    let result = Builder::new().name(long_name.clone()).spawn(move || {
-        // Rust remembers the full thread name itself.
-        assert_eq!(thread::current().name(), Some(long_name.as_str()));
-
-        // But the kernel is limited -- make sure we successfully set a truncation.
-        let mut buf = vec![0u8; long_name.len() + 1];
-        unsafe {
-            libc::pthread_getname_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len());
-        }
-        let cstr = CStr::from_bytes_until_nul(&buf).unwrap();
-        assert!(cstr.to_bytes().len() > 0);
-        assert!(long_name.as_bytes().starts_with(cstr.to_bytes()));
-    });
-    result.unwrap().join().unwrap();
-}
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index dfb8765ab4eed..71eb41cd564db 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -37,6 +37,31 @@ fn test_named_thread() {
         .unwrap();
 }
 
+#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[test]
+fn test_named_thread_truncation() {
+    use crate::ffi::CStr;
+
+    let long_name = crate::iter::once("test_named_thread_truncation")
+        .chain(crate::iter::repeat(" yada").take(100))
+        .collect::<String>();
+
+    let result = Builder::new().name(long_name.clone()).spawn(move || {
+        // Rust remembers the full thread name itself.
+        assert_eq!(thread::current().name(), Some(long_name.as_str()));
+
+        // But the system is limited -- make sure we successfully set a truncation.
+        let mut buf = vec![0u8; long_name.len() + 1];
+        unsafe {
+            libc::pthread_getname_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len());
+        }
+        let cstr = CStr::from_bytes_until_nul(&buf).unwrap();
+        assert!(cstr.to_bytes().len() > 0);
+        assert!(long_name.as_bytes().starts_with(cstr.to_bytes()));
+    });
+    result.unwrap().join().unwrap();
+}
+
 #[test]
 #[should_panic]
 fn test_invalid_named_thread() {

From 8f8f74d9a1ba6bf8d8fcd6e5bafb9ee3ad2898db Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sat, 22 Oct 2022 21:38:05 +0000
Subject: [PATCH 06/14] Name impl trait in region bound suggestion

---
 .../nice_region_error/static_impl_trait.rs    | 21 +++++++++----------
 .../ret-impl-trait-one.stderr                 |  2 +-
 .../ui/impl-trait/hidden-lifetimes.stderr     |  4 ++--
 .../ordinary-bounds-unrelated.stderr          |  2 +-
 .../ordinary-bounds-unsuited.stderr           |  2 +-
 .../must_outlive_least_region_or_bound.stderr | 14 ++++++-------
 .../impl-trait/region-escape-via-bound.stderr |  2 +-
 .../static-return-lifetime-infered.stderr     |  8 +++----
 .../ty-outlives/impl-trait-captures.stderr    |  2 +-
 ...types_pin_lifetime_impl_trait-async.stderr |  2 +-
 ..._self_types_pin_lifetime_impl_trait.stderr |  2 +-
 .../missing-lifetimes-in-signature.stderr     |  2 +-
 .../trait-object-nested-in-impl-trait.stderr  |  4 ++--
 13 files changed, 33 insertions(+), 34 deletions(-)

diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 6bb736687d6e5..a74c172fa0c13 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -286,8 +286,8 @@ pub fn suggest_new_region_bound(
 ) {
     debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
     // FIXME: account for the need of parens in `&(dyn Trait + '_)`
-    let consider = "consider changing the";
-    let declare = "to declare that the";
+    let consider = "consider changing";
+    let declare = "to declare that";
     let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name);
     let explicit_static =
         arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg));
@@ -305,6 +305,10 @@ pub fn suggest_new_region_bound(
                     return;
                 };
 
+                // Get the identity type for this RPIT
+                let did = item_id.def_id.to_def_id();
+                let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did));
+
                 if let Some(span) = opaque
                     .bounds
                     .iter()
@@ -321,7 +325,7 @@ pub fn suggest_new_region_bound(
                     if let Some(explicit_static) = &explicit_static {
                         err.span_suggestion_verbose(
                             span,
-                            &format!("{} `impl Trait`'s {}", consider, explicit_static),
+                            &format!("{consider} `{ty}`'s {explicit_static}"),
                             &lifetime_name,
                             Applicability::MaybeIncorrect,
                         );
@@ -351,12 +355,7 @@ pub fn suggest_new_region_bound(
                 } else {
                     err.span_suggestion_verbose(
                         fn_return.span.shrink_to_hi(),
-                        &format!(
-                            "{declare} `impl Trait` {captures}, {explicit}",
-                            declare = declare,
-                            captures = captures,
-                            explicit = explicit,
-                        ),
+                        &format!("{declare} `{ty}` {captures}, {explicit}",),
                         &plus_lt,
                         Applicability::MaybeIncorrect,
                     );
@@ -367,7 +366,7 @@ pub fn suggest_new_region_bound(
                     err.span_suggestion_verbose(
                         fn_return.span.shrink_to_hi(),
                         &format!(
-                            "{declare} trait object {captures}, {explicit}",
+                            "{declare} the trait object {captures}, {explicit}",
                             declare = declare,
                             captures = captures,
                             explicit = explicit,
@@ -384,7 +383,7 @@ pub fn suggest_new_region_bound(
                     if let Some(explicit_static) = &explicit_static {
                         err.span_suggestion_verbose(
                             lt.span,
-                            &format!("{} trait object's {}", consider, explicit_static),
+                            &format!("{} the trait object's {}", consider, explicit_static),
                             &lifetime_name,
                             Applicability::MaybeIncorrect,
                         );
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
index 3128b4df4e2d1..ae4d0d5853ca6 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
@@ -25,7 +25,7 @@ LL | |     (a, b)
 LL | | }
    | |_^
    |
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound
    |
 LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
    |                                                                                ++++
diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr
index efc228de58be5..93896ace70bcf 100644
--- a/src/test/ui/impl-trait/hidden-lifetimes.stderr
+++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr
@@ -6,7 +6,7 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
 LL |     x
    |     ^
    |
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Swap` captures `'b`, you can add an explicit `'b` lifetime bound
    |
 LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
    |                                                                     ++++
@@ -19,7 +19,7 @@ LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl S
 LL |     x
    |     ^
    |
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Swap` captures `'b`, you can add an explicit `'b` lifetime bound
    |
 LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a + 'b {
    |                                                                                     ++++
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
index cb1dc0b7d50ae..ec49a61795a0c 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> im
 LL |     if condition() { a } else { b }
    |                                 ^
    |
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound
    |
 LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
    |                                                                                             ++++
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
index 4388e6601a6cf..c36f9bc6957c6 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a,
 LL |     if condition() { a } else { b }
    |                                 ^
    |
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound
    |
 LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
    |                                                                                 ++++
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 16767abd72241..a43669f57c06d 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x }
    |              |
    |              hidden type `&i32` captures the anonymous lifetime defined here
    |
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound
    |
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ++++
@@ -19,7 +19,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |             |
    |             hidden type `&'a i32` captures the lifetime `'a` as defined here
    |
-help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
+help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                          ++++
@@ -32,7 +32,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |               |
    |               let's call the lifetime of this reference `'1`
    |
-help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+help: consider changing `impl Copy`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
    |                                    ~~
@@ -47,7 +47,7 @@ error: lifetime may not live long enough
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    |              -- lifetime `'a` defined here            ^ returning this value requires that `'a` must outlive `'static`
    |
-help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+help: consider changing `impl Copy`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                             ~~
@@ -76,7 +76,7 @@ help: to declare that the trait object captures data from argument `x`, you can
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug + '_>, impl Debug) { (Box::new(x), x) }
    |                                       ++++
-help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Debug` captures data from argument `x`, you can add an explicit `'_` lifetime bound
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
    |                                                    ++++
@@ -87,7 +87,7 @@ error: lifetime may not live long enough
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |               -- lifetime `'a` defined here                         ^ returning this value requires that `'a` must outlive `'static`
    |
-help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+help: consider changing `impl LifetimeTrait<'a>`'s explicit `'static` bound to the lifetime of argument `x`
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
    |                                                           ~~
@@ -104,7 +104,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
 LL |     move |_| println!("{}", y)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Fn(&'a u32)` captures `'b`, you can add an explicit `'b` lifetime bound
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b {
    |                                                                              ++++
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr
index fdb2fe022b4d2..44a790cb1a43a 100644
--- a/src/test/ui/impl-trait/region-escape-via-bound.stderr
+++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr
@@ -7,7 +7,7 @@ LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
 LL |     x
    |     ^
    |
-help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound
+help: to declare that `impl Trait<'y>` captures `'x`, you can add an explicit `'x` lifetime bound
    |
 LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x
    |                                                    ++++
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
index b868152315503..b365bd8845480 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -6,7 +6,7 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Iterator<Item = u32>` captures `'_`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ++++
@@ -19,7 +19,7 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Iterator<Item = u32>` captures `'_`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ++++
@@ -32,7 +32,7 @@ LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
+help: to declare that `impl Iterator<Item = u32>` captures `'a`, you can add an explicit `'a` lifetime bound
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                                             ++++
@@ -45,7 +45,7 @@ LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
+help: to declare that `impl Iterator<Item = u32>` captures `'a`, you can add an explicit `'a` lifetime bound
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                                             ++++
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
index 6a8a1ad1caadd..737cb35841cf5 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
+++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
@@ -6,7 +6,7 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
 LL |     x
    |     ^
    |
-help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
+help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
    |
 LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
    |                                      ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index 7e7d60d0ff90a..eb3d3e4a67a98 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -6,7 +6,7 @@ LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
    |                          |
    |                          hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
    |
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
    |                                                ++++
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 30d2250c0c81d..2c0b2a0d91938 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -6,7 +6,7 @@ LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
    |                    |
    |                    hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
    |
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
    |                                          ++++
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index 171f4b333db4e..fa758bf05df5a 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -18,7 +18,7 @@ LL | |         *dest = g.get();
 LL | |     }
    | |_____^
    |
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl FnOnce()` captures `'_`, you can add an explicit `'_` lifetime bound
    |
 LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |                                                   ++++
diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
index f49876bcd3f14..c77ef79e7ed18 100644
--- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
+++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
@@ -10,7 +10,7 @@ LL | |             remaining: self.0.iter(),
 LL | |         }
    | |_________^ returning this value requires that `'1` must outlive `'static`
    |
-help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
    |                                                          ++++
@@ -65,7 +65,7 @@ LL | |             remaining: self.0.iter(),
 LL | |         }
    | |_________^ returning this value requires that `'a` must outlive `'static`
    |
-help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound
+help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'a` lifetime bound
    |
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
    |                                                                 ++++

From 4bd98443ed368a781812545915cf758e2091128d Mon Sep 17 00:00:00 2001
From: ouz-a <oguz.agcayazi@gmail.com>
Date: Sun, 16 Oct 2022 21:30:32 +0300
Subject: [PATCH 07/14] remove misc_cast and validate types

---
 .../rustc_const_eval/src/interpret/cast.rs    | 63 +++++++++++++------
 .../src/transform/validate.rs                 | 25 ++++++--
 src/tools/miri/src/shims/intrinsics/simd.rs   |  6 +-
 3 files changed, 66 insertions(+), 28 deletions(-)

diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 764224fd0072e..f980e606b932d 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -42,10 +42,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?;
                 self.write_immediate(res, dest)?;
             }
-            // FIXME: We shouldn't use `misc_cast` for these but handle them separately.
-            IntToInt | FloatToInt | FloatToFloat | IntToFloat | FnPtrToPtr | PtrToPtr => {
+
+            IntToInt | IntToFloat => {
                 let src = self.read_immediate(src)?;
-                let res = self.misc_cast(&src, cast_ty)?;
+                let res = self.int_to_int_or_float(&src, cast_ty)?;
+                self.write_immediate(res, dest)?;
+            }
+
+            FloatToFloat | FloatToInt => {
+                let src = self.read_immediate(src)?;
+                let res = self.float_to_float_or_int(&src, cast_ty)?;
+                self.write_immediate(res, dest)?;
+            }
+
+            FnPtrToPtr | PtrToPtr => {
+                let src = self.read_immediate(&src)?;
+                let res = self.ptr_to_ptr(&src, cast_ty)?;
                 self.write_immediate(res, dest)?;
             }
 
@@ -126,13 +138,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
-    pub fn misc_cast(
+    pub fn int_to_int_or_float(
+        &mut self,
+        src: &ImmTy<'tcx, M::Provenance>,
+        cast_ty: Ty<'tcx>,
+    ) -> InterpResult<'tcx, Immediate<M::Provenance>> {
+        if (src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool())
+            && (cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char())
+        {
+            let scalar = src.to_scalar();
+            Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
+        } else {
+            bug!("Unexpected cast from type {:?}", src.layout.ty)
+        }
+    }
+
+    pub fn float_to_float_or_int(
         &mut self,
         src: &ImmTy<'tcx, M::Provenance>,
         cast_ty: Ty<'tcx>,
     ) -> InterpResult<'tcx, Immediate<M::Provenance>> {
         use rustc_type_ir::sty::TyKind::*;
-        trace!("Casting {:?}: {:?} to {:?}", *src, src.layout.ty, cast_ty);
 
         match src.layout.ty.kind() {
             // Floating point
@@ -142,19 +168,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Float(FloatTy::F64) => {
                 return Ok(self.cast_from_float(src.to_scalar().to_f64()?, cast_ty).into());
             }
-            // The rest is integer/pointer-"like", including fn ptr casts
-            _ => assert!(
-                src.layout.ty.is_bool()
-                    || src.layout.ty.is_char()
-                    || src.layout.ty.is_integral()
-                    || src.layout.ty.is_any_ptr(),
-                "Unexpected cast from type {:?}",
-                src.layout.ty
-            ),
+            _ => {
+                bug!("Can't cast 'Float' type into {:?}", cast_ty);
+            }
         }
+    }
 
-        // # First handle non-scalar source values.
-
+    /// Handles 'FnPtrToPtr' and 'PtrToPtr' casts.
+    pub fn ptr_to_ptr(
+        &mut self,
+        src: &ImmTy<'tcx, M::Provenance>,
+        cast_ty: Ty<'tcx>,
+    ) -> InterpResult<'tcx, Immediate<M::Provenance>> {
         // Handle casting any ptr to raw ptr (might be a fat ptr).
         if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() {
             let dest_layout = self.layout_of(cast_ty)?;
@@ -178,11 +203,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
                 };
             }
+        } else {
+            bug!("Can't cast 'Ptr' or 'FnPtr' into {:?}", cast_ty);
         }
-
-        // # The remaining source values are scalar and "int-like".
-        let scalar = src.to_scalar();
-        Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
     }
 
     pub fn pointer_expose_address_cast(
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 8abf767f89f88..40946344a35d1 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -556,21 +556,36 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 check_kinds!(a, "Cannot shallow init type {:?}", ty::RawPtr(..));
             }
             Rvalue::Cast(kind, operand, target_type) => {
+                let op_ty = operand.ty(self.body, self.tcx);
                 match kind {
                     CastKind::DynStar => {
                         // FIXME(dyn-star): make sure nothing needs to be done here.
                     }
-                    // Nothing to check here
+                    // FIXME: Add Checks for these
                     CastKind::PointerFromExposedAddress
                     | CastKind::PointerExposeAddress
                     | CastKind::Pointer(_) => {}
-                    _ => {
-                        let op_ty = operand.ty(self.body, self.tcx);
-                        if op_ty.is_enum() {
+                    CastKind::IntToInt | CastKind::IntToFloat => {
+                        let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
+                        let target_valid = target_type.is_numeric() || target_type.is_char();
+                        if !input_valid || !target_valid {
+                            self.fail(
+                                location,
+                                format!("Wrong cast kind {kind:?} for the type {op_ty}",),
+                            );
+                        }
+                    }
+                    CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
+                        if !(op_ty.is_any_ptr() && target_type.is_unsafe_ptr()) {
+                            self.fail(location, "Can't cast {op_ty} into 'Ptr'");
+                        }
+                    }
+                    CastKind::FloatToFloat | CastKind::FloatToInt => {
+                        if !op_ty.is_floating_point() || !target_type.is_numeric() {
                             self.fail(
                                 location,
                                 format!(
-                                    "enum -> int casts should go through `Rvalue::Discriminant`: {operand:?}:{op_ty} as {target_type}",
+                                    "Trying to cast non 'Float' as {kind:?} into {target_type:?}"
                                 ),
                             );
                         }
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index 163d185f66f3a..c1b949b1f7993 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -437,13 +437,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
                         // Int-to-(int|float): always safe
                         (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) =>
-                            this.misc_cast(&op, dest.layout.ty)?,
+                            this.int_to_int_or_float(&op, dest.layout.ty)?,
                         // Float-to-float: always safe
                         (ty::Float(_), ty::Float(_)) =>
-                            this.misc_cast(&op, dest.layout.ty)?,
+                            this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in safe mode
                         (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
-                            this.misc_cast(&op, dest.layout.ty)?,
+                            this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in unchecked mode
                         (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if !safe_cast =>
                             this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(),

From 15cfeb33b08c91090d52685651aa9762b8f3c43f Mon Sep 17 00:00:00 2001
From: Josh Stone <jistone@redhat.com>
Date: Sun, 23 Oct 2022 11:53:39 -0700
Subject: [PATCH 08/14] Only test pthread_getname_np on linux-gnu

---
 library/std/src/thread/tests.rs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 71eb41cd564db..6c9ce6fa0ddbd 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -37,7 +37,13 @@ fn test_named_thread() {
         .unwrap();
 }
 
-#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(
+    // Note: musl didn't add pthread_getname_np until 1.2.3
+    all(target_os = "linux", target_env = "gnu"),
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "watchos"
+))]
 #[test]
 fn test_named_thread_truncation() {
     use crate::ffi::CStr;

From e521a8d46b4437f94ba1bb85826bb7d00ba13436 Mon Sep 17 00:00:00 2001
From: Gary Guo <gary@garyguo.net>
Date: Wed, 5 Oct 2022 19:59:45 +0100
Subject: [PATCH 09/14] Prevent foreign Rust exceptions from being caught

---
 library/panic_unwind/src/gcc.rs | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index 261404e8795fc..777ae41fab124 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -38,12 +38,23 @@
 
 use alloc::boxed::Box;
 use core::any::Any;
+use core::ptr;
 
 use unwind as uw;
 
+// In case where multiple copies of std is compiled into a single binary,
+// we use address of this static variable to distinguish an exception raised by
+// this copy and some other copy (which needs to be treated as foreign exception).
+static CANARY: u8 = 0;
+
+// NOTE(nbdd0121)
+// Once `c_unwind` feature is stabilized, there will be ABI stability requirement
+// on this struct. The first two field must be `_Unwind_Exception` and `canary`,
+// as it may be accessed by a different version of the std with a different compiler.
 #[repr(C)]
 struct Exception {
     _uwe: uw::_Unwind_Exception,
+    canary: *const u8,
     cause: Box<dyn Any + Send>,
 }
 
@@ -54,6 +65,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
             exception_cleanup,
             private: [0; uw::unwinder_private_data_size],
         },
+        canary: &CANARY,
         cause: data,
     });
     let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
@@ -75,10 +87,22 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     if (*exception).exception_class != rust_exception_class() {
         uw::_Unwind_DeleteException(exception);
         super::__rust_foreign_exception();
-    } else {
-        let exception = Box::from_raw(exception as *mut Exception);
-        exception.cause
     }
+
+    let exception = exception.cast::<Exception>();
+    // Just access the canary field, avoid accessing the entire `Exception` as
+    // it can be a foreign Rust exception.
+    let canary = ptr::addr_of!((*exception).canary).read();
+    if !ptr::eq(canary, &CANARY) {
+        // A foreign Rust exception, treat it slightly differently from other
+        // foreign exceptions, because call into `_Unwind_DeleteException` will
+        // call into `__rust_drop_panic` which produces a confusing
+        // "Rust panic must be rethrown" message.
+        super::__rust_foreign_exception();
+    }
+
+    let exception = Box::from_raw(exception as *mut Exception);
+    exception.cause
 }
 
 // Rust's exception class identifier.  This is used by personality routines to

From 86c65d2c1ce5aba2c1c74298c3e42696cff1d41a Mon Sep 17 00:00:00 2001
From: Gary Guo <gary@garyguo.net>
Date: Wed, 5 Oct 2022 22:40:07 +0100
Subject: [PATCH 10/14] Implement Rust foreign exception protection for EMCC
 and SEH

---
 library/panic_unwind/src/emcc.rs | 37 +++++++++++++++++++++++---------
 library/panic_unwind/src/seh.rs  | 20 ++++++++++++-----
 2 files changed, 42 insertions(+), 15 deletions(-)

diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs
index 7c233c7c3a1cb..57e817ce6ad54 100644
--- a/library/panic_unwind/src/emcc.rs
+++ b/library/panic_unwind/src/emcc.rs
@@ -47,7 +47,12 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo {
     name: b"rust_panic\0".as_ptr(),
 };
 
+// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization.
+#[repr(C)]
 struct Exception {
+    // See `gcc.rs` on why this is present. We already have a static here so just use it.
+    canary: *const TypeInfo,
+
     // This is necessary because C++ code can capture our exception with
     // std::exception_ptr and rethrow it multiple times, possibly even in
     // another thread.
@@ -70,16 +75,21 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     let catch_data = &*(ptr as *mut CatchData);
 
     let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception;
-    let out = if catch_data.is_rust_panic {
-        let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst);
-        if was_caught {
-            // Since cleanup() isn't allowed to panic, we just abort instead.
-            intrinsics::abort();
-        }
-        (*adjusted_ptr).data.take().unwrap()
-    } else {
+    if !catch_data.is_rust_panic {
         super::__rust_foreign_exception();
-    };
+    }
+
+    let canary = ptr::addr_of!((*adjusted_ptr).canary).read();
+    if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) {
+        super::__rust_foreign_exception();
+    }
+
+    let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst);
+    if was_caught {
+        // Since cleanup() isn't allowed to panic, we just abort instead.
+        intrinsics::abort();
+    }
+    let out = (*adjusted_ptr).data.take().unwrap();
     __cxa_end_catch();
     out
 }
@@ -90,7 +100,14 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     if exception.is_null() {
         return uw::_URC_FATAL_PHASE1_ERROR as u32;
     }
-    ptr::write(exception, Exception { caught: AtomicBool::new(false), data: Some(data) });
+    ptr::write(
+        exception,
+        Exception {
+            canary: &EXCEPTION_TYPE_INFO,
+            caught: AtomicBool::new(false),
+            data: Some(data),
+        },
+    );
     __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup);
 }
 
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index 6b8d065686113..651115a8248ac 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -49,9 +49,15 @@
 use alloc::boxed::Box;
 use core::any::Any;
 use core::mem::{self, ManuallyDrop};
+use core::ptr;
 use libc::{c_int, c_uint, c_void};
 
+// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization.
+#[repr(C)]
 struct Exception {
+    // See `gcc.rs` on why this is present. We already have a static here so just use it.
+    canary: *const _TypeDescriptor,
+
     // This needs to be an Option because we catch the exception by reference
     // and its destructor is executed by the C++ runtime. When we take the Box
     // out of the exception, we need to leave the exception in a valid state
@@ -235,7 +241,7 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
 macro_rules! define_cleanup {
     ($abi:tt $abi2:tt) => {
         unsafe extern $abi fn exception_cleanup(e: *mut Exception) {
-            if let Exception { data: Some(b) } = e.read() {
+            if let Exception { data: Some(b), .. } = e.read() {
                 drop(b);
                 super::__rust_drop_panic();
             }
@@ -265,7 +271,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     // The ManuallyDrop is needed here since we don't want Exception to be
     // dropped when unwinding. Instead it will be dropped by exception_cleanup
     // which is invoked by the C++ runtime.
-    let mut exception = ManuallyDrop::new(Exception { data: Some(data) });
+    let mut exception = ManuallyDrop::new(Exception { canary: &TYPE_DESCRIPTOR, data: Some(data) });
     let throw_ptr = &mut exception as *mut _ as *mut _;
 
     // This... may seems surprising, and justifiably so. On 32-bit MSVC the
@@ -321,8 +327,12 @@ pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> {
     // __rust_try. This happens when a non-Rust foreign exception is caught.
     if payload.is_null() {
         super::__rust_foreign_exception();
-    } else {
-        let exception = &mut *(payload as *mut Exception);
-        exception.data.take().unwrap()
     }
+    let exception = payload as *mut Exception;
+    let canary = ptr::addr_of!((*exception).canary).read();
+    if !ptr::eq(canary, &TYPE_DESCRIPTOR) {
+        // A foreign Rust exception.
+        super::__rust_foreign_exception();
+    }
+    (*exception).data.take().unwrap()
 }

From daf3063056d6c3dbd402d5b940f0b28aac0e1dff Mon Sep 17 00:00:00 2001
From: Gary Guo <gary@garyguo.net>
Date: Wed, 5 Oct 2022 23:58:35 +0100
Subject: [PATCH 11/14] Add test case for foreign Rust exceptions

---
 .../foreign-rust-exceptions/Makefile                 |  6 ++++++
 .../run-make-fulldeps/foreign-rust-exceptions/bar.rs |  7 +++++++
 .../run-make-fulldeps/foreign-rust-exceptions/foo.rs | 12 ++++++++++++
 3 files changed, 25 insertions(+)
 create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile
 create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs
 create mode 100644 src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs

diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile
new file mode 100644
index 0000000000000..24d9742aef0b0
--- /dev/null
+++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile
@@ -0,0 +1,6 @@
+include ../tools.mk
+
+all:
+	$(RUSTC) bar.rs --crate-type=cdylib
+	$(RUSTC) foo.rs
+	$(call RUN,foo) 2>&1 | $(CGREP) "Rust cannot catch foreign exceptions"
diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs
new file mode 100644
index 0000000000000..5f9efe323609b
--- /dev/null
+++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs
@@ -0,0 +1,7 @@
+#![crate_type = "cdylib"]
+#![feature(c_unwind)]
+
+#[no_mangle]
+extern "C-unwind" fn panic() {
+    panic!();
+}
diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs
new file mode 100644
index 0000000000000..d6a6d94a19497
--- /dev/null
+++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs
@@ -0,0 +1,12 @@
+#![feature(c_unwind)]
+
+#[link(name = "bar")]
+extern "C-unwind" {
+    fn panic();
+}
+
+fn main() {
+    let _ = std::panic::catch_unwind(|| {
+        unsafe { panic() };
+    });
+}

From 979d1a2c78a3fd45807eb28ccff5aeea37128e0f Mon Sep 17 00:00:00 2001
From: Gary Guo <gary@garyguo.net>
Date: Tue, 11 Oct 2022 18:02:07 +0100
Subject: [PATCH 12/14] Apply suggestion

Co-authored-by: Amanieu d'Antras <amanieu@gmail.com>
---
 library/panic_unwind/src/gcc.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index 777ae41fab124..0b7a873a691cc 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -42,7 +42,7 @@ use core::ptr;
 
 use unwind as uw;
 
-// In case where multiple copies of std is compiled into a single binary,
+// In case where multiple copies of std exist in a single process,
 // we use address of this static variable to distinguish an exception raised by
 // this copy and some other copy (which needs to be treated as foreign exception).
 static CANARY: u8 = 0;

From 4e6d60c837e178950b844bd1235c67ebbb6a5899 Mon Sep 17 00:00:00 2001
From: Gary Guo <gary@garyguo.net>
Date: Wed, 12 Oct 2022 12:24:59 +0100
Subject: [PATCH 13/14] Fix alloc size

---
 library/panic_unwind/src/emcc.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs
index 57e817ce6ad54..c6d42308596cb 100644
--- a/library/panic_unwind/src/emcc.rs
+++ b/library/panic_unwind/src/emcc.rs
@@ -95,8 +95,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
 }
 
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
-    let sz = mem::size_of_val(&data);
-    let exception = __cxa_allocate_exception(sz) as *mut Exception;
+    let exception = __cxa_allocate_exception(mem::size_of::<Exception>()) as *mut Exception;
     if exception.is_null() {
         return uw::_URC_FATAL_PHASE1_ERROR as u32;
     }

From c9cca33e85352c6ffd0c29a22c7302ca5f761ba3 Mon Sep 17 00:00:00 2001
From: Gary Guo <gary@garyguo.net>
Date: Sun, 23 Oct 2022 21:30:37 +0100
Subject: [PATCH 14/14] Fix windows compilation

---
 src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs
index d6a6d94a19497..266987c5b6d63 100644
--- a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs
+++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs
@@ -1,6 +1,7 @@
 #![feature(c_unwind)]
 
-#[link(name = "bar")]
+#[cfg_attr(not(windows), link(name = "bar"))]
+#[cfg_attr(windows, link(name = "bar.dll"))]
 extern "C-unwind" {
     fn panic();
 }