about summary refs log tree commit diff
path: root/library/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src')
-rw-r--r--library/core/src/error.md5
-rw-r--r--library/core/src/panic.rs7
-rw-r--r--library/core/src/panic/location.rs3
-rw-r--r--library/core/src/panic/panic_info.rs106
-rw-r--r--library/core/src/panicking.rs24
5 files changed, 52 insertions, 93 deletions
diff --git a/library/core/src/error.md b/library/core/src/error.md
index a5deb71e6b8..4b62391cafc 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 8771f40f9b4..b5a0932221a 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 eb27da1724e..8c04994ac0f 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 40326221258..df8f441bf35 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 ca06e059b75..97fb1d6b732 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,