3 use crate::panic::Location;
5 /// A struct providing information about a panic.
7 /// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
10 /// [`set_hook`]: ../../std/panic/fn.set_hook.html
17 /// panic::set_hook(Box::new(|panic_info| {
18 /// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
19 /// println!("panic occurred: {s:?}");
21 /// println!("panic occurred");
25 /// panic!("Normal panic");
27 #[lang = "panic_info"]
28 #[stable(feature = "panic_hooks", since = "1.10.0")]
30 pub struct PanicInfo<'a> {
31 payload: &'a (dyn Any + Send),
32 message: Option<&'a fmt::Arguments<'a>>,
33 location: &'a Location<'a>,
37 impl<'a> PanicInfo<'a> {
39 feature = "panic_internals",
40 reason = "internal details of the implementation of the `panic!` and related macros",
45 pub fn internal_constructor(
46 message: Option<&'a fmt::Arguments<'a>>,
47 location: &'a Location<'a>,
51 PanicInfo { location, message, payload: &NoPayload, can_unwind }
55 feature = "panic_internals",
56 reason = "internal details of the implementation of the `panic!` and related macros",
61 pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
65 /// Returns the payload associated with the panic.
67 /// This will commonly, but not always, be a `&'static str` or [`String`].
69 /// [`String`]: ../../std/string/struct.String.html
76 /// panic::set_hook(Box::new(|panic_info| {
77 /// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
78 /// println!("panic occurred: {s:?}");
80 /// println!("panic occurred");
84 /// panic!("Normal panic");
87 #[stable(feature = "panic_hooks", since = "1.10.0")]
88 pub fn payload(&self) -> &(dyn Any + Send) {
92 /// If the `panic!` macro from the `core` crate (not from `std`)
93 /// was used with a formatting string and some additional arguments,
94 /// returns that message ready to be used for example with [`fmt::write`]
96 #[unstable(feature = "panic_info_message", issue = "66745")]
97 pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
101 /// Returns information about the location from which the panic originated,
104 /// This method will currently always return [`Some`], but this may change
105 /// in future versions.
112 /// panic::set_hook(Box::new(|panic_info| {
113 /// if let Some(location) = panic_info.location() {
114 /// println!("panic occurred in file '{}' at line {}",
119 /// println!("panic occurred but can't get location information...");
123 /// panic!("Normal panic");
126 #[stable(feature = "panic_hooks", since = "1.10.0")]
127 pub fn location(&self) -> Option<&Location<'_>> {
128 // NOTE: If this is changed to sometimes return None,
129 // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt.
133 /// Returns whether the panic handler is allowed to unwind the stack from
134 /// the point where the panic occurred.
136 /// This is true for most kinds of panics with the exception of panics
137 /// caused by trying to unwind out of a `Drop` implementation or a function
138 /// whose ABI does not support unwinding.
140 /// It is safe for a panic handler to unwind even when this function returns
141 /// true, however this will simply cause the panic handler to be called
144 #[unstable(feature = "panic_can_unwind", issue = "92988")]
145 pub fn can_unwind(&self) -> bool {
150 #[stable(feature = "panic_hook_display", since = "1.26.0")]
151 impl fmt::Display for PanicInfo<'_> {
152 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
153 formatter.write_str("panicked at ")?;
154 if let Some(message) = self.message {
155 write!(formatter, "'{}', ", message)?
156 } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
157 write!(formatter, "'{}', ", payload)?
159 // NOTE: we cannot use downcast_ref::<String>() here
160 // since String is not available in core!
161 // The payload is a String when `std::panic!` is called with multiple arguments,
162 // but in that case the message is also available.
164 self.location.fmt(formatter)