summaryrefslogtreecommitdiffstats
path: root/library/core/src/panic/panic_info.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /library/core/src/panic/panic_info.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/src/panic/panic_info.rs')
-rw-r--r--library/core/src/panic/panic_info.rs166
1 files changed, 166 insertions, 0 deletions
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
new file mode 100644
index 000000000..1923155eb
--- /dev/null
+++ b/library/core/src/panic/panic_info.rs
@@ -0,0 +1,166 @@
+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.
+///
+/// [`set_hook`]: ../../std/panic/fn.set_hook.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");
+/// ```
+#[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>>,
+ location: &'a Location<'a>,
+ can_unwind: 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>>,
+ location: &'a Location<'a>,
+ can_unwind: bool,
+ ) -> Self {
+ struct NoPayload;
+ PanicInfo { location, message, payload: &NoPayload, 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 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
+ }
+
+ /// If the `panic!` macro from the `core` crate (not from `std`)
+ /// was used with a formatting string and some additional arguments,
+ /// 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<'_>> {
+ self.message
+ }
+
+ /// 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]
+ #[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
+ /// true, however this will simply cause the panic handler to be called
+ /// again.
+ #[must_use]
+ #[unstable(feature = "panic_can_unwind", issue = "92988")]
+ pub fn can_unwind(&self) -> bool {
+ self.can_unwind
+ }
+}
+
+#[stable(feature = "panic_hook_display", since = "1.26.0")]
+impl fmt::Display for PanicInfo<'_> {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("panicked at ")?;
+ if let Some(message) = self.message {
+ write!(formatter, "'{}', ", message)?
+ } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
+ write!(formatter, "'{}', ", payload)?
+ }
+ // NOTE: we cannot use downcast_ref::<String>() here
+ // since String is not available in libcore!
+ // The payload is a String when `std::panic!` is called with multiple arguments,
+ // but in that case the message is also available.
+
+ self.location.fmt(formatter)
+ }
+}