panic.rs - source
Description: Source of the Rust file `library/core/src/panic.rs`.

#
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 = "semiopaque"]
    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 = "semiopaque"]
    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 = "semiopaque"]
    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 = "semiopaque"]
    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                if const #[track_caller] {
    170                    $crate::panic!($const_msg)
    171                } else #[track_caller] {
    172                    $crate::panic!($runtime_msg)
    173                }
    174            )
    175        }
    176
    177        do_panic($($val),*)
    178    }},
    179    // We support leaving away the `val` expressions for *all* arguments
    180    // (but not for *some* arguments, that's too tricky).
    181    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => {
    182        $crate::panic::const_panic!(
    183            $const_msg,
    184            $runtime_msg,
    185            $($arg: $ty = $arg),*
    186        )
    187    },
    188}
    189
    190/// A version of `assert` that prints a non-formatting message in const contexts.
    191///
    192/// See [`const_panic!`].
    193#[unstable(feature = "panic_internals", issue = "none")]
    194#[doc(hidden)]
    195pub macro const_assert {
    196    ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{
    197        if !($condition) {
    198            $crate::panic::const_panic!($const_msg, $runtime_msg, $($arg)*)
    199        }
    200    }}
    201}