      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167

    //! Panic support for libcore
    //!
    //! The core library cannot define panicking, but it does *declare* panicking. This
    //! means that the functions inside of libcore are allowed to panic, but to be
    //! useful an upstream crate must define panicking for libcore to use. The current
    //! interface for panicking is:
    //!
    //! ```
    //! fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> !
    //! # { loop {} }
    //! ```
    //!
    //! This definition allows for panicking with any general message, but it does not
    //! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`,
    //! for which we fill in a dummy value in `PanicInfo::internal_constructor`.)
    //! The reason for this is that libcore is not allowed to allocate.
    //!
    //! This module contains a few other panicking functions, but these are just the
    //! necessary lang items for the compiler. All panics are funneled through this
    //! one function. The actual symbol is declared through the `#[panic_handler]` attribute.

    #![allow(dead_code, missing_docs)]
    #![unstable(
        feature = "core_panic",
        reason = "internal details of the implementation of the `panic!` and related macros",
        issue = "none"
    )]

    use crate::fmt;
    use crate::panic::{Location, PanicInfo};

    /// The underlying implementation of libcore's `panic!` macro when no formatting is used.
    #[cold]
    // never inline unless panic_immediate_abort to avoid code
    // bloat at the call sites as much as possible
    #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
    #[track_caller]
    #[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
    pub fn panic(expr: &'static str) -> ! {
        if cfg!(feature = "panic_immediate_abort") {
            super::intrinsics::abort()
        }

        // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
        // reduce size overhead. The format_args! macro uses str's Display trait to
        // write expr, which calls Formatter::pad, which must accommodate string
        // truncation and padding (even though none is used here). Using
        // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
        // output binary, saving up to a few kilobytes.
        panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
    }

    #[inline]
    #[track_caller]
    #[lang = "panic_str"] // needed for const-evaluated panics
    pub fn panic_str(expr: &str) -> ! {
        panic_fmt(format_args!("{}", expr));
    }

    #[cold]
    #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
    #[track_caller]
    #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
    fn panic_bounds_check(index: usize, len: usize) -> ! {
        if cfg!(feature = "panic_immediate_abort") {
            super::intrinsics::abort()
        }

        panic!("index out of bounds: the len is {} but the index is {}", len, index)
    }

    /// The underlying implementation of libcore's `panic!` macro when formatting is used.
    #[cold]
    #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
    #[cfg_attr(feature = "panic_immediate_abort", inline)]
    #[track_caller]
    pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
        if cfg!(feature = "panic_immediate_abort") {
            super::intrinsics::abort()
        }

        // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
        // that gets resolved to the `#[panic_handler]` function.
        extern "Rust" {
            #[lang = "panic_impl"]
            fn panic_impl(pi: &PanicInfo<'_>) -> !;
        }

        let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller());

        // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
        unsafe { panic_impl(&pi) }
    }

    #[derive(Debug)]
    #[doc(hidden)]
    pub enum AssertKind {
        Eq,
        Ne,
        Match,
    }

    /// Internal function for `assert_eq!` and `assert_ne!` macros
    #[cold]
    #[track_caller]
    #[doc(hidden)]
    pub fn assert_failed<T, U>(
        kind: AssertKind,
        left: &T,
        right: &U,
        args: Option<fmt::Arguments<'_>>,
    ) -> !
    where
        T: fmt::Debug + ?Sized,
        U: fmt::Debug + ?Sized,
    {
        assert_failed_inner(kind, &left, &right, args)
    }

    /// Internal function for `assert_match!`
    #[cold]
    #[track_caller]
    #[doc(hidden)]
    pub fn assert_matches_failed<T: fmt::Debug + ?Sized>(
        left: &T,
        right: &str,
        args: Option<fmt::Arguments<'_>>,
    ) -> ! {
        // Use the Display implementation to display the pattern.
        struct Pattern<'a>(&'a str);
        impl fmt::Debug for Pattern<'_> {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                fmt::Display::fmt(self.0, f)
            }
        }
        assert_failed_inner(AssertKind::Match, &left, &Pattern(right), args);
    }

    /// Non-generic version of the above functions, to avoid code bloat.
    #[track_caller]
    fn assert_failed_inner(
        kind: AssertKind,
        left: &dyn fmt::Debug,
        right: &dyn fmt::Debug,
        args: Option<fmt::Arguments<'_>>,
    ) -> ! {
        let op = match kind {
            AssertKind::Eq => "==",
            AssertKind::Ne => "!=",
            AssertKind::Match => "matches",
        };

        match args {
            Some(args) => panic!(
                r#"assertion failed: `(left {} right)`
      left: `{:?}`,
     right: `{:?}`: {}"#,
                op, left, right, args
            ),
            None => panic!(
                r#"assertion failed: `(left {} right)`
      left: `{:?}`,
     right: `{:?}`"#,
                op, left, right,
            ),
        }
    }