core/
panic.rs

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"]
51pub macro panic_2021 {
52    () => (
53        $crate::panicking::panic("explicit panic")
54    ),
55    // Special-case the single-argument case for const_panic.
56    ("{}", $arg:expr $(,)?) => ({
57        $crate::panicking::panic_display(&$arg);
58    }),
59    ($($t:tt)+) => ({
60        // Semicolon to prevent temporaries inside the formatting machinery from
61        // being considered alive in the caller after the panic_fmt call.
62        $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
63    }),
64}
65
66#[doc(hidden)]
67#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
68#[allow_internal_unstable(panic_internals)]
69#[rustc_diagnostic_item = "unreachable_2015_macro"]
70#[rustc_macro_transparency = "semitransparent"]
71pub macro unreachable_2015 {
72    () => (
73        $crate::panicking::panic("internal error: entered unreachable code")
74    ),
75    // Use of `unreachable_display` for non_fmt_panic lint.
76    // NOTE: the message ("internal error ...") is embedded directly in unreachable_display
77    ($msg:expr $(,)?) => ({
78        $crate::panicking::unreachable_display(&$msg);
79    }),
80    ($fmt:expr, $($arg:tt)*) => (
81        $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
82    ),
83}
84
85#[doc(hidden)]
86#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
87#[allow_internal_unstable(panic_internals)]
88#[rustc_macro_transparency = "semitransparent"]
89pub macro unreachable_2021 {
90    () => (
91        $crate::panicking::panic("internal error: entered unreachable code")
92    ),
93    ($($t:tt)+) => (
94        $crate::panic!("internal error: entered unreachable code: {}", $crate::format_args!($($t)+))
95    ),
96}
97
98/// Invokes a closure, aborting if the closure unwinds.
99///
100/// When compiled with aborting panics, this function is effectively a no-op.
101/// With unwinding panics, an unwind results in another call into the panic
102/// hook followed by a process abort.
103///
104/// # Notes
105///
106/// Instead of using this function, code should attempt to support unwinding.
107/// Implementing [`Drop`] allows you to restore invariants uniformly in both
108/// return and unwind paths.
109///
110/// If an unwind can lead to logical issues but not soundness issues, you
111/// should allow the unwind. Opting out of [`UnwindSafe`] indicates to your
112/// consumers that they need to consider correctness in the face of unwinds.
113///
114/// If an unwind would be unsound, then this function should be used in order
115/// to prevent unwinds. However, note that `extern "C" fn` will automatically
116/// convert unwinds to aborts, so using this function isn't necessary for FFI.
117#[unstable(feature = "abort_unwind", issue = "130338")]
118#[rustc_nounwind]
119pub fn abort_unwind<F: FnOnce() -> R, R>(f: F) -> R {
120    f()
121}
122
123/// An internal trait used by std to pass data from std to `panic_unwind` and
124/// other panic runtimes. Not intended to be stabilized any time soon, do not
125/// use.
126#[unstable(feature = "std_internals", issue = "none")]
127#[doc(hidden)]
128pub unsafe trait PanicPayload: crate::fmt::Display {
129    /// Take full ownership of the contents.
130    /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core.
131    ///
132    /// After this method got called, only some dummy default value is left in `self`.
133    /// Calling this method twice, or calling `get` after calling this method, is an error.
134    ///
135    /// The argument is borrowed because the panic runtime (`__rust_start_panic`) only
136    /// gets a borrowed `dyn PanicPayload`.
137    fn take_box(&mut self) -> *mut (dyn Any + Send);
138
139    /// Just borrow the contents.
140    fn get(&mut self) -> &(dyn Any + Send);
141
142    /// Tries to borrow the contents as `&str`, if possible without doing any allocations.
143    fn as_str(&mut self) -> Option<&str> {
144        None
145    }
146}
147
148/// Helper macro for panicking in a `const fn`.
149/// Invoke as:
150/// ```rust,ignore (just an example)
151/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar);
152/// ```
153/// where the first message will be printed in const-eval,
154/// and the second message will be printed at runtime.
155// All uses of this macro are FIXME(const-hack).
156#[unstable(feature = "panic_internals", issue = "none")]
157#[doc(hidden)]
158pub macro const_panic {
159    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{
160        // Wrap call to `const_eval_select` in a function so that we can
161        // add the `rustc_allow_const_fn_unstable`. This is okay to do
162        // because both variants will panic, just with different messages.
163        #[rustc_allow_const_fn_unstable(const_eval_select)]
164        #[inline(always)] // inline the wrapper
165        #[track_caller]
166        const fn do_panic($($arg: $ty),*) -> ! {
167            $crate::intrinsics::const_eval_select!(
168                @capture { $($arg: $ty = $arg),* } -> !:
169                #[noinline]
170                if const #[track_caller] #[inline] { // Inline this, to prevent codegen
171                    $crate::panic!($const_msg)
172                } else #[track_caller] { // Do not inline this, it makes perf worse
173                    $crate::panic!($runtime_msg)
174                }
175            )
176        }
177
178        do_panic($($val),*)
179    }},
180    // We support leaving away the `val` expressions for *all* arguments
181    // (but not for *some* arguments, that's too tricky).
182    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => {
183        $crate::panic::const_panic!(
184            $const_msg,
185            $runtime_msg,
186            $($arg: $ty = $arg),*
187        )
188    },
189}
190
191/// A version of `assert` that prints a non-formatting message in const contexts.
192///
193/// See [`const_panic!`].
194#[unstable(feature = "panic_internals", issue = "none")]
195#[doc(hidden)]
196pub macro const_assert {
197    ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{
198        if !$crate::intrinsics::likely($condition) {
199            $crate::panic::const_panic!($const_msg, $runtime_msg, $($arg)*)
200        }
201    }}
202}