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