Skip to main content

core/panic/
panic_info.rs

1use crate::fmt::{self, Display};
2use crate::panic::Location;
3
4/// A struct providing information about a panic.
5///
6/// A `PanicInfo` structure is passed to the panic handler defined by `#[panic_handler]`.
7///
8/// For the type used by the panic hook mechanism in `std`, see [`std::panic::PanicHookInfo`].
9///
10/// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
11#[lang = "panic_info"]
12#[stable(feature = "panic_hooks", since = "1.10.0")]
13#[derive(Debug)]
14pub struct PanicInfo<'a> {
15    message: &'a fmt::Arguments<'a>,
16    location: &'static Location<'static>,
17    can_unwind: bool,
18    force_no_backtrace: bool,
19}
20
21/// A message that was given to the `panic!()` macro.
22///
23/// The [`Display`] implementation of this type will format the message with the arguments
24/// that were given to the `panic!()` macro.
25///
26/// See [`PanicInfo::message`].
27#[stable(feature = "panic_info_message", since = "1.81.0")]
28pub struct PanicMessage<'a> {
29    message: &'a fmt::Arguments<'a>,
30}
31
32impl<'a> PanicInfo<'a> {
33    #[inline]
34    pub(crate) fn new(
35        message: &'a fmt::Arguments<'a>,
36        location: &'static Location<'static>,
37        can_unwind: bool,
38        force_no_backtrace: bool,
39    ) -> Self {
40        PanicInfo { location, message, can_unwind, force_no_backtrace }
41    }
42
43    /// The message that was given to the `panic!` macro.
44    ///
45    /// # Example
46    ///
47    /// The type returned by this method implements `Display`, so it can
48    /// be passed directly to [`write!()`] and similar macros.
49    ///
50    /// [`write!()`]: core::write
51    ///
52    /// ```ignore (no_std)
53    /// #[panic_handler]
54    /// fn panic_handler(panic_info: &PanicInfo<'_>) -> ! {
55    ///     write!(DEBUG_OUTPUT, "panicked: {}", panic_info.message());
56    ///     loop {}
57    /// }
58    /// ```
59    #[must_use]
60    #[stable(feature = "panic_info_message", since = "1.81.0")]
61    pub fn message(&self) -> PanicMessage<'_> {
62        PanicMessage { message: self.message }
63    }
64
65    /// Returns information about the location from which the panic originated,
66    /// if available.
67    ///
68    /// This method will currently always return [`Some`], but this may change
69    /// in future versions.
70    ///
71    /// # Example
72    ///
73    /// ```ignore (no_std)
74    /// #[panic_handler]
75    /// fn panic_handler(panic_info: &PanicInfo<'_>) -> ! {
76    ///     if let Some(location) = panic_info.location() {
77    ///         write!(DEBUG_OUTPUT, "panicked at {}", location);
78    ///     } else {
79    ///         write!(DEBUG_OUTPUT, "panicked at unknown location");
80    ///     }
81    ///     loop {}
82    /// }
83    /// ```
84    #[must_use]
85    #[stable(feature = "panic_hooks", since = "1.10.0")]
86    pub fn location(&self) -> Option<&'static Location<'static>> {
87        // NOTE: If this is changed to sometimes return None,
88        // deal with that case in std::panicking::panic_handler and core::panicking::panic_fmt.
89        Some(self.location)
90    }
91
92    /// Returns the payload associated with the panic.
93    ///
94    /// On this type, `core::panic::PanicInfo`, this method never returns anything useful.
95    /// It only exists because of compatibility with [`std::panic::PanicHookInfo`],
96    /// which used to be the same type.
97    ///
98    /// See [`std::panic::PanicHookInfo::payload`].
99    ///
100    /// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
101    /// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload
102    #[deprecated(since = "1.81.0", note = "this never returns anything useful")]
103    #[stable(feature = "panic_hooks", since = "1.10.0")]
104    #[allow(deprecated)]
105    pub fn payload(&self) -> &(dyn crate::any::Any + Send) {
106        struct NoPayload;
107        &NoPayload
108    }
109
110    /// Returns whether the panic handler is allowed to unwind the stack from
111    /// the point where the panic occurred.
112    ///
113    /// This is true for most kinds of panics with the exception of panics
114    /// caused by trying to unwind out of a `Drop` implementation or a function
115    /// whose ABI does not support unwinding.
116    ///
117    /// It is safe for a panic handler to unwind even when this function returns
118    /// false, however this will simply cause the panic handler to be called
119    /// again.
120    #[must_use]
121    #[unstable(feature = "panic_can_unwind", issue = "92988")]
122    pub fn can_unwind(&self) -> bool {
123        self.can_unwind
124    }
125
126    #[unstable(
127        feature = "panic_internals",
128        reason = "internal details of the implementation of the `panic!` and related macros",
129        issue = "none"
130    )]
131    #[doc(hidden)]
132    #[inline]
133    pub fn force_no_backtrace(&self) -> bool {
134        self.force_no_backtrace
135    }
136}
137
138#[stable(feature = "panic_hook_display", since = "1.26.0")]
139impl Display for PanicInfo<'_> {
140    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
141        formatter.write_str("panicked at ")?;
142        self.location.fmt(formatter)?;
143        formatter.write_str(":\n")?;
144        formatter.write_fmt(*self.message)?;
145        Ok(())
146    }
147}
148
149impl<'a> PanicMessage<'a> {
150    /// Gets the formatted message, if it has no arguments to be formatted at runtime.
151    ///
152    /// This can be used to avoid allocations in some cases.
153    ///
154    /// # Guarantees
155    ///
156    /// For `panic!("just a literal")`, this function is guaranteed to
157    /// return `Some("just a literal")`.
158    ///
159    /// For most cases with placeholders, this function will return `None`.
160    ///
161    /// See [`fmt::Arguments::as_str`] for details.
162    #[stable(feature = "panic_info_message", since = "1.81.0")]
163    #[rustc_const_stable(feature = "const_arguments_as_str", since = "1.84.0")]
164    #[must_use]
165    #[inline]
166    pub const fn as_str(&self) -> Option<&'static str> {
167        self.message.as_str()
168    }
169}
170
171#[stable(feature = "panic_info_message", since = "1.81.0")]
172impl Display for PanicMessage<'_> {
173    #[inline]
174    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
175        formatter.write_fmt(*self.message)
176    }
177}
178
179#[stable(feature = "panic_info_message", since = "1.81.0")]
180impl fmt::Debug for PanicMessage<'_> {
181    #[inline]
182    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
183        formatter.write_fmt(*self.message)
184    }
185}