diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 93a65290602af..fef4ce0b471c8 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -52,7 +52,7 @@ use std::ffi::OsString;
 use std::fmt::Write as _;
 use std::fs::{self, File};
 use std::io::{self, IsTerminal, Read, Write};
-use std::panic::{self, catch_unwind, PanicInfo};
+use std::panic::{self, catch_unwind, PanicHookInfo};
 use std::path::PathBuf;
 use std::process::{self, Command, Stdio};
 use std::str;
@@ -1366,11 +1366,10 @@ pub fn install_ice_hook(
     let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default());
     let using_internal_features_hook = using_internal_features.clone();
     panic::update_hook(Box::new(
-        move |default_hook: &(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static),
-              info: &PanicInfo<'_>| {
+        move |default_hook: &(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static),
+              info: &PanicHookInfo<'_>| {
             // Lock stderr to prevent interleaving of concurrent panics.
             let _guard = io::stderr().lock();
-
             // If the error was caused by a broken pipe then this is not a bug.
             // Write the error and return immediately. See #98700.
             #[cfg(windows)]
@@ -1431,7 +1430,7 @@ pub fn install_ice_hook(
 /// When `install_ice_hook` is called, this function will be called as the panic
 /// hook.
 fn report_ice(
-    info: &panic::PanicInfo<'_>,
+    info: &panic::PanicHookInfo<'_>,
     bug_report_url: &str,
     extra_info: fn(&DiagCtxt),
     using_internal_features: &AtomicBool,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index bbe4a8791c69c..803d155432461 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3360,14 +3360,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .source_map()
                         .indentation_before(rcvr.span)
                         .unwrap_or_else(|| " ".to_string());
-                    err.multipart_suggestion(
-                        "consider pinning the expression",
-                        vec![
-                            (rcvr.span.shrink_to_lo(), format!("let mut pinned = std::pin::pin!(")),
-                            (rcvr.span.shrink_to_hi(), format!(");\n{indent}pinned.{pin_call}()")),
-                        ],
-                        Applicability::MaybeIncorrect,
-                    );
+                    let mut expr = rcvr;
+                    while let Node::Expr(call_expr) = self.tcx.parent_hir_node(expr.hir_id)
+                        && let hir::ExprKind::MethodCall(hir::PathSegment { .. }, ..) =
+                            call_expr.kind
+                    {
+                        expr = call_expr;
+                    }
+                    match self.tcx.parent_hir_node(expr.hir_id) {
+                        Node::LetStmt(stmt)
+                            if let Some(init) = stmt.init
+                                && let Ok(code) =
+                                    self.tcx.sess.source_map().span_to_snippet(rcvr.span) =>
+                        {
+                            // We need to take care to account for the existing binding when we
+                            // suggest the code.
+                            err.multipart_suggestion(
+                                "consider pinning the expression",
+                                vec![
+                                    (
+                                        stmt.span.shrink_to_lo(),
+                                        format!(
+                                            "let mut pinned = std::pin::pin!({code});\n{indent}"
+                                        ),
+                                    ),
+                                    (
+                                        init.span.until(rcvr.span.shrink_to_hi()),
+                                        format!("pinned.{pin_call}()"),
+                                    ),
+                                ],
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                        Node::Block(_) | Node::Stmt(_) => {
+                            // There's no binding, so we can provide a slightly nicer looking
+                            // suggestion.
+                            err.multipart_suggestion(
+                                "consider pinning the expression",
+                                vec![
+                                    (
+                                        rcvr.span.shrink_to_lo(),
+                                        format!("let mut pinned = std::pin::pin!("),
+                                    ),
+                                    (
+                                        rcvr.span.shrink_to_hi(),
+                                        format!(");\n{indent}pinned.{pin_call}()"),
+                                    ),
+                                ],
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                        _ => {
+                            // We don't quite know what the users' code looks like, so we don't
+                            // provide a pinning suggestion.
+                            err.span_help(
+                                rcvr.span,
+                                "consider pinning the expression with `std::pin::pin!()` and \
+                                 assigning that to a new binding",
+                            );
+                        }
+                    }
                     // We don't care about the other suggestions.
                     alt_rcvr_sugg = true;
                 }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 8c9abeafacfe7..98318cd14d9dc 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -142,7 +142,7 @@ declare_lint! {
     /// ```rust,compile_fail
     /// #![deny(box_pointers)]
     /// struct Foo {
-    ///     x: Box<isize>,
+    ///     x: Box<i32>,
     /// }
     /// ```
     ///
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 46b137881866e..aeb7f587a26fd 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -2069,12 +2069,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 })
                 .collect();
 
-            let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
+            let end = if candidates.len() <= 9 || self.tcx.sess.opts.verbose {
+                candidates.len()
+            } else {
+                8
+            };
             err.help(format!(
                 "the following {other}types implement trait `{}`:{}{}",
                 trait_ref.print_trait_sugared(),
                 candidates[..end].join(""),
-                if candidates.len() > 9 {
+                if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
                     format!("\nand {} others", candidates.len() - 8)
                 } else {
                     String::new()
diff --git a/library/core/src/error.md b/library/core/src/error.md
index a5deb71e6b80a..4b62391cafc37 100644
--- a/library/core/src/error.md
+++ b/library/core/src/error.md
@@ -17,8 +17,8 @@ The following are the primary interfaces of the panic system and the
 responsibilities they cover:
 
 * [`panic!`] and [`panic_any`] (Constructing, Propagated automatically)
-* [`PanicInfo`] (Reporting)
-* [`set_hook`], [`take_hook`], and [`#[panic_handler]`][panic-handler] (Reporting)
+* [`set_hook`], [`take_hook`], and [`PanicHookInfo`] (Reporting)
+* [`#[panic_handler]`][panic-handler] and [`PanicInfo`] (Reporting in no_std)
 * [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating)
 
 The following are the primary interfaces of the error system and the
@@ -125,6 +125,7 @@ expect-as-precondition style error messages remember to focus on the word
 should be available and executable by the current user".
 
 [`panic_any`]: ../../std/panic/fn.panic_any.html
+[`PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
 [`PanicInfo`]: crate::panic::PanicInfo
 [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
 [`resume_unwind`]: ../../std/panic/fn.resume_unwind.html
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 8771f40f9b42b..b5a0932221ad6 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -144,7 +144,7 @@ pub macro unreachable_2021 {
 /// use.
 #[unstable(feature = "std_internals", issue = "none")]
 #[doc(hidden)]
-pub unsafe trait PanicPayload {
+pub unsafe trait PanicPayload: crate::fmt::Display {
     /// Take full ownership of the contents.
     /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core.
     ///
@@ -157,4 +157,9 @@ pub unsafe trait PanicPayload {
 
     /// Just borrow the contents.
     fn get(&mut self) -> &(dyn Any + Send);
+
+    /// Try to borrow the contents as `&str`, if possible without doing any allocations.
+    fn as_str(&mut self) -> Option<&str> {
+        None
+    }
 }
diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs
index eb27da1724ec9..8c04994ac0fc4 100644
--- a/library/core/src/panic/location.rs
+++ b/library/core/src/panic/location.rs
@@ -2,9 +2,10 @@ use crate::fmt;
 
 /// A struct containing information about the location of a panic.
 ///
-/// This structure is created by [`PanicInfo::location()`].
+/// This structure is created by [`PanicHookInfo::location()`] and [`PanicInfo::location()`].
 ///
 /// [`PanicInfo::location()`]: crate::panic::PanicInfo::location
+/// [`PanicHookInfo::location()`]: ../../std/panic/struct.PanicHookInfo.html#method.location
 ///
 /// # Examples
 ///
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index 403262212580c..df8f441bf3533 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -1,90 +1,32 @@
-use crate::any::Any;
 use crate::fmt;
 use crate::panic::Location;
 
 /// A struct providing information about a panic.
 ///
-/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
-/// function.
+/// A `PanicInfo` structure is passed to the panic handler defined by `#[panic_handler]`.
 ///
-/// [`set_hook`]: ../../std/panic/fn.set_hook.html
+/// For the type used by the panic hook mechanism in `std`, see [`std::panic::PanicHookInfo`].
 ///
-/// # Examples
-///
-/// ```should_panic
-/// use std::panic;
-///
-/// panic::set_hook(Box::new(|panic_info| {
-///     println!("panic occurred: {panic_info}");
-/// }));
-///
-/// panic!("critical system failure");
-/// ```
+/// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
 #[lang = "panic_info"]
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 #[derive(Debug)]
 pub struct PanicInfo<'a> {
-    payload: &'a (dyn Any + Send),
-    message: Option<&'a fmt::Arguments<'a>>,
+    message: fmt::Arguments<'a>,
     location: &'a Location<'a>,
     can_unwind: bool,
     force_no_backtrace: bool,
 }
 
 impl<'a> PanicInfo<'a> {
-    #[unstable(
-        feature = "panic_internals",
-        reason = "internal details of the implementation of the `panic!` and related macros",
-        issue = "none"
-    )]
-    #[doc(hidden)]
     #[inline]
-    pub fn internal_constructor(
-        message: Option<&'a fmt::Arguments<'a>>,
+    pub(crate) fn new(
+        message: fmt::Arguments<'a>,
         location: &'a Location<'a>,
         can_unwind: bool,
         force_no_backtrace: bool,
     ) -> Self {
-        struct NoPayload;
-        PanicInfo { location, message, payload: &NoPayload, can_unwind, force_no_backtrace }
-    }
-
-    #[unstable(
-        feature = "panic_internals",
-        reason = "internal details of the implementation of the `panic!` and related macros",
-        issue = "none"
-    )]
-    #[doc(hidden)]
-    #[inline]
-    pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
-        self.payload = info;
-    }
-
-    /// Returns the payload associated with the panic.
-    ///
-    /// This will commonly, but not always, be a `&'static str` or [`String`].
-    ///
-    /// [`String`]: ../../std/string/struct.String.html
-    ///
-    /// # Examples
-    ///
-    /// ```should_panic
-    /// use std::panic;
-    ///
-    /// panic::set_hook(Box::new(|panic_info| {
-    ///     if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
-    ///         println!("panic occurred: {s:?}");
-    ///     } else {
-    ///         println!("panic occurred");
-    ///     }
-    /// }));
-    ///
-    /// panic!("Normal panic");
-    /// ```
-    #[must_use]
-    #[stable(feature = "panic_hooks", since = "1.10.0")]
-    pub fn payload(&self) -> &(dyn Any + Send) {
-        self.payload
+        PanicInfo { location, message, can_unwind, force_no_backtrace }
     }
 
     /// If the `panic!` macro from the `core` crate (not from `std`)
@@ -92,7 +34,7 @@ impl<'a> PanicInfo<'a> {
     /// returns that message ready to be used for example with [`fmt::write`]
     #[must_use]
     #[unstable(feature = "panic_info_message", issue = "66745")]
-    pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
+    pub fn message(&self) -> fmt::Arguments<'_> {
         self.message
     }
 
@@ -128,6 +70,24 @@ impl<'a> PanicInfo<'a> {
         Some(&self.location)
     }
 
+    /// Returns the payload associated with the panic.
+    ///
+    /// On `core::panic::PanicInfo`, this method never returns anything useful.
+    /// It only exists because of compatibility with [`std::panic::PanicHookInfo`],
+    /// which used to be the same type.
+    ///
+    /// See [`std::panic::PanicHookInfo::payload`].
+    ///
+    /// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
+    /// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload
+    #[deprecated(since = "1.77.0", note = "this never returns anything useful")]
+    #[stable(feature = "panic_hooks", since = "1.10.0")]
+    #[allow(deprecated, deprecated_in_future)]
+    pub fn payload(&self) -> &(dyn crate::any::Any + Send) {
+        struct NoPayload;
+        &NoPayload
+    }
+
     /// Returns whether the panic handler is allowed to unwind the stack from
     /// the point where the panic occurred.
     ///
@@ -161,18 +121,8 @@ impl fmt::Display for PanicInfo<'_> {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         formatter.write_str("panicked at ")?;
         self.location.fmt(formatter)?;
-        formatter.write_str(":")?;
-        if let Some(message) = self.message {
-            formatter.write_str("\n")?;
-            formatter.write_fmt(*message)?;
-        } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
-            formatter.write_str("\n")?;
-            formatter.write_str(payload)?;
-        }
-        // NOTE: we cannot use downcast_ref::<String>() here
-        // since String is not available in core!
-        // The payload is a String when `std::panic!` is called with multiple arguments,
-        // but in that case the message is also available.
+        formatter.write_str(":\n")?;
+        formatter.write_fmt(self.message)?;
         Ok(())
     }
 }
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index ca06e059b75ac..97fb1d6b7323f 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -1,7 +1,14 @@
 //! Panic support for core
 //!
-//! The core library cannot define panicking, but it does *declare* panicking. This
-//! means that the functions inside of core are allowed to panic, but to be
+//! In core, panicking is always done with a message, resulting in a `core::panic::PanicInfo`
+//! containing a `fmt::Arguments`. In std, however, panicking can be done with panic_any, which
+//! throws a `Box<dyn Any>` containing any type of value. Because of this,
+//! `std::panic::PanicHookInfo` is a different type, which contains a `&dyn Any` instead of a
+//! `fmt::Arguments`. std's panic handler will convert the `fmt::Arguments` to a `&dyn Any`
+//! containing either a `&'static str` or `String` containing the formatted message.
+//!
+//! The core library cannot define any panic handler, but it can invoke it.
+//! This means that the functions inside of core are allowed to panic, but to be
 //! useful an upstream crate must define panicking for core to use. The current
 //! interface for panicking is:
 //!
@@ -10,11 +17,6 @@
 //! # { loop {} }
 //! ```
 //!
-//! This definition allows for panicking with any general message, but it does not
-//! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`,
-//! for which we fill in a dummy value in `PanicInfo::internal_constructor`.)
-//! The reason for this is that core is not allowed to allocate.
-//!
 //! This module contains a few other panicking functions, but these are just the
 //! necessary lang items for the compiler. All panics are funneled through this
 //! one function. The actual symbol is declared through the `#[panic_handler]` attribute.
@@ -61,8 +63,8 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
         fn panic_impl(pi: &PanicInfo<'_>) -> !;
     }
 
-    let pi = PanicInfo::internal_constructor(
-        Some(&fmt),
+    let pi = PanicInfo::new(
+        fmt,
         Location::caller(),
         /* can_unwind */ true,
         /* force_no_backtrace */ false,
@@ -99,8 +101,8 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
         }
 
         // PanicInfo with the `can_unwind` flag set to false forces an abort.
-        let pi = PanicInfo::internal_constructor(
-            Some(&fmt),
+        let pi = PanicInfo::new(
+            fmt,
             Location::caller(),
             /* can_unwind */ false,
             force_no_backtrace,
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index e63b46ab70548..5282c00fccaf0 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -4,11 +4,215 @@
 
 use crate::any::Any;
 use crate::collections;
+use crate::fmt;
 use crate::panicking;
 use crate::sync::atomic::{AtomicU8, Ordering};
 use crate::sync::{Condvar, Mutex, RwLock};
 use crate::thread::Result;
 
+#[stable(feature = "panic_hooks", since = "1.10.0")]
+#[deprecated(
+    since = "1.82.0",
+    note = "use `PanicHookInfo` instead",
+    suggestion = "std::panic::PanicHookInfo"
+)]
+/// A struct providing information about a panic.
+///
+/// `PanicInfo` has been renamed to [`PanicHookInfo`] to avoid confusion with
+/// [`core::panic::PanicInfo`].
+pub type PanicInfo<'a> = PanicHookInfo<'a>;
+
+/// A struct providing information about a panic.
+///
+/// `PanicHookInfo` structure is passed to a panic hook set by the [`set_hook`] function.
+///
+/// # Examples
+///
+/// ```should_panic
+/// use std::panic;
+///
+/// panic::set_hook(Box::new(|panic_info| {
+///     println!("panic occurred: {panic_info}");
+/// }));
+///
+/// panic!("critical system failure");
+/// ```
+///
+/// [`set_hook`]: ../../std/panic/fn.set_hook.html
+#[stable(feature = "panic_hook_info", since = "CURRENT_RUSTC_VERSION")]
+#[derive(Debug)]
+pub struct PanicHookInfo<'a> {
+    payload: &'a (dyn Any + Send),
+    location: &'a Location<'a>,
+    can_unwind: bool,
+    force_no_backtrace: bool,
+}
+
+impl<'a> PanicHookInfo<'a> {
+    #[inline]
+    pub(crate) fn new(
+        location: &'a Location<'a>,
+        payload: &'a (dyn Any + Send),
+        can_unwind: bool,
+        force_no_backtrace: bool,
+    ) -> Self {
+        PanicHookInfo { payload, location, can_unwind, force_no_backtrace }
+    }
+
+    /// Returns the payload associated with the panic.
+    ///
+    /// This will commonly, but not always, be a `&'static str` or [`String`].
+    ///
+    /// A invocation of the `panic!()` macro in Rust 2021 or later will always result in a
+    /// panic payload of type `&'static str` or `String`.
+    ///
+    /// Only an invocation of [`panic_any`]
+    /// (or, in Rust 2018 and earlier, `panic!(x)` where `x` is something other than a string)
+    /// can result in a panic payload other than a `&'static str` or `String`.
+    ///
+    /// [`String`]: ../../std/string/struct.String.html
+    ///
+    /// # Examples
+    ///
+    /// ```should_panic
+    /// use std::panic;
+    ///
+    /// panic::set_hook(Box::new(|panic_info| {
+    ///     if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
+    ///         println!("panic occurred: {s:?}");
+    ///     } else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
+    ///         println!("panic occurred: {s:?}");
+    ///     } else {
+    ///         println!("panic occurred");
+    ///     }
+    /// }));
+    ///
+    /// panic!("Normal panic");
+    /// ```
+    #[must_use]
+    #[inline]
+    #[stable(feature = "panic_hooks", since = "1.10.0")]
+    pub fn payload(&self) -> &(dyn Any + Send) {
+        self.payload
+    }
+
+    /// Returns the payload associated with the panic, if it is a string.
+    ///
+    /// This returns the payload if it is of type `&'static str` or `String`.
+    ///
+    /// A invocation of the `panic!()` macro in Rust 2021 or later will always result in a
+    /// panic payload where `payload_as_str` returns `Some`.
+    ///
+    /// Only an invocation of [`panic_any`]
+    /// (or, in Rust 2018 and earlier, `panic!(x)` where `x` is something other than a string)
+    /// can result in a panic payload where `payload_as_str` returns `None`.
+    ///
+    /// # Example
+    ///
+    /// ```should_panic
+    /// #![feature(panic_payload_as_str)]
+    ///
+    /// std::panic::set_hook(Box::new(|panic_info| {
+    ///     if let Some(s) = panic_info.payload_as_str() {
+    ///         println!("panic occurred: {s:?}");
+    ///     } else {
+    ///         println!("panic occurred");
+    ///     }
+    /// }));
+    ///
+    /// panic!("Normal panic");
+    /// ```
+    #[must_use]
+    #[inline]
+    #[unstable(feature = "panic_payload_as_str", issue = "125175")]
+    pub fn payload_as_str(&self) -> Option<&str> {
+        if let Some(s) = self.payload.downcast_ref::<&str>() {
+            Some(s)
+        } else if let Some(s) = self.payload.downcast_ref::<String>() {
+            Some(s)
+        } else {
+            None
+        }
+    }
+
+    /// Returns information about the location from which the panic originated,
+    /// if available.
+    ///
+    /// This method will currently always return [`Some`], but this may change
+    /// in future versions.
+    ///
+    /// # Examples
+    ///
+    /// ```should_panic
+    /// use std::panic;
+    ///
+    /// panic::set_hook(Box::new(|panic_info| {
+    ///     if let Some(location) = panic_info.location() {
+    ///         println!("panic occurred in file '{}' at line {}",
+    ///             location.file(),
+    ///             location.line(),
+    ///         );
+    ///     } else {
+    ///         println!("panic occurred but can't get location information...");
+    ///     }
+    /// }));
+    ///
+    /// panic!("Normal panic");
+    /// ```
+    #[must_use]
+    #[inline]
+    #[stable(feature = "panic_hooks", since = "1.10.0")]
+    pub fn location(&self) -> Option<&Location<'_>> {
+        // NOTE: If this is changed to sometimes return None,
+        // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt.
+        Some(&self.location)
+    }
+
+    /// Returns whether the panic handler is allowed to unwind the stack from
+    /// the point where the panic occurred.
+    ///
+    /// This is true for most kinds of panics with the exception of panics
+    /// caused by trying to unwind out of a `Drop` implementation or a function
+    /// whose ABI does not support unwinding.
+    ///
+    /// It is safe for a panic handler to unwind even when this function returns
+    /// false, however this will simply cause the panic handler to be called
+    /// again.
+    #[must_use]
+    #[inline]
+    #[unstable(feature = "panic_can_unwind", issue = "92988")]
+    pub fn can_unwind(&self) -> bool {
+        self.can_unwind
+    }
+
+    #[unstable(
+        feature = "panic_internals",
+        reason = "internal details of the implementation of the `panic!` and related macros",
+        issue = "none"
+    )]
+    #[doc(hidden)]
+    #[inline]
+    pub fn force_no_backtrace(&self) -> bool {
+        self.force_no_backtrace
+    }
+}
+
+#[stable(feature = "panic_hook_display", since = "1.26.0")]
+impl fmt::Display for PanicHookInfo<'_> {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        formatter.write_str("panicked at ")?;
+        self.location.fmt(formatter)?;
+        if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
+            formatter.write_str(":\n")?;
+            formatter.write_str(payload)?;
+        } else if let Some(payload) = self.payload.downcast_ref::<String>() {
+            formatter.write_str(":\n")?;
+            formatter.write_str(payload)?;
+        }
+        Ok(())
+    }
+}
+
 #[doc(hidden)]
 #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
 #[allow_internal_unstable(libstd_sys_internals, const_format_args, panic_internals, rt)]
@@ -43,7 +247,7 @@ pub use crate::panicking::{set_hook, take_hook};
 pub use crate::panicking::update_hook;
 
 #[stable(feature = "panic_hooks", since = "1.10.0")]
-pub use core::panic::{Location, PanicInfo};
+pub use core::panic::Location;
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
@@ -53,7 +257,7 @@ pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
 /// The message can be of any (`Any + Send`) type, not just strings.
 ///
 /// The message is wrapped in a `Box<'static + Any + Send>`, which can be
-/// accessed later using [`PanicInfo::payload`].
+/// accessed later using [`PanicHookInfo::payload`].
 ///
 /// See the [`panic!`] macro for more information about panicking.
 #[stable(feature = "panic_any", since = "1.51.0")]
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 5699937cdb49b..8fd8134c11147 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -9,8 +9,8 @@
 
 #![deny(unsafe_op_in_unsafe_fn)]
 
-use crate::panic::BacktraceStyle;
-use core::panic::{Location, PanicInfo, PanicPayload};
+use crate::panic::{BacktraceStyle, PanicHookInfo};
+use core::panic::{Location, PanicPayload};
 
 use crate::any::Any;
 use crate::fmt;
@@ -70,12 +70,12 @@ extern "C" fn __rust_foreign_exception() -> ! {
 
 enum Hook {
     Default,
-    Custom(Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>),
+    Custom(Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>),
 }
 
 impl Hook {
     #[inline]
-    fn into_box(self) -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
+    fn into_box(self) -> Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send> {
         match self {
             Hook::Default => Box::new(default_hook),
             Hook::Custom(hook) => hook,
@@ -105,7 +105,7 @@ static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
 ///
 /// [`take_hook`]: ./fn.take_hook.html
 ///
-/// The hook is provided with a `PanicInfo` struct which contains information
+/// The hook is provided with a `PanicHookInfo` struct which contains information
 /// about the origin of the panic, including the payload passed to `panic!` and
 /// the source code location from which the panic originated.
 ///
@@ -129,7 +129,7 @@ static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
 /// panic!("Normal panic");
 /// ```
 #[stable(feature = "panic_hooks", since = "1.10.0")]
-pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
+pub fn set_hook(hook: Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>) {
     if thread::panicking() {
         panic!("cannot modify the panic hook from a panicking thread");
     }
@@ -173,7 +173,7 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
 /// ```
 #[must_use]
 #[stable(feature = "panic_hooks", since = "1.10.0")]
-pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
+pub fn take_hook() -> Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send> {
     if thread::panicking() {
         panic!("cannot modify the panic hook from a panicking thread");
     }
@@ -219,7 +219,7 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
 #[unstable(feature = "panic_update_hook", issue = "92649")]
 pub fn update_hook<F>(hook_fn: F)
 where
-    F: Fn(&(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static), &PanicInfo<'_>)
+    F: Fn(&(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static), &PanicHookInfo<'_>)
         + Sync
         + Send
         + 'static,
@@ -234,7 +234,7 @@ where
 }
 
 /// The default panic handler.
-fn default_hook(info: &PanicInfo<'_>) {
+fn default_hook(info: &PanicHookInfo<'_>) {
     // If this is a double panic, make sure that we print a backtrace
     // for this panic. Otherwise only print it if logging is enabled.
     let backtrace = if info.force_no_backtrace() {
@@ -248,13 +248,7 @@ fn default_hook(info: &PanicInfo<'_>) {
     // The current implementation always returns `Some`.
     let location = info.location().unwrap();
 
-    let msg = match info.payload().downcast_ref::<&'static str>() {
-        Some(s) => *s,
-        None => match info.payload().downcast_ref::<String>() {
-            Some(s) => &s[..],
-            None => "Box<dyn Any>",
-        },
-    };
+    let msg = payload_as_str(info.payload());
     let thread = thread::try_current();
     let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
 
@@ -597,17 +591,13 @@ pub fn panicking() -> bool {
 /// Entry point of panics from the core crate (`panic_impl` lang item).
 #[cfg(not(any(test, doctest)))]
 #[panic_handler]
-pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
+pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
     struct FormatStringPayload<'a> {
         inner: &'a fmt::Arguments<'a>,
         string: Option<String>,
     }
 
-    impl<'a> FormatStringPayload<'a> {
-        fn new(inner: &'a fmt::Arguments<'a>) -> Self {
-            Self { inner, string: None }
-        }
-
+    impl FormatStringPayload<'_> {
         fn fill(&mut self) -> &mut String {
             use crate::fmt::Write;
 
@@ -621,7 +611,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
         }
     }
 
-    unsafe impl<'a> PanicPayload for FormatStringPayload<'a> {
+    unsafe impl PanicPayload for FormatStringPayload<'_> {
         fn take_box(&mut self) -> *mut (dyn Any + Send) {
             // We do two allocations here, unfortunately. But (a) they're required with the current
             // scheme, and (b) we don't handle panic + OOM properly anyway (see comment in
@@ -635,6 +625,12 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
         }
     }
 
+    impl fmt::Display for FormatStringPayload<'_> {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            if let Some(s) = &self.string { f.write_str(s) } else { f.write_fmt(*self.inner) }
+        }
+    }
+
     struct StaticStrPayload(&'static str);
 
     unsafe impl PanicPayload for StaticStrPayload {
@@ -645,25 +641,31 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
         fn get(&mut self) -> &(dyn Any + Send) {
             &self.0
         }
+
+        fn as_str(&mut self) -> Option<&str> {
+            Some(self.0)
+        }
+    }
+
+    impl fmt::Display for StaticStrPayload {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            f.write_str(self.0)
+        }
     }
 
     let loc = info.location().unwrap(); // The current implementation always returns Some
-    let msg = info.message().unwrap(); // The current implementation always returns Some
+    let msg = info.message();
     crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
-        // FIXME: can we just pass `info` along rather than taking it apart here, only to have
-        // `rust_panic_with_hook` construct a new `PanicInfo`?
-        if let Some(msg) = msg.as_str() {
+        if let Some(s) = msg.as_str() {
             rust_panic_with_hook(
-                &mut StaticStrPayload(msg),
-                info.message(),
+                &mut StaticStrPayload(s),
                 loc,
                 info.can_unwind(),
                 info.force_no_backtrace(),
             );
         } else {
             rust_panic_with_hook(
-                &mut FormatStringPayload::new(msg),
-                info.message(),
+                &mut FormatStringPayload { inner: &msg, string: None },
                 loc,
                 info.can_unwind(),
                 info.force_no_backtrace(),
@@ -689,27 +691,10 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
         intrinsics::abort()
     }
 
-    let loc = Location::caller();
-    return crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
-        rust_panic_with_hook(
-            &mut Payload::new(msg),
-            None,
-            loc,
-            /* can_unwind */ true,
-            /* force_no_backtrace */ false,
-        )
-    });
-
     struct Payload<A> {
         inner: Option<A>,
     }
 
-    impl<A: Send + 'static> Payload<A> {
-        fn new(inner: A) -> Payload<A> {
-            Payload { inner: Some(inner) }
-        }
-    }
-
     unsafe impl<A: Send + 'static> PanicPayload for Payload<A> {
         fn take_box(&mut self) -> *mut (dyn Any + Send) {
             // Note that this should be the only allocation performed in this code path. Currently
@@ -731,6 +716,35 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
             }
         }
     }
+
+    impl<A: 'static> fmt::Display for Payload<A> {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            match &self.inner {
+                Some(a) => f.write_str(payload_as_str(a)),
+                None => process::abort(),
+            }
+        }
+    }
+
+    let loc = Location::caller();
+    crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
+        rust_panic_with_hook(
+            &mut Payload { inner: Some(msg) },
+            loc,
+            /* can_unwind */ true,
+            /* force_no_backtrace */ false,
+        )
+    })
+}
+
+fn payload_as_str(payload: &dyn Any) -> &str {
+    if let Some(&s) = payload.downcast_ref::<&'static str>() {
+        s
+    } else if let Some(s) = payload.downcast_ref::<String>() {
+        s.as_str()
+    } else {
+        "Box<dyn Any>"
+    }
 }
 
 /// Central point for dispatching panics.
@@ -740,7 +754,6 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
 /// abort or unwind.
 fn rust_panic_with_hook(
     payload: &mut dyn PanicPayload,
-    message: Option<&fmt::Arguments<'_>>,
     location: &Location<'_>,
     can_unwind: bool,
     force_no_backtrace: bool,
@@ -754,35 +767,21 @@ fn rust_panic_with_hook(
                 // Don't try to format the message in this case, perhaps that is causing the
                 // recursive panics. However if the message is just a string, no user-defined
                 // code is involved in printing it, so that is risk-free.
-                let msg_str = message.and_then(|m| m.as_str()).map(|m| [m]);
-                let message = msg_str.as_ref().map(|m| fmt::Arguments::new_const(m));
-                let panicinfo = PanicInfo::internal_constructor(
-                    message.as_ref(),
-                    location,
-                    can_unwind,
-                    force_no_backtrace,
+                let message: &str = payload.as_str().unwrap_or_default();
+                rtprintpanic!(
+                    "panicked at {location}:\n{message}\nthread panicked while processing panic. aborting.\n"
                 );
-                rtprintpanic!("{panicinfo}\nthread panicked while processing panic. aborting.\n");
             }
             panic_count::MustAbort::AlwaysAbort => {
                 // Unfortunately, this does not print a backtrace, because creating
                 // a `Backtrace` will allocate, which we must avoid here.
-                let panicinfo = PanicInfo::internal_constructor(
-                    message,
-                    location,
-                    can_unwind,
-                    force_no_backtrace,
-                );
-                rtprintpanic!("{panicinfo}\npanicked after panic::always_abort(), aborting.\n");
+                rtprintpanic!("aborting due to panic at {location}:\n{payload}\n");
             }
         }
         crate::sys::abort_internal();
     }
 
-    let mut info =
-        PanicInfo::internal_constructor(message, location, can_unwind, force_no_backtrace);
-    let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner);
-    match *hook {
+    match *HOOK.read().unwrap_or_else(PoisonError::into_inner) {
         // Some platforms (like wasm) know that printing to stderr won't ever actually
         // print anything, and if that's the case we can skip the default
         // hook. Since string formatting happens lazily when calling `payload`
@@ -791,15 +790,17 @@ fn rust_panic_with_hook(
         // formatting.)
         Hook::Default if panic_output().is_none() => {}
         Hook::Default => {
-            info.set_payload(payload.get());
-            default_hook(&info);
+            default_hook(&PanicHookInfo::new(
+                location,
+                payload.get(),
+                can_unwind,
+                force_no_backtrace,
+            ));
         }
         Hook::Custom(ref hook) => {
-            info.set_payload(payload.get());
-            hook(&info);
+            hook(&PanicHookInfo::new(location, payload.get(), can_unwind, force_no_backtrace));
         }
-    };
-    drop(hook);
+    }
 
     // Indicate that we have finished executing the panic hook. After this point
     // it is fine if there is a panic while executing destructors, as long as it
@@ -835,6 +836,12 @@ pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
         }
     }
 
+    impl fmt::Display for RewrapBox {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            f.write_str(payload_as_str(&self.0))
+        }
+    }
+
     rust_panic(&mut RewrapBox(payload))
 }
 
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 7bd08a0605f83..7aff7fe1fdd68 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -58,7 +58,7 @@ use std::{
     env, io,
     io::prelude::Write,
     mem::ManuallyDrop,
-    panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo},
+    panic::{self, catch_unwind, AssertUnwindSafe, PanicHookInfo},
     process::{self, Command, Termination},
     sync::mpsc::{channel, Sender},
     sync::{Arc, Mutex},
@@ -123,7 +123,7 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Opt
             // from interleaving with the panic message or appearing after it.
             let builtin_panic_hook = panic::take_hook();
             let hook = Box::new({
-                move |info: &'_ PanicInfo<'_>| {
+                move |info: &'_ PanicHookInfo<'_>| {
                     if !info.can_unwind() {
                         std::mem::forget(std::io::stderr().lock());
                         let mut stdout = ManuallyDrop::new(std::io::stdout().lock());
@@ -726,7 +726,7 @@ fn spawn_test_subprocess(
 
 fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) -> ! {
     let builtin_panic_hook = panic::take_hook();
-    let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| {
+    let record_result = Arc::new(move |panic_info: Option<&'_ PanicHookInfo<'_>>| {
         let test_result = match panic_info {
             Some(info) => calc_result(&desc, Err(info.payload()), &None, &None),
             None => calc_result(&desc, Ok(()), &None, &None),
diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile
similarity index 54%
rename from src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
rename to src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile
index 07260be35877a..a9ffa5918b5bc 100644
--- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile
@@ -1,39 +1,36 @@
 # based on armhf-gnu/Dockerfile
-FROM ubuntu:20.04
+FROM ubuntu:22.04
 
-RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
+ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update -y && apt-get install -y --no-install-recommends \
-    bc \
-    bison \
-    ca-certificates \
-    cmake \
-    cpio \
-    curl \
-    debian-ports-archive-keyring \
-    debootstrap \
-    flex \
-    gcc \
-    gcc-riscv64-linux-gnu \
-    git \
-    g++-riscv64-linux-gnu \
-    g++ \
-    libc6-dev \
-    libc6-dev-riscv64-cross \
-    libssl-dev \
-    make \
-    ninja-build \
-    patch \
-    python3 \
-    qemu-system-misc \
-    xz-utils
+      bc \
+      bzip2 \
+      ca-certificates \
+      cmake \
+      cpio \
+      curl \
+      file \
+      flex \
+      bison \
+      g++ \
+      g++-riscv64-linux-gnu \
+      git \
+      libc6-dev \
+      libc6-dev-riscv64-cross \
+      libssl-dev \
+      make \
+      ninja-build \
+      python3 \
+      qemu-system-riscv64 \
+      xz-utils
 
-ENV ARCH=riscv
-ENV CROSS_COMPILE=riscv64-linux-gnu-
+ENV ARCH=riscv \
+    CROSS_COMPILE=riscv64-linux-gnu-
 
 WORKDIR /build
 
 # From https://github.com/michaeljclark/busybear-linux/blob/master/conf/linux.config
-COPY host-x86_64/riscv64gc-linux/linux.config /build
+COPY host-x86_64/riscv64gc-gnu/linux.config /build
 
 # Compile the kernel that we're going to be emulating with. This is
 # basically just done to be compatible with the QEMU target that we're going
@@ -49,29 +46,22 @@ RUN curl https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.6.16.tar.xz | tar
 # Compile an instance of busybox as this provides a lightweight system and init
 # binary which we will boot into. Only trick here is configuring busybox to
 # build static binaries.
-RUN curl https://busybox.net/downloads/busybox-1.31.1.tar.bz2 | tar xjf -
-COPY host-x86_64/riscv64gc-linux/0001-Remove-stime-function-calls.patch /build/busybox-1.31.1/
-RUN cd /build/busybox-1.31.1 && \
-    patch -p1 -i 0001-Remove-stime-function-calls.patch && \
-    make defconfig && \
-    sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \
-    make -j$(nproc) && \
-    make install && \
-    mv _install /tmp/rootfs && \
-    cd /build && \
-    rm -rf busybox-1.31.1
+RUN curl https://www.busybox.net/downloads/busybox-1.32.1.tar.bz2 | tar xjf - && \
+      cd busybox-1.32.1 && \
+      make defconfig && \
+      sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \
+      make -j$(nproc) && \
+      make install && \
+      mv _install /tmp/rootfs && \
+      cd /build && \
+      rm -rf busybox-1.32.1
 
-# Download the ubuntu rootfs, which we'll use as a chroot for all our tests
-# This is only needed to provide /lib/* and /usr/lib/*
+# Download the ubuntu rootfs, which we'll use as a chroot for all our tests.
 WORKDIR /tmp
-RUN debootstrap --variant=minbase --arch=riscv64 --foreign focal /tmp/rootfs/ubuntu
-RUN cd rootfs && mkdir proc sys dev etc etc/init.d
-# rootfs/ubuntu/proc is in a weird state (access fails with ELOOP) until
-# rootfs/ubuntu/debootstrap/debootstrap --second-stage is run (under emulation),
-# but this takes ages. Instead hack it into a good enough state.
-# /proc is used by std::env::current_exe() (which is roughly
-# `readlink /proc/self/exe`)
-RUN cd rootfs/ubuntu && rm -rf proc && mkdir proc
+RUN mkdir rootfs/ubuntu
+RUN curl https://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04.2-base-riscv64.tar.gz | \
+      tar xzf - -C rootfs/ubuntu && \
+      cd rootfs && mkdir proc sys dev etc etc/init.d
 
 # Copy over our init script, which starts up our test server and also a few other
 # misc tasks
@@ -95,12 +85,12 @@ RUN mkdir build && cd build && \
 WORKDIR /tmp
 RUN rm -rf /tmp/riscv-pk
 
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+# Avoid "fatal: detected dubious ownership in repository at '/checkout'" error
+RUN git config --global --add safe.directory /checkout
+
 ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs
 ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target riscv64gc-unknown-linux-gnu
 
diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/linux.config b/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/linux.config
similarity index 100%
rename from src/ci/docker/host-x86_64/disabled/riscv64gc-linux/linux.config
rename to src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/linux.config
diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch
deleted file mode 100644
index 4437a870b207e..0000000000000
--- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-From c820da85c65c7f3aa9e9cb3ed71ada69bf9b783e Mon Sep 17 00:00:00 2001
-From: Alistair Francis <alistair.francis@wdc.com>
-Date: Tue, 19 Nov 2019 13:06:40 +0100
-Subject: [PATCH] Remove stime() function calls
-
-stime() has been deprecated in glibc 2.31 and replaced with
-clock_settime(). Let's replace the stime() function calls with
-clock_settime() in preparation.
-
-function                                             old     new   delta
-rdate_main                                           197     224     +27
-clock_settime                                          -      27     +27
-date_main                                            926     941     +15
-stime                                                 37       -     -37
-------------------------------------------------------------------------------
-(add/remove: 2/2 grow/shrink: 2/0 up/down: 69/-37)             Total: 32 bytes
-
-Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
-Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-
-[Tom Eccles: adjust patch context to apply on top of 1.31.1-stable]
-Signed-off-by: Tom Eccles <tom.eccles@codethink.co.uk>
----
- coreutils/date.c         | 6 +++++-
- libbb/missing_syscalls.c | 8 --------
- util-linux/rdate.c       | 8 ++++++--
- 3 files changed, 11 insertions(+), 11 deletions(-)
-
-diff --git a/coreutils/date.c b/coreutils/date.c
-index 3414d38ae..4ade6abb4 100644
---- a/coreutils/date.c
-+++ b/coreutils/date.c
-@@ -279,6 +279,9 @@ int date_main(int argc UNUSED_PARAM, char **argv)
- 		time(&ts.tv_sec);
- #endif
- 	}
-+#if !ENABLE_FEATURE_DATE_NANO
-+	ts.tv_nsec = 0;
-+#endif
- 	localtime_r(&ts.tv_sec, &tm_time);
- 
- 	/* If date string is given, update tm_time, and maybe set date */
-@@ -301,9 +304,10 @@ int date_main(int argc UNUSED_PARAM, char **argv)
- 		if (date_str[0] != '@')
- 			tm_time.tm_isdst = -1;
- 		ts.tv_sec = validate_tm_time(date_str, &tm_time);
-+		ts.tv_nsec = 0;
- 
- 		/* if setting time, set it */
--		if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) {
-+		if ((opt & OPT_SET) && clock_settime(CLOCK_REALTIME, &ts) < 0) {
- 			bb_perror_msg("can't set date");
- 		}
- 	}
-diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c
-index 87cf59b3d..dc40d9155 100644
---- a/libbb/missing_syscalls.c
-+++ b/libbb/missing_syscalls.c
-@@ -15,14 +15,6 @@ pid_t getsid(pid_t pid)
- 	return syscall(__NR_getsid, pid);
- }
- 
--int stime(const time_t *t)
--{
--	struct timeval tv;
--	tv.tv_sec = *t;
--	tv.tv_usec = 0;
--	return settimeofday(&tv, NULL);
--}
--
- int sethostname(const char *name, size_t len)
- {
- 	return syscall(__NR_sethostname, name, len);
-diff --git a/util-linux/rdate.c b/util-linux/rdate.c
-index 70f829e7f..878375d78 100644
---- a/util-linux/rdate.c
-+++ b/util-linux/rdate.c
-@@ -95,9 +95,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
- 	if (!(flags & 2)) { /* no -p (-s may be present) */
- 		if (time(NULL) == remote_time)
- 			bb_error_msg("current time matches remote time");
--		else
--			if (stime(&remote_time) < 0)
-+		else {
-+			struct timespec ts;
-+			ts.tv_sec = remote_time;
-+			ts.tv_nsec = 0;
-+			if (clock_settime(CLOCK_REALTIME, &ts) < 0)
- 				bb_perror_msg_and_die("can't set time of day");
-+		}
- 	}
- 
- 	if (flags != 1) /* not lone -s */
--- 
-2.25.1
-
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index b07e012a1b8af..448d4887d32cb 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -175,7 +175,6 @@ run-make/pgo-gen/Makefile
 run-make/pgo-indirect-call-promotion/Makefile
 run-make/pgo-use/Makefile
 run-make/pointer-auth-link-with-c/Makefile
-run-make/prefer-dylib/Makefile
 run-make/prefer-rlib/Makefile
 run-make/pretty-print-to-file/Makefile
 run-make/pretty-print-with-dep-file/Makefile
diff --git a/tests/run-make/prefer-dylib/Makefile b/tests/run-make/prefer-dylib/Makefile
deleted file mode 100644
index cc26e70ae67ca..0000000000000
--- a/tests/run-make/prefer-dylib/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	$(RUSTC) bar.rs --crate-type=dylib --crate-type=rlib -C prefer-dynamic
-	$(RUSTC) foo.rs -C prefer-dynamic
-	$(call RUN,foo)
-	rm $(TMPDIR)/*bar*
-	$(call FAIL,foo)
diff --git a/tests/run-make/prefer-dylib/rmake.rs b/tests/run-make/prefer-dylib/rmake.rs
new file mode 100644
index 0000000000000..ad9fd8a15a2c0
--- /dev/null
+++ b/tests/run-make/prefer-dylib/rmake.rs
@@ -0,0 +1,16 @@
+//@ ignore-cross-compile
+
+use run_make_support::{cwd, dynamic_lib_name, read_dir, run, run_fail, rustc};
+use std::fs::remove_file;
+use std::process::Command;
+
+fn main() {
+    rustc().input("bar.rs").crate_type("dylib").crate_type("rlib").arg("-Cprefer-dynamic").run();
+    rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
+
+    run("foo");
+
+    remove_file(dynamic_lib_name("bar")).unwrap();
+    // This time the command should fail.
+    run_fail("foo");
+}
diff --git a/tests/ui/async-await/pin-needed-to-poll-3.rs b/tests/ui/async-await/pin-needed-to-poll-3.rs
new file mode 100644
index 0000000000000..11ba7d29abaf9
--- /dev/null
+++ b/tests/ui/async-await/pin-needed-to-poll-3.rs
@@ -0,0 +1,25 @@
+use std::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+
+struct FutureWrapper<F> {
+    fut: F,
+}
+
+impl<F> Future for FutureWrapper<F>
+where
+    F: Future,
+{
+    type Output = F::Output;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let res = self.fut.poll(cx);
+        //~^ ERROR no method named `poll` found for type parameter `F` in the current scope
+        res
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/pin-needed-to-poll-3.stderr b/tests/ui/async-await/pin-needed-to-poll-3.stderr
new file mode 100644
index 0000000000000..e4fbef69bacbf
--- /dev/null
+++ b/tests/ui/async-await/pin-needed-to-poll-3.stderr
@@ -0,0 +1,18 @@
+error[E0599]: no method named `poll` found for type parameter `F` in the current scope
+  --> $DIR/pin-needed-to-poll-3.rs:19:28
+   |
+LL | impl<F> Future for FutureWrapper<F>
+   |      - method `poll` not found for this type parameter
+...
+LL |         let res = self.fut.poll(cx);
+   |                            ^^^^ method not found in `F`
+   |
+help: consider pinning the expression
+   |
+LL ~         let mut pinned = std::pin::pin!(self.fut);
+LL ~         let res = pinned.as_mut().poll(cx);
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/duplicate_entry_error.rs b/tests/ui/duplicate_entry_error.rs
index 7ebbab4709557..8e49f57a3df94 100644
--- a/tests/ui/duplicate_entry_error.rs
+++ b/tests/ui/duplicate_entry_error.rs
@@ -5,7 +5,9 @@
 
 #![feature(lang_items)]
 
-use std::panic::PanicInfo;
+extern crate core;
+
+use core::panic::PanicInfo;
 
 #[lang = "panic_impl"]
 fn panic_impl(info: &PanicInfo) -> ! {
diff --git a/tests/ui/duplicate_entry_error.stderr b/tests/ui/duplicate_entry_error.stderr
index 3b5998df353c4..958e9c7527d8c 100644
--- a/tests/ui/duplicate_entry_error.stderr
+++ b/tests/ui/duplicate_entry_error.stderr
@@ -1,5 +1,5 @@
 error[E0152]: found duplicate lang item `panic_impl`
-  --> $DIR/duplicate_entry_error.rs:11:1
+  --> $DIR/duplicate_entry_error.rs:13:1
    |
 LL | / fn panic_impl(info: &PanicInfo) -> ! {
 LL | |
diff --git a/tests/ui/panic-handler/panic-handler-std.rs b/tests/ui/panic-handler/panic-handler-std.rs
index 91b3997819ce4..051828ec8809f 100644
--- a/tests/ui/panic-handler/panic-handler-std.rs
+++ b/tests/ui/panic-handler/panic-handler-std.rs
@@ -1,8 +1,9 @@
 //@ normalize-stderr-test "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib"
 //@ error-pattern: found duplicate lang item `panic_impl`
 
+extern crate core;
 
-use std::panic::PanicInfo;
+use core::panic::PanicInfo;
 
 #[panic_handler]
 fn panic(info: PanicInfo) -> ! {
diff --git a/tests/ui/panic-handler/panic-handler-std.stderr b/tests/ui/panic-handler/panic-handler-std.stderr
index 48c216ce27ec4..caae16118ef7f 100644
--- a/tests/ui/panic-handler/panic-handler-std.stderr
+++ b/tests/ui/panic-handler/panic-handler-std.stderr
@@ -1,5 +1,5 @@
 error[E0152]: found duplicate lang item `panic_impl`
-  --> $DIR/panic-handler-std.rs:8:1
+  --> $DIR/panic-handler-std.rs:9:1
    |
 LL | / fn panic(info: PanicInfo) -> ! {
 LL | |     loop {}