Split core's PanicInfo and std's PanicInfo. · model-checking/verify-rust-std@702405e

@@ -4,11 +4,162 @@

4455

use crate::any::Any;

66

use crate::collections;

7+

use crate::fmt;

78

use crate::panicking;

89

use crate::sync::atomic::{AtomicU8, Ordering};

910

use crate::sync::{Condvar, Mutex, RwLock};

1011

use 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};

43194

pub 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")]

49200

pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};