Skip to main content

core/
panic.rs

1//! Panic support in core.
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};
17
18#[doc(hidden)]
19#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
20#[allow_internal_unstable(panic_internals, const_format_args)]
21#[rustc_diagnostic_item = "core_panic_2015_macro"]
22#[rustc_macro_transparency = "semiopaque"]
23pub macro panic_2015 {
24    () => (
25        $crate::panicking::panic("explicit panic")
26    ),
27    ($msg:literal $(,)?) => (
28        $crate::panicking::panic($msg)
29    ),
30    // Use `panic_str_2015` instead of `panic_display::<&str>` for non_fmt_panic lint.
31    ($msg:expr $(,)?) => ({
32        $crate::panicking::panic_str_2015($msg);
33    }),
34    // Special-case the single-argument case for const_panic.
35    ("{}", $arg:expr $(,)?) => ({
36        $crate::panicking::panic_display(&$arg);
37    }),
38    ($fmt:expr, $($arg:tt)+) => ({
39        // Semicolon to prevent temporaries inside the formatting machinery from
40        // being considered alive in the caller after the panic_fmt call.
41        $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+));
42    }),
43}
44
45#[doc(hidden)]
46#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
47#[allow_internal_unstable(panic_internals, const_format_args)]
48#[rustc_diagnostic_item = "core_panic_2021_macro"]
49#[rustc_macro_transparency = "semiopaque"]
50pub macro panic_2021 {
51    () => (
52        $crate::panicking::panic("explicit panic")
53    ),
54    // Special-case the single-argument case for const_panic.
55    ("{}", $arg:expr $(,)?) => ({
56        $crate::panicking::panic_display(&$arg);
57    }),
58    ($($t:tt)+) => ({
59        // Semicolon to prevent temporaries inside the formatting machinery from
60        // being considered alive in the caller after the panic_fmt call.
61        $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
62    }),
63}
64
65#[doc(hidden)]
66#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
67#[allow_internal_unstable(panic_internals)]
68#[rustc_diagnostic_item = "unreachable_2015_macro"]
69#[rustc_macro_transparency = "semiopaque"]
70pub macro unreachable_2015 {
71    () => (
72        $crate::panicking::panic("internal error: entered unreachable code")
73    ),
74    // Use of `unreachable_display` for non_fmt_panic lint.
75    // NOTE: the message ("internal error ...") is embedded directly in unreachable_display
76    ($msg:expr $(,)?) => ({
77        $crate::panicking::unreachable_display(&$msg);
78    }),
79    ($fmt:expr, $($arg:tt)*) => (
80        $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
81    ),
82}
83
84#[doc(hidden)]
85#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
86#[allow_internal_unstable(panic_internals)]
87#[rustc_macro_transparency = "semiopaque"]
88pub macro unreachable_2021 {
89    () => (
90        $crate::panicking::panic("internal error: entered unreachable code")
91    ),
92    ($($t:tt)+) => (
93        $crate::panic!("internal error: entered unreachable code: {}", $crate::format_args!($($t)+))
94    ),
95}
96
97/// Invokes a closure, aborting if the closure unwinds.
98///
99/// When compiled with aborting panics, this function is effectively a no-op.
100/// With unwinding panics, an unwind results in another call into the panic
101/// hook followed by a process abort.
102///
103/// # Notes
104///
105/// Instead of using this function, code should attempt to support unwinding.
106/// Implementing [`Drop`] allows you to restore invariants uniformly in both
107/// return and unwind paths.
108///
109/// If an unwind can lead to logical issues but not soundness issues, you
110/// should allow the unwind. Opting out of [`UnwindSafe`] indicates to your
111/// consumers that they need to consider correctness in the face of unwinds.
112///
113/// If an unwind would be unsound, then this function should be used in order
114/// to prevent unwinds. However, note that `extern "C" fn` will automatically
115/// convert unwinds to aborts, so using this function isn't necessary for FFI.
116#[unstable(feature = "abort_unwind", issue = "130338")]
117#[rustc_nounwind]
118pub fn abort_on_unwind<F: FnOnce() -> R, R>(f: F) -> R {
119    f()
120}
121
122/// Helper macro for panicking in a `const fn`.
123/// Invoke as:
124/// ```rust,ignore (just an example)
125/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar);
126/// ```
127/// where the first message will be printed in const-eval,
128/// and the second message will be printed at runtime.
129// All uses of this macro are FIXME(const-hack).
130#[unstable(feature = "panic_internals", issue = "none")]
131#[doc(hidden)]
132pub macro const_panic {
133    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{
134        // Wrap call to `const_eval_select` in a function so that we can
135        // add the `rustc_allow_const_fn_unstable`. This is okay to do
136        // because both variants will panic, just with different messages.
137        #[rustc_allow_const_fn_unstable(const_eval_select)]
138        #[inline(always)] // inline the wrapper
139        #[track_caller]
140        const fn do_panic($($arg: $ty),*) -> ! {
141            $crate::intrinsics::const_eval_select!(
142                @capture { $($arg: $ty = $arg),* } -> !:
143                if const #[track_caller] {
144                    $crate::panic!($const_msg)
145                } else #[track_caller] {
146                    $crate::panic!($runtime_msg)
147                }
148            )
149        }
150
151        do_panic($($val),*)
152    }},
153    // We support leaving away the `val` expressions for *all* arguments
154    // (but not for *some* arguments, that's too tricky).
155    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => {
156        $crate::panic::const_panic!(
157            $const_msg,
158            $runtime_msg,
159            $($arg: $ty = $arg),*
160        )
161    },
162}
163
164/// A version of `assert` that prints a non-formatting message in const contexts.
165///
166/// See [`const_panic!`].
167#[unstable(feature = "panic_internals", issue = "none")]
168#[doc(hidden)]
169pub macro const_assert {
170    ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{
171        if !($condition) {
172            $crate::panic::const_panic!($const_msg, $runtime_msg, $($arg)*)
173        }
174    }}
175}