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