about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/backtrace.rs60
-rw-r--r--library/std/src/env.rs12
-rw-r--r--library/std/src/os/linux/raw.rs6
-rw-r--r--library/std/src/panic.rs205
-rw-r--r--library/std/src/panicking.rs155
-rw-r--r--library/std/src/sys/pal/windows/rand.rs4
-rw-r--r--library/std/src/sys_common/wtf8.rs3
7 files changed, 334 insertions, 111 deletions
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 475b3e7eb93..e3e0cde8afe 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -428,39 +428,43 @@ impl fmt::Display for Backtrace {
     }
 }
 
-type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe;
-
-fn lazy_resolve(mut capture: Capture) -> LazyResolve {
-    move || {
-        // Use the global backtrace lock to synchronize this as it's a
-        // requirement of the `backtrace` crate, and then actually resolve
-        // everything.
-        let _lock = lock();
-        for frame in capture.frames.iter_mut() {
-            let symbols = &mut frame.symbols;
-            let frame = match &frame.frame {
-                RawFrame::Actual(frame) => frame,
-                #[cfg(test)]
-                RawFrame::Fake => unimplemented!(),
-            };
-            unsafe {
-                backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
-                    symbols.push(BacktraceSymbol {
-                        name: symbol.name().map(|m| m.as_bytes().to_vec()),
-                        filename: symbol.filename_raw().map(|b| match b {
-                            BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
-                            BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
-                        }),
-                        lineno: symbol.lineno(),
-                        colno: symbol.colno(),
+mod helper {
+    use super::*;
+    pub(super) type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe;
+
+    pub(super) fn lazy_resolve(mut capture: Capture) -> LazyResolve {
+        move || {
+            // Use the global backtrace lock to synchronize this as it's a
+            // requirement of the `backtrace` crate, and then actually resolve
+            // everything.
+            let _lock = lock();
+            for frame in capture.frames.iter_mut() {
+                let symbols = &mut frame.symbols;
+                let frame = match &frame.frame {
+                    RawFrame::Actual(frame) => frame,
+                    #[cfg(test)]
+                    RawFrame::Fake => unimplemented!(),
+                };
+                unsafe {
+                    backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
+                        symbols.push(BacktraceSymbol {
+                            name: symbol.name().map(|m| m.as_bytes().to_vec()),
+                            filename: symbol.filename_raw().map(|b| match b {
+                                BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
+                                BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
+                            }),
+                            lineno: symbol.lineno(),
+                            colno: symbol.colno(),
+                        });
                     });
-                });
+                }
             }
-        }
 
-        capture
+            capture
+        }
     }
 }
+use helper::*;
 
 impl RawFrame {
     fn ip(&self) -> *mut c_void {
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index b7b817d97c9..2f35e721610 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -323,8 +323,10 @@ impl Error for VarError {
 /// This function is also always safe to call on Windows, in single-threaded
 /// and multi-threaded programs.
 ///
-/// In multi-threaded programs on other operating systems, we strongly suggest
-/// not using `set_var` or `remove_var` at all. The exact requirement is: you
+/// In multi-threaded programs on other operating systems, the only safe option is
+/// to not use `set_var` or `remove_var` at all.
+///
+/// The exact requirement is: you
 /// must ensure that there are no other threads concurrently writing or
 /// *reading*(!) the environment through functions or global variables other
 /// than the ones in this module. The problem is that these operating systems
@@ -382,8 +384,10 @@ unsafe fn _set_var(key: &OsStr, value: &OsStr) {
 /// This function is also always safe to call on Windows, in single-threaded
 /// and multi-threaded programs.
 ///
-/// In multi-threaded programs on other operating systems, we strongly suggest
-/// not using `set_var` or `remove_var` at all. The exact requirement is: you
+/// In multi-threaded programs on other operating systems, the only safe option is
+/// to not use `set_var` or `remove_var` at all.
+///
+/// The exact requirement is: you
 /// must ensure that there are no other threads concurrently writing or
 /// *reading*(!) the environment through functions or global variables other
 /// than the ones in this module. The problem is that these operating systems
diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs
index c29dd62bc06..d53674d3c5f 100644
--- a/library/std/src/os/linux/raw.rs
+++ b/library/std/src/os/linux/raw.rs
@@ -244,7 +244,11 @@ mod arch {
     pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};
 }
 
-#[cfg(target_arch = "aarch64")]
+#[cfg(any(
+    target_arch = "aarch64",
+    // Arm64EC is Windows-only, but docs are always build as Linux, so re-use AArch64 for Arm64EC.
+    all(doc, target_arch = "arm64ec")
+))]
 mod arch {
     use crate::os::raw::{c_int, c_long};
 
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index e63b46ab705..c5d1a893ee8 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -4,11 +4,212 @@
 
 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_as_str() {
+            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 +244,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 +254,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 5699937cdb4..8fd8134c111 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/std/src/sys/pal/windows/rand.rs b/library/std/src/sys/pal/windows/rand.rs
index e427546222a..09f527a09bf 100644
--- a/library/std/src/sys/pal/windows/rand.rs
+++ b/library/std/src/sys/pal/windows/rand.rs
@@ -1,6 +1,6 @@
+use core::{mem, ptr};
+
 use crate::sys::c;
-use core::mem;
-use core::ptr;
 
 #[cfg(not(target_vendor = "win7"))]
 #[inline]
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index bb1e505285b..84128a4b595 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -477,6 +477,9 @@ impl Wtf8Buf {
     /// Part of a hack to make PathBuf::push/pop more efficient.
     #[inline]
     pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {
+        // FIXME: this function should not even exist, as it implies violating Wtf8Buf invariants
+        // For now, simply assume that is about to happen.
+        self.is_known_utf8 = false;
         &mut self.bytes
     }
 }