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
//! Sometimes it just takes a small nudge for the compiler to generate the code you want.

#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
#![cfg_attr(not(feature = "std"), no_std)]

mod internal {
    cfg_if::cfg_if! {
        if #[cfg(feature = "nightly")] {
            #[inline(always)]
            pub unsafe fn assume(b: bool) {
                core::intrinsics::assume(b)
            }

            #[inline(always)]
            pub fn unlikely(b: bool) -> bool {
                // not actually unsafe to say a bool is probably false
                unsafe { core::intrinsics::unlikely(b) }
            }

            #[inline(always)]
            pub fn likely(b: bool) -> bool {
                // not actually unsafe to say a bool is probably true
                unsafe { core::intrinsics::likely(b) }
            }
        } else {
            #[inline]
            #[cold]
            fn cold() {}

            #[inline(always)]
            pub unsafe fn assume(b: bool) {
                if !b { crate::unreach() }
            }

            #[inline(always)]
            pub fn unlikely(b: bool) -> bool {
                if b {
                    cold()
                }
                b
            }

            #[inline(always)]
            pub fn likely(b: bool) -> bool {
                if !b {
                    cold()
                }
                b
            }
        }
    }
    cfg_if::cfg_if! {
        if #[cfg(feature = "std")] {
            #[inline]
            pub fn abort() -> ! {
                std::process::abort()
            }
        } else {
            #[inline(always)]
            pub extern "C" fn abort() -> ! {
                panic!()
            }
        }
    }
}

/// Unsafely assumes the value of an expression to be `true`.
///
/// The compiler is sometimes able to use this to optimize better, but it often backfires.
///
/// This generally requires the `nightly` feature to work.
#[inline(always)]
pub unsafe fn assume(b: bool) {
    crate::internal::assume(b)
}

/// Tells the compiler this `bool` is probably `false`.
///
/// This generally requires the `nightly` feature to work.
#[inline(always)]
pub fn unlikely(b: bool) -> bool {
    crate::internal::unlikely(b)
}

/// Tells the compiler this `bool` is probably `true`.
///
/// This generally requires the `nightly` feature to work.
#[inline(always)]
pub fn likely(b: bool) -> bool {
    crate::internal::likely(b)
}

/// Tells the compiler this code is unreachable.
///
/// This is identical to `core::hint::unreachable_unchecked` and is provided only for completeness.
#[inline(always)]
pub unsafe fn unreach() -> ! {
    core::hint::unreachable_unchecked()
}

/// The same as `std::process::abort`, but annotated as `#[cold]` and usable in `no_std` environments.
///
/// In a `no_std` environment this generates a trap instruction.
#[cold]
pub fn abort() -> ! {
    crate::internal::abort()
}

/// Assumes a closure will not panic.
///
/// Calls to `core::panicking` functions will still be generated; however, this function is nounwind and panics will cause UB.
#[inline]
pub unsafe extern "C" fn assume_nopanic<F: FnOnce() -> T, T>(f: F) -> T {
    struct NoPanic;
    impl Drop for NoPanic {
        #[inline(always)]
        fn drop(&mut self) {
            unsafe { crate::unreach() };
        }
    }

    let no_panic = NoPanic;
    let r = f();
    core::mem::forget(no_panic);
    r
}