| //! Panic support in core. | |
| #![stable(feature = "core_panic_info", since = "1.41.0")] | |
| mod location; | |
| mod panic_info; | |
| mod unwind_safe; | |
| #[stable(feature = "panic_hooks", since = "1.10.0")] | |
| pub use self::location::Location; | |
| #[stable(feature = "panic_hooks", since = "1.10.0")] | |
| pub use self::panic_info::PanicInfo; | |
| #[stable(feature = "panic_info_message", since = "1.81.0")] | |
| pub use self::panic_info::PanicMessage; | |
| #[stable(feature = "catch_unwind", since = "1.9.0")] | |
| pub use self::unwind_safe::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe}; | |
| #[doc(hidden)] | |
| #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] | |
| #[allow_internal_unstable(panic_internals, const_format_args)] | |
| #[rustc_diagnostic_item = "core_panic_2015_macro"] | |
| #[rustc_macro_transparency = "semiopaque"] | |
| pub macro panic_2015 { | |
| () => ( | |
| $crate::panicking::panic("explicit panic") | |
| ), | |
| ($msg:literal $(,)?) => ( | |
| $crate::panicking::panic($msg) | |
| ), | |
| // Use `panic_str_2015` instead of `panic_display::<&str>` for non_fmt_panic lint. | |
| ($msg:expr $(,)?) => ({ | |
| $crate::panicking::panic_str_2015($msg); | |
| }), | |
| // Special-case the single-argument case for const_panic. | |
| ("{}", $arg:expr $(,)?) => ({ | |
| $crate::panicking::panic_display(&$arg); | |
| }), | |
| ($fmt:expr, $($arg:tt)+) => ({ | |
| // Semicolon to prevent temporaries inside the formatting machinery from | |
| // being considered alive in the caller after the panic_fmt call. | |
| $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)); | |
| }), | |
| } | |
| #[doc(hidden)] | |
| #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] | |
| #[allow_internal_unstable(panic_internals, const_format_args)] | |
| #[rustc_diagnostic_item = "core_panic_2021_macro"] | |
| #[rustc_macro_transparency = "semiopaque"] | |
| pub macro panic_2021 { | |
| () => ( | |
| $crate::panicking::panic("explicit panic") | |
| ), | |
| // Special-case the single-argument case for const_panic. | |
| ("{}", $arg:expr $(,)?) => ({ | |
| $crate::panicking::panic_display(&$arg); | |
| }), | |
| ($($t:tt)+) => ({ | |
| // Semicolon to prevent temporaries inside the formatting machinery from | |
| // being considered alive in the caller after the panic_fmt call. | |
| $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); | |
| }), | |
| } | |
| #[doc(hidden)] | |
| #[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")] | |
| #[allow_internal_unstable(panic_internals)] | |
| #[rustc_diagnostic_item = "unreachable_2015_macro"] | |
| #[rustc_macro_transparency = "semiopaque"] | |
| pub macro unreachable_2015 { | |
| () => ( | |
| $crate::panicking::panic("internal error: entered unreachable code") | |
| ), | |
| // Use of `unreachable_display` for non_fmt_panic lint. | |
| // NOTE: the message ("internal error ...") is embedded directly in unreachable_display | |
| ($msg:expr $(,)?) => ({ | |
| $crate::panicking::unreachable_display(&$msg); | |
| }), | |
| ($fmt:expr, $($arg:tt)*) => ( | |
| $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) | |
| ), | |
| } | |
| #[doc(hidden)] | |
| #[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")] | |
| #[allow_internal_unstable(panic_internals)] | |
| #[rustc_macro_transparency = "semiopaque"] | |
| pub macro unreachable_2021 { | |
| () => ( | |
| $crate::panicking::panic("internal error: entered unreachable code") | |
| ), | |
| ($($t:tt)+) => ( | |
| $crate::panic!("internal error: entered unreachable code: {}", $crate::format_args!($($t)+)) | |
| ), | |
| } | |
| /// Invokes a closure, aborting if the closure unwinds. | |
| /// | |
| /// When compiled with aborting panics, this function is effectively a no-op. | |
| /// With unwinding panics, an unwind results in another call into the panic | |
| /// hook followed by a process abort. | |
| /// | |
| /// # Notes | |
| /// | |
| /// Instead of using this function, code should attempt to support unwinding. | |
| /// Implementing [`Drop`] allows you to restore invariants uniformly in both | |
| /// return and unwind paths. | |
| /// | |
| /// If an unwind can lead to logical issues but not soundness issues, you | |
| /// should allow the unwind. Opting out of [`UnwindSafe`] indicates to your | |
| /// consumers that they need to consider correctness in the face of unwinds. | |
| /// | |
| /// If an unwind would be unsound, then this function should be used in order | |
| /// to prevent unwinds. However, note that `extern "C" fn` will automatically | |
| /// convert unwinds to aborts, so using this function isn't necessary for FFI. | |
| #[unstable(feature = "abort_unwind", issue = "130338")] | |
| #[rustc_nounwind] | |
| pub fn abort_on_unwind<F: FnOnce() -> R, R>(f: F) -> R { | |
| f() | |
| } | |
| /// Helper macro for panicking in a `const fn`. | |
| /// Invoke as: | |
| /// ```rust,ignore (just an example) | |
| /// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar); | |
| /// ``` | |
| /// where the first message will be printed in const-eval, | |
| /// and the second message will be printed at runtime. | |
| // All uses of this macro are FIXME(const-hack). | |
| #[unstable(feature = "panic_internals", issue = "none")] | |
| #[doc(hidden)] | |
| pub macro const_panic { | |
| ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{ | |
| // Wrap call to `const_eval_select` in a function so that we can | |
| // add the `rustc_allow_const_fn_unstable`. This is okay to do | |
| // because both variants will panic, just with different messages. | |
| #[rustc_allow_const_fn_unstable(const_eval_select)] | |
| #[inline(always)] // inline the wrapper | |
| #[track_caller] | |
| const fn do_panic($($arg: $ty),*) -> ! { | |
| $crate::intrinsics::const_eval_select!( | |
| @capture { $($arg: $ty = $arg),* } -> !: | |
| if const #[track_caller] { | |
| $crate::panic!($const_msg) | |
| } else #[track_caller] { | |
| $crate::panic!($runtime_msg) | |
| } | |
| ) | |
| } | |
| do_panic($($val),*) | |
| }}, | |
| // We support leaving away the `val` expressions for *all* arguments | |
| // (but not for *some* arguments, that's too tricky). | |
| ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => { | |
| $crate::panic::const_panic!( | |
| $const_msg, | |
| $runtime_msg, | |
| $($arg: $ty = $arg),* | |
| ) | |
| }, | |
| } | |
| /// A version of `assert` that prints a non-formatting message in const contexts. | |
| /// | |
| /// See [`const_panic!`]. | |
| #[unstable(feature = "panic_internals", issue = "none")] | |
| #[doc(hidden)] | |
| pub macro const_assert { | |
| ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{ | |
| if !($condition) { | |
| $crate::panic::const_panic!($const_msg, $runtime_msg, $($arg)*) | |
| } | |
| }} | |
| } |