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
use core::hint::unreachable_unchecked;

/// This has no effect if `predicate` returns true and invokes undefined behavior or panics in debug otherwise. This provides compiler with
/// additional opportunities for optimization when used in the critical paths of your application. Actual effect must
/// always be measured with a profiler and through ASM / IR inspection.
/// # Safety
/// `predicate` must not create any side effects or panic. It's better to avoid potentially panicking functions altogether, including memory allocation
/// and []-indexing as compiler may not be able to remove the code. 
/// You should stick with `assert` macro unless it is possible to formally verify `predicate`.
/// # Examples
/// ```
/// # use unsafer::assume::assume;
/// unsafe fn push_unchecked(v: &mut Vec<i32>, val: i32) {
///     unsafe {
///         assume(|| v.len() < v.capacity());
///         // Compiler is allowed to remove capacity check, reallocation logic and panic handler.
///         v.push(val);
///     }
/// }
/// ```
#[inline(always)]
pub unsafe fn assume(predicate: impl Fn() -> bool)
{
    let f = predicate();
    debug_assert!(f);
    if !f {
        unsafe {
            unreachable_unchecked();
        }
    }
}

pub trait OptionAssume<T> {
    /// Unwraps `self` in it contains Some and invokes undefined behavior or panics in debug otherwise.
    /// # Examples

    /// ```# use unsafer::assume::OptionAssume;
    /// let mut dict = HashMap::new();
    /// dict.insert("first", 64);
    /// dict.insert("second", 93);
    /// dict.insert("third", 1256);
    /// dict.insert("fourth", 5483);
    ///
    /// let a = unsafe { *dict.get("third").assume_some() };
    /// assert!(a == 1256);
    /// // let a = unsafe { *dict.get("thidr").assume_some() }; // UB: get hangs in an infinite loop
    /// // assert!(a == 1256);

    unsafe fn assume_some(self) -> T;
    /// Unwraps `self` in it contains None and invokes undefined behavior or panics in debug otherwise.
    unsafe fn assume_none(self);
}

impl <T> OptionAssume<T> for Option<T> {
    unsafe fn assume_some(self) -> T {
        debug_assert!(self.is_some());
        match self {
            Some(this) => this,
            None => unreachable_unchecked()
        }
    }

    unsafe fn assume_none(self) {
        debug_assert!(self.is_none());
        match self {
            Some(_) => unreachable_unchecked(),
            None => ()
        }
    }
}