forked from Kestrer/bounded-integer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlib.rs
More file actions
64 lines (57 loc) · 2.22 KB
/
lib.rs
File metadata and controls
64 lines (57 loc) · 2.22 KB
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
//! Checking compilation with optimizations for the `assert_unchecked` range tests in `unsafe_api`.
//!
//! ```rust,compile_fail
//! const LOWER_BOUND: usize = 15;
//!
//! let bounded = bounded_integer::BoundedUsize::<LOWER_BOUND, 20>::new_saturating(15);
//! let bounded = core::hint::black_box(bounded);
//!
//! optimization_tests::assert_optimized_out!(
//! bounded.get() <= LOWER_BOUND
//! )
//! optimization_tests::assert_optimized_out!(
//! *bounded.get_ref() <= LOWER_BOUND
//! )
//! optimization_tests::assert_optimized_out!(
//! *unsafe { bounded.get_mut() } <= LOWER_BOUND
//! )
//! ```
// We should not export anything when not running tests
#![cfg(test)]
use bounded_integer::BoundedUsize;
unsafe extern "C" {
/// This function should fail to link if range checks are not optimized out as expected.
safe fn should_be_optimized_out() -> !;
}
/// Ensure that LLVM has enough information at compile-time to statically ensure that the
/// condition is true. If LLVM cannot statically ensure that the condition is true and
/// emits a run-time branch, the binary will contain a call to a non-existent `extern`
/// function and fail to link.
#[macro_export]
macro_rules! optimizer_assert_guaranteed {
($cond:expr) => {
if !$cond {
$crate::should_be_optimized_out();
}
};
}
/// Assert that the inner value is statically enforced to be between the bounds `LO` and
/// `HI` inclusive.
fn range_check_optimized_out_usize<const LO: usize, const HI: usize>(expected: usize) {
let i = core::hint::black_box(BoundedUsize::<LO, HI>::new(expected).unwrap());
optimizer_assert_guaranteed!(i.get() >= LO && i.get() <= HI);
let i = core::hint::black_box(i);
optimizer_assert_guaranteed!(*i.get_ref() >= LO && *i.get_ref() <= HI);
let mut i = core::hint::black_box(i);
optimizer_assert_guaranteed!(*unsafe { i.get_mut() } >= LO && *unsafe { i.get_mut() } <= HI);
assert_eq!(
core::hint::black_box(i.get()),
core::hint::black_box(expected)
);
}
#[test]
fn range_check_optimized_out() {
range_check_optimized_out_usize::<10, 20>(15);
range_check_optimized_out_usize::<20, 20>(20);
range_check_optimized_out_usize::<1, { usize::MAX - 1 }>(usize::MAX - 1);
}