This updates the standard library's documentation to use the new syntax. The documentation is worthwhile to update as it should be more idiomatic (particularly for features like this, which are nice for users to get acquainted with). The general codebase is likely more hassle than benefit to update: it'll hurt git blame, and generally updates can be done by folks updating the code if (and when) that makes things more readable with the new format. A few places in the compiler and library code are updated (mostly just due to already having been done when this commit was first authored).
166 lines
5.2 KiB
Rust
166 lines
5.2 KiB
Rust
use crate::any::Any;
|
|
use crate::fmt;
|
|
use crate::panic::Location;
|
|
|
|
/// A struct providing information about a panic.
|
|
///
|
|
/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
|
|
/// function.
|
|
///
|
|
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```should_panic
|
|
/// use std::panic;
|
|
///
|
|
/// panic::set_hook(Box::new(|panic_info| {
|
|
/// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
|
/// println!("panic occurred: {s:?}");
|
|
/// } else {
|
|
/// println!("panic occurred");
|
|
/// }
|
|
/// }));
|
|
///
|
|
/// panic!("Normal panic");
|
|
/// ```
|
|
#[lang = "panic_info"]
|
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
|
#[derive(Debug)]
|
|
pub struct PanicInfo<'a> {
|
|
payload: &'a (dyn Any + Send),
|
|
message: Option<&'a fmt::Arguments<'a>>,
|
|
location: &'a Location<'a>,
|
|
can_unwind: bool,
|
|
}
|
|
|
|
impl<'a> PanicInfo<'a> {
|
|
#[unstable(
|
|
feature = "panic_internals",
|
|
reason = "internal details of the implementation of the `panic!` and related macros",
|
|
issue = "none"
|
|
)]
|
|
#[doc(hidden)]
|
|
#[inline]
|
|
pub fn internal_constructor(
|
|
message: Option<&'a fmt::Arguments<'a>>,
|
|
location: &'a Location<'a>,
|
|
can_unwind: bool,
|
|
) -> Self {
|
|
struct NoPayload;
|
|
PanicInfo { location, message, payload: &NoPayload, can_unwind }
|
|
}
|
|
|
|
#[unstable(
|
|
feature = "panic_internals",
|
|
reason = "internal details of the implementation of the `panic!` and related macros",
|
|
issue = "none"
|
|
)]
|
|
#[doc(hidden)]
|
|
#[inline]
|
|
pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
|
|
self.payload = info;
|
|
}
|
|
|
|
/// Returns the payload associated with the panic.
|
|
///
|
|
/// This will commonly, but not always, be a `&'static str` or [`String`].
|
|
///
|
|
/// [`String`]: ../../std/string/struct.String.html
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```should_panic
|
|
/// use std::panic;
|
|
///
|
|
/// panic::set_hook(Box::new(|panic_info| {
|
|
/// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
|
/// println!("panic occurred: {s:?}");
|
|
/// } else {
|
|
/// println!("panic occurred");
|
|
/// }
|
|
/// }));
|
|
///
|
|
/// panic!("Normal panic");
|
|
/// ```
|
|
#[must_use]
|
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
|
pub fn payload(&self) -> &(dyn Any + Send) {
|
|
self.payload
|
|
}
|
|
|
|
/// If the `panic!` macro from the `core` crate (not from `std`)
|
|
/// was used with a formatting string and some additional arguments,
|
|
/// returns that message ready to be used for example with [`fmt::write`]
|
|
#[must_use]
|
|
#[unstable(feature = "panic_info_message", issue = "66745")]
|
|
pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
|
|
self.message
|
|
}
|
|
|
|
/// Returns information about the location from which the panic originated,
|
|
/// if available.
|
|
///
|
|
/// This method will currently always return [`Some`], but this may change
|
|
/// in future versions.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```should_panic
|
|
/// use std::panic;
|
|
///
|
|
/// panic::set_hook(Box::new(|panic_info| {
|
|
/// if let Some(location) = panic_info.location() {
|
|
/// println!("panic occurred in file '{}' at line {}",
|
|
/// location.file(),
|
|
/// location.line(),
|
|
/// );
|
|
/// } else {
|
|
/// println!("panic occurred but can't get location information...");
|
|
/// }
|
|
/// }));
|
|
///
|
|
/// panic!("Normal panic");
|
|
/// ```
|
|
#[must_use]
|
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
|
pub fn location(&self) -> Option<&Location<'_>> {
|
|
// NOTE: If this is changed to sometimes return None,
|
|
// deal with that case in std::panicking::default_hook and core::panicking::panic_fmt.
|
|
Some(&self.location)
|
|
}
|
|
|
|
/// Returns whether the panic handler is allowed to unwind the stack from
|
|
/// the point where the panic occurred.
|
|
///
|
|
/// This is true for most kinds of panics with the exception of panics
|
|
/// caused by trying to unwind out of a `Drop` implementation or a function
|
|
/// whose ABI does not support unwinding.
|
|
///
|
|
/// It is safe for a panic handler to unwind even when this function returns
|
|
/// true, however this will simply cause the panic handler to be called
|
|
/// again.
|
|
#[must_use]
|
|
#[unstable(feature = "panic_can_unwind", issue = "92988")]
|
|
pub fn can_unwind(&self) -> bool {
|
|
self.can_unwind
|
|
}
|
|
}
|
|
|
|
#[stable(feature = "panic_hook_display", since = "1.26.0")]
|
|
impl fmt::Display for PanicInfo<'_> {
|
|
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
formatter.write_str("panicked at ")?;
|
|
if let Some(message) = self.message {
|
|
write!(formatter, "'{}', ", message)?
|
|
} else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
|
|
write!(formatter, "'{}', ", payload)?
|
|
}
|
|
// NOTE: we cannot use downcast_ref::<String>() here
|
|
// since String is not available in libcore!
|
|
// The payload is a String when `std::panic!` is called with multiple arguments,
|
|
// but in that case the message is also available.
|
|
|
|
self.location.fmt(formatter)
|
|
}
|
|
}
|