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}