diff options
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/error.md | 5 | ||||
| -rw-r--r-- | library/core/src/panic.rs | 7 | ||||
| -rw-r--r-- | library/core/src/panic/location.rs | 3 | ||||
| -rw-r--r-- | library/core/src/panic/panic_info.rs | 106 | ||||
| -rw-r--r-- | library/core/src/panicking.rs | 24 |
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, |
