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}