1//! Panic support in the standard library.
2
3#![stable(feature = "core_panic_info", since = "1.41.0")]
4
5mod location;
6mod panic_info;
7mod unwind_safe;
8
9#[stable(feature = "panic_hooks", since = "1.10.0")]
10pub use self::location::Location;
11#[stable(feature = "panic_hooks", since = "1.10.0")]
12pub use self::panic_info::PanicInfo;
13#[stable(feature = "panic_info_message", since = "1.81.0")]
14pub use self::panic_info::PanicMessage;
15#[stable(feature = "catch_unwind", since = "1.9.0")]
16pub use self::unwind_safe::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
17use crate::any::Any;
18
19#[doc(hidden)]
20#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
21#[allow_internal_unstable(panic_internals, const_format_args)]
22#[rustc_diagnostic_item = "core_panic_2015_macro"]
23#[rustc_macro_transparency = "semitransparent"]
24pub macro panic_2015 {
25 () => (
26 $crate::panicking::panic("explicit panic")
27 ),
28 ($msg:literal $(,)?) => (
29 $crate::panicking::panic($msg)
30 ),
31 // Use `panic_str_2015` instead of `panic_display::<&str>` for non_fmt_panic lint.
32 ($msg:expr $(,)?) => ({
33 $crate::panicking::panic_str_2015($msg);
34 }),
35 // Special-case the single-argument case for const_panic.
36 ("{}", $arg:expr $(,)?) => ({
37 $crate::panicking::panic_display(&$arg);
38 }),
39 ($fmt:expr, $($arg:tt)+) => ({
40 // Semicolon to prevent temporaries inside the formatting machinery from
41 // being considered alive in the caller after the panic_fmt call.
42 $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+));
43 }),
44}
45
46#[doc(hidden)]
47#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
48#[allow_internal_unstable(panic_internals, const_format_args)]
49#[rustc_diagnostic_item = "core_panic_2021_macro"]
50#[rustc_macro_transparency = "semitransparent"]
51#[cfg(feature = "panic_immediate_abort")]
52pub macro panic_2021 {
53 () => (
54 $crate::panicking::panic("explicit panic")
55 ),
56 // Special-case the single-argument case for const_panic.
57 ("{}", $arg:expr $(,)?) => ({
58 $crate::panicking::panic_display(&$arg);
59 }),
60 ($($t:tt)+) => ({
61 // Semicolon to prevent temporaries inside the formatting machinery from
62 // being considered alive in the caller after the panic_fmt call.
63 $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
64 }),
65}
66
67#[doc(hidden)]
68#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
69#[allow_internal_unstable(
70 panic_internals,
71 core_intrinsics,
72 const_dispatch,
73 const_eval_select,
74 const_format_args,
75 rustc_attrs
76)]
77#[rustc_diagnostic_item = "core_panic_2021_macro"]
78#[rustc_macro_transparency = "semitransparent"]
79#[cfg(not(feature = "panic_immediate_abort"))]
80pub macro panic_2021 {
81 () => ({
82 // Create a function so that the argument for `track_caller`
83 // can be moved inside if possible.
84 #[cold]
85 #[track_caller]
86 #[inline(never)]
87 const fn panic_cold_explicit() -> ! {
88 $crate::panicking::panic_explicit()
89 }
90 panic_cold_explicit();
91 }),
92 // Special-case the single-argument case for const_panic.
93 ("{}", $arg:expr $(,)?) => ({
94 #[cold]
95 #[track_caller]
96 #[inline(never)]
97 #[rustc_const_panic_str] // enforce a &&str argument in const-check and hook this by const-eval
98 #[rustc_do_not_const_check] // hooked by const-eval
99 const fn panic_cold_display<T: $crate::fmt::Display>(arg: &T) -> ! {
100 $crate::panicking::panic_display(arg)
101 }
102 panic_cold_display(&$arg);
103 }),
104 ($($t:tt)+) => ({
105 // Semicolon to prevent temporaries inside the formatting machinery from
106 // being considered alive in the caller after the panic_fmt call.
107 $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
108 }),
109}
110
111#[doc(hidden)]
112#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
113#[allow_internal_unstable(panic_internals)]
114#[rustc_diagnostic_item = "unreachable_2015_macro"]
115#[rustc_macro_transparency = "semitransparent"]
116pub macro unreachable_2015 {
117 () => (
118 $crate::panicking::panic("internal error: entered unreachable code")
119 ),
120 // Use of `unreachable_display` for non_fmt_panic lint.
121 // NOTE: the message ("internal error ...") is embedded directly in unreachable_display
122 ($msg:expr $(,)?) => ({
123 $crate::panicking::unreachable_display(&$msg);
124 }),
125 ($fmt:expr, $($arg:tt)*) => (
126 $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
127 ),
128}
129
130#[doc(hidden)]
131#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
132#[allow_internal_unstable(panic_internals)]
133#[rustc_macro_transparency = "semitransparent"]
134pub macro unreachable_2021 {
135 () => (
136 $crate::panicking::panic("internal error: entered unreachable code")
137 ),
138 ($($t:tt)+) => (
139 $crate::panic!("internal error: entered unreachable code: {}", $crate::format_args!($($t)+))
140 ),
141}
142
143/// Invokes a closure, aborting if the closure unwinds.
144///
145/// When compiled with aborting panics, this function is effectively a no-op.
146/// With unwinding panics, an unwind results in another call into the panic
147/// hook followed by a process abort.
148///
149/// # Notes
150///
151/// Instead of using this function, code should attempt to support unwinding.
152/// Implementing [`Drop`] allows you to restore invariants uniformly in both
153/// return and unwind paths.
154///
155/// If an unwind can lead to logical issues but not soundness issues, you
156/// should allow the unwind. Opting out of [`UnwindSafe`] indicates to your
157/// consumers that they need to consider correctness in the face of unwinds.
158///
159/// If an unwind would be unsound, then this function should be used in order
160/// to prevent unwinds. However, note that `extern "C" fn` will automatically
161/// convert unwinds to aborts, so using this function isn't necessary for FFI.
162#[unstable(feature = "abort_unwind", issue = "130338")]
163#[rustc_nounwind]
164pub fn abort_unwind<F: FnOnce() -> R, R>(f: F) -> R {
165 f()
166}
167
168/// An internal trait used by std to pass data from std to `panic_unwind` and
169/// other panic runtimes. Not intended to be stabilized any time soon, do not
170/// use.
171#[unstable(feature = "std_internals", issue = "none")]
172#[doc(hidden)]
173pub unsafe trait PanicPayload: crate::fmt::Display {
174 /// Take full ownership of the contents.
175 /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core.
176 ///
177 /// After this method got called, only some dummy default value is left in `self`.
178 /// Calling this method twice, or calling `get` after calling this method, is an error.
179 ///
180 /// The argument is borrowed because the panic runtime (`__rust_start_panic`) only
181 /// gets a borrowed `dyn PanicPayload`.
182 fn take_box(&mut self) -> *mut (dyn Any + Send);
183
184 /// Just borrow the contents.
185 fn get(&mut self) -> &(dyn Any + Send);
186
187 /// Tries to borrow the contents as `&str`, if possible without doing any allocations.
188 fn as_str(&mut self) -> Option<&str> {
189 None
190 }
191}
192
193/// Helper macro for panicking in a `const fn`.
194/// Invoke as:
195/// ```rust,ignore (just an example)
196/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar);
197/// ```
198/// where the first message will be printed in const-eval,
199/// and the second message will be printed at runtime.
200// All uses of this macro are FIXME(const-hack).
201#[unstable(feature = "panic_internals", issue = "none")]
202#[doc(hidden)]
203pub macro const_panic {
204 ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{
205 // Wrap call to `const_eval_select` in a function so that we can
206 // add the `rustc_allow_const_fn_unstable`. This is okay to do
207 // because both variants will panic, just with different messages.
208 #[rustc_allow_const_fn_unstable(const_eval_select)]
209 #[inline(always)] // inline the wrapper
210 #[track_caller]
211 const fn do_panic($($arg: $ty),*) -> ! {
212 $crate::intrinsics::const_eval_select!(
213 @capture { $($arg: $ty = $arg),* } -> !:
214 #[noinline]
215 if const #[track_caller] #[inline] { // Inline this, to prevent codegen
216 $crate::panic!($const_msg)
217 } else #[track_caller] { // Do not inline this, it makes perf worse
218 $crate::panic!($runtime_msg)
219 }
220 )
221 }
222
223 do_panic($($val),*)
224 }},
225 // We support leaving away the `val` expressions for *all* arguments
226 // (but not for *some* arguments, that's too tricky).
227 ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => {
228 $crate::panic::const_panic!(
229 $const_msg,
230 $runtime_msg,
231 $($arg: $ty = $arg),*
232 )
233 },
234}
235
236/// A version of `assert` that prints a non-formatting message in const contexts.
237///
238/// See [`const_panic!`].
239#[unstable(feature = "panic_internals", issue = "none")]
240#[doc(hidden)]
241pub macro const_assert {
242 ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{
243 if !$crate::intrinsics::likely($condition) {
244 $crate::panic::const_panic!($const_msg, $runtime_msg, $($arg)*)
245 }
246 }}
247}
248

Provided by KDAB

Privacy Policy