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: &'a Location<'a>,
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: &'a Location<'a>,
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    /// # Examples
72    ///
73    /// ```should_panic
74    /// use std::panic;
75    ///
76    /// panic::set_hook(Box::new(|panic_info| {
77    ///     if let Some(location) = panic_info.location() {
78    ///         println!("panic occurred in file '{}' at line {}",
79    ///             location.file(),
80    ///             location.line(),
81    ///         );
82    ///     } else {
83    ///         println!("panic occurred but can't get location information...");
84    ///     }
85    /// }));
86    ///
87    /// panic!("Normal panic");
88    /// ```
89    #[must_use]
90    #[stable(feature = "panic_hooks", since = "1.10.0")]
91    pub fn location(&self) -> Option<&Location<'_>> {
92        // NOTE: If this is changed to sometimes return None,
93        // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt.
94        Some(&self.location)
95    }
96
97    /// Returns the payload associated with the panic.
98    ///
99    /// On this type, `core::panic::PanicInfo`, this method never returns anything useful.
100    /// It only exists because of compatibility with [`std::panic::PanicHookInfo`],
101    /// which used to be the same type.
102    ///
103    /// See [`std::panic::PanicHookInfo::payload`].
104    ///
105    /// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
106    /// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload
107    #[deprecated(since = "1.81.0", note = "this never returns anything useful")]
108    #[stable(feature = "panic_hooks", since = "1.10.0")]
109    #[allow(deprecated, deprecated_in_future)]
110    pub fn payload(&self) -> &(dyn crate::any::Any + Send) {
111        struct NoPayload;
112        &NoPayload
113    }
114
115    /// Returns whether the panic handler is allowed to unwind the stack from
116    /// the point where the panic occurred.
117    ///
118    /// This is true for most kinds of panics with the exception of panics
119    /// caused by trying to unwind out of a `Drop` implementation or a function
120    /// whose ABI does not support unwinding.
121    ///
122    /// It is safe for a panic handler to unwind even when this function returns
123    /// false, however this will simply cause the panic handler to be called
124    /// again.
125    #[must_use]
126    #[unstable(feature = "panic_can_unwind", issue = "92988")]
127    pub fn can_unwind(&self) -> bool {
128        self.can_unwind
129    }
130
131    #[unstable(
132        feature = "panic_internals",
133        reason = "internal details of the implementation of the `panic!` and related macros",
134        issue = "none"
135    )]
136    #[doc(hidden)]
137    #[inline]
138    pub fn force_no_backtrace(&self) -> bool {
139        self.force_no_backtrace
140    }
141}
142
143#[stable(feature = "panic_hook_display", since = "1.26.0")]
144impl Display for PanicInfo<'_> {
145    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
146        formatter.write_str("panicked at ")?;
147        self.location.fmt(formatter)?;
148        formatter.write_str(":\n")?;
149        formatter.write_fmt(*self.message)?;
150        Ok(())
151    }
152}
153
154impl<'a> PanicMessage<'a> {
155    /// Gets the formatted message, if it has no arguments to be formatted at runtime.
156    ///
157    /// This can be used to avoid allocations in some cases.
158    ///
159    /// # Guarantees
160    ///
161    /// For `panic!("just a literal")`, this function is guaranteed to
162    /// return `Some("just a literal")`.
163    ///
164    /// For most cases with placeholders, this function will return `None`.
165    ///
166    /// See [`fmt::Arguments::as_str`] for details.
167    #[stable(feature = "panic_info_message", since = "1.81.0")]
168    #[rustc_const_stable(feature = "const_arguments_as_str", since = "1.84.0")]
169    #[must_use]
170    #[inline]
171    pub const fn as_str(&self) -> Option<&'static str> {
172        self.message.as_str()
173    }
174}
175
176#[stable(feature = "panic_info_message", since = "1.81.0")]
177impl Display for PanicMessage<'_> {
178    #[inline]
179    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
180        formatter.write_fmt(*self.message)
181    }
182}
183
184#[stable(feature = "panic_info_message", since = "1.81.0")]
185impl fmt::Debug for PanicMessage<'_> {
186    #[inline]
187    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
188        formatter.write_fmt(*self.message)
189    }
190}