Split core's PanicInfo and std's PanicInfo. · model-checking/verify-rust-std@702405e
@@ -4,11 +4,162 @@
4455use crate::any::Any;
66use crate::collections;
7+use crate::fmt;
78use crate::panicking;
89use crate::sync::atomic::{AtomicU8, Ordering};
910use crate::sync::{Condvar, Mutex, RwLock};
1011use crate::thread::Result;
111213+/// A struct providing information about a panic.
14+///
15+/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
16+/// function.
17+///
18+/// [`set_hook`]: ../../std/panic/fn.set_hook.html
19+///
20+/// # Examples
21+///
22+/// ```should_panic
23+/// use std::panic;
24+///
25+/// panic::set_hook(Box::new(|panic_info| {
26+/// println!("panic occurred: {panic_info}");
27+/// }));
28+///
29+/// panic!("critical system failure");
30+/// ```
31+#[stable(feature = "panic_hooks", since = "1.10.0")]
32+#[derive(Debug)]
33+pub struct PanicInfo<'a> {
34+payload: &'a (dyn Any + Send),
35+location: &'a Location<'a>,
36+can_unwind: bool,
37+force_no_backtrace: bool,
38+}
39+40+impl<'a> PanicInfo<'a> {
41+#[unstable(feature = "panic_internals", issue = "none")]
42+#[doc(hidden)]
43+#[inline]
44+pub fn internal_constructor(
45+location: &'a Location<'a>,
46+can_unwind: bool,
47+force_no_backtrace: bool,
48+) -> Self {
49+struct NoPayload;
50+PanicInfo { payload: &NoPayload, location, can_unwind, force_no_backtrace }
51+}
52+53+#[unstable(feature = "panic_internals", issue = "none")]
54+#[doc(hidden)]
55+#[inline]
56+pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
57+self.payload = info;
58+}
59+60+/// Returns the payload associated with the panic.
61+ ///
62+ /// This will commonly, but not always, be a `&'static str` or [`String`].
63+ ///
64+ /// [`String`]: ../../std/string/struct.String.html
65+ ///
66+ /// # Examples
67+ ///
68+ /// ```should_panic
69+ /// use std::panic;
70+ ///
71+ /// panic::set_hook(Box::new(|panic_info| {
72+ /// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
73+ /// println!("panic occurred: {s:?}");
74+ /// } else {
75+ /// println!("panic occurred");
76+ /// }
77+ /// }));
78+ ///
79+ /// panic!("Normal panic");
80+ /// ```
81+ #[must_use]
82+#[stable(feature = "panic_hooks", since = "1.10.0")]
83+pub fn payload(&self) -> &(dyn Any + Send) {
84+self.payload
85+}
86+87+/// Returns information about the location from which the panic originated,
88+ /// if available.
89+ ///
90+ /// This method will currently always return [`Some`], but this may change
91+ /// in future versions.
92+ ///
93+ /// # Examples
94+ ///
95+ /// ```should_panic
96+ /// use std::panic;
97+ ///
98+ /// panic::set_hook(Box::new(|panic_info| {
99+ /// if let Some(location) = panic_info.location() {
100+ /// println!("panic occurred in file '{}' at line {}",
101+ /// location.file(),
102+ /// location.line(),
103+ /// );
104+ /// } else {
105+ /// println!("panic occurred but can't get location information...");
106+ /// }
107+ /// }));
108+ ///
109+ /// panic!("Normal panic");
110+ /// ```
111+ #[must_use]
112+#[stable(feature = "panic_hooks", since = "1.10.0")]
113+pub fn location(&self) -> Option<&Location<'_>> {
114+// NOTE: If this is changed to sometimes return None,
115+// deal with that case in std::panicking::default_hook and core::panicking::panic_fmt.
116+Some(&self.location)
117+}
118+119+/// Returns whether the panic handler is allowed to unwind the stack from
120+ /// the point where the panic occurred.
121+ ///
122+ /// This is true for most kinds of panics with the exception of panics
123+ /// caused by trying to unwind out of a `Drop` implementation or a function
124+ /// whose ABI does not support unwinding.
125+ ///
126+ /// It is safe for a panic handler to unwind even when this function returns
127+ /// false, however this will simply cause the panic handler to be called
128+ /// again.
129+ #[must_use]
130+#[unstable(feature = "panic_can_unwind", issue = "92988")]
131+pub fn can_unwind(&self) -> bool {
132+self.can_unwind
133+}
134+135+#[unstable(
136+ feature = "panic_internals",
137+ reason = "internal details of the implementation of the `panic!` and related macros",
138+ issue = "none"
139+ )]
140+#[doc(hidden)]
141+#[inline]
142+pub fn force_no_backtrace(&self) -> bool {
143+self.force_no_backtrace
144+}
145+}
146+147+#[stable(feature = "panic_hook_display", since = "1.26.0")]
148+impl fmt::Display for PanicInfo<'_> {
149+fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
150+ formatter.write_str("panicked at ")?;
151+self.location.fmt(formatter)?;
152+if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
153+ formatter.write_str(":\n")?;
154+ formatter.write_str(payload)?;
155+} else if let Some(payload) = self.payload.downcast_ref::<String>() {
156+ formatter.write_str(":\n")?;
157+ formatter.write_str(payload)?;
158+}
159+Ok(())
160+}
161+}
162+12163#[doc(hidden)]
13164#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
14165#[allow_internal_unstable(libstd_sys_internals, const_format_args, panic_internals, rt)]
@@ -43,7 +194,7 @@ pub use crate::panicking::{set_hook, take_hook};
43194pub use crate::panicking::update_hook;
4419545196#[stable(feature = "panic_hooks", since = "1.10.0")]
46-pub use core::panic::{Location, PanicInfo};
197+pub use core::panic::Location;
4719848199#[stable(feature = "catch_unwind", since = "1.9.0")]
49200pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};