1bcab3026Sopenharmony_ci/// Asserts that constant expressions evaluate to `true`. 2bcab3026Sopenharmony_ci/// 3bcab3026Sopenharmony_ci/// Constant expressions can be ensured to have certain properties via this 4bcab3026Sopenharmony_ci/// macro If the expression evaluates to `false`, the file will fail to compile. 5bcab3026Sopenharmony_ci/// This is synonymous to [`static_assert` in C++][static_assert]. 6bcab3026Sopenharmony_ci/// 7bcab3026Sopenharmony_ci/// # Alternatives 8bcab3026Sopenharmony_ci/// 9bcab3026Sopenharmony_ci/// There also exists [`const_assert_eq`](macro.const_assert_eq.html) for 10bcab3026Sopenharmony_ci/// validating whether a sequence of expressions are equal to one another. 11bcab3026Sopenharmony_ci/// 12bcab3026Sopenharmony_ci/// # Examples 13bcab3026Sopenharmony_ci/// 14bcab3026Sopenharmony_ci/// A common use case is to guarantee properties about a constant value that's 15bcab3026Sopenharmony_ci/// generated via meta-programming. 16bcab3026Sopenharmony_ci/// 17bcab3026Sopenharmony_ci/// ``` 18bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {} 19bcab3026Sopenharmony_ci/// const VALUE: i32 = // ... 20bcab3026Sopenharmony_ci/// # 3; 21bcab3026Sopenharmony_ci/// 22bcab3026Sopenharmony_ci/// const_assert!(VALUE >= 2); 23bcab3026Sopenharmony_ci/// ``` 24bcab3026Sopenharmony_ci/// 25bcab3026Sopenharmony_ci/// Inputs are type-checked as booleans: 26bcab3026Sopenharmony_ci/// 27bcab3026Sopenharmony_ci/// ```compile_fail 28bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {} 29bcab3026Sopenharmony_ci/// const_assert!(!0); 30bcab3026Sopenharmony_ci/// ``` 31bcab3026Sopenharmony_ci/// 32bcab3026Sopenharmony_ci/// Despite this being a macro, we see this produces a type error: 33bcab3026Sopenharmony_ci/// 34bcab3026Sopenharmony_ci/// ```txt 35bcab3026Sopenharmony_ci/// | const_assert!(!0); 36bcab3026Sopenharmony_ci/// | ^^ expected bool, found integral variable 37bcab3026Sopenharmony_ci/// | 38bcab3026Sopenharmony_ci/// = note: expected type `bool` 39bcab3026Sopenharmony_ci/// found type `{integer}` 40bcab3026Sopenharmony_ci/// ``` 41bcab3026Sopenharmony_ci/// 42bcab3026Sopenharmony_ci/// The following fails to compile because multiplying by 5 does not have an 43bcab3026Sopenharmony_ci/// identity property: 44bcab3026Sopenharmony_ci/// 45bcab3026Sopenharmony_ci/// ```compile_fail 46bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {} 47bcab3026Sopenharmony_ci/// const_assert!(5 * 5 == 5); 48bcab3026Sopenharmony_ci/// ``` 49bcab3026Sopenharmony_ci/// 50bcab3026Sopenharmony_ci/// [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert 51bcab3026Sopenharmony_ci#[macro_export] 52bcab3026Sopenharmony_cimacro_rules! const_assert { 53bcab3026Sopenharmony_ci ($x:expr $(,)?) => { 54bcab3026Sopenharmony_ci #[allow(unknown_lints, eq_op)] 55bcab3026Sopenharmony_ci const _: [(); 0 - !{ const ASSERT: bool = $x; ASSERT } as usize] = []; 56bcab3026Sopenharmony_ci }; 57bcab3026Sopenharmony_ci} 58bcab3026Sopenharmony_ci 59bcab3026Sopenharmony_ci/// Asserts that constants are equal in value. 60bcab3026Sopenharmony_ci/// 61bcab3026Sopenharmony_ci/// # Examples 62bcab3026Sopenharmony_ci/// 63bcab3026Sopenharmony_ci/// This works as a shorthand for `const_assert!(a == b)`: 64bcab3026Sopenharmony_ci/// 65bcab3026Sopenharmony_ci/// ``` 66bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {} 67bcab3026Sopenharmony_ci/// const TWO: usize = 2; 68bcab3026Sopenharmony_ci/// 69bcab3026Sopenharmony_ci/// const_assert_eq!(TWO * TWO, TWO + TWO); 70bcab3026Sopenharmony_ci/// ``` 71bcab3026Sopenharmony_ci/// 72bcab3026Sopenharmony_ci/// Just because 2 × 2 = 2 + 2 doesn't mean it holds true for other numbers: 73bcab3026Sopenharmony_ci/// 74bcab3026Sopenharmony_ci/// ```compile_fail 75bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {} 76bcab3026Sopenharmony_ci/// const_assert_eq!(4 + 4, 4 * 4); 77bcab3026Sopenharmony_ci/// ``` 78bcab3026Sopenharmony_ci#[macro_export(local_inner_macros)] 79bcab3026Sopenharmony_cimacro_rules! const_assert_eq { 80bcab3026Sopenharmony_ci ($x:expr, $y:expr $(,)?) => { 81bcab3026Sopenharmony_ci const_assert!($x == $y); 82bcab3026Sopenharmony_ci }; 83bcab3026Sopenharmony_ci} 84bcab3026Sopenharmony_ci 85bcab3026Sopenharmony_ci/// Asserts that constants are **not** equal in value. 86bcab3026Sopenharmony_ci/// 87bcab3026Sopenharmony_ci/// # Examples 88bcab3026Sopenharmony_ci/// 89bcab3026Sopenharmony_ci/// This works as a shorthand for `const_assert!(a != b)`: 90bcab3026Sopenharmony_ci/// 91bcab3026Sopenharmony_ci/// ``` 92bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {} 93bcab3026Sopenharmony_ci/// const NUM: usize = 32; 94bcab3026Sopenharmony_ci/// 95bcab3026Sopenharmony_ci/// const_assert_ne!(NUM * NUM, 64); 96bcab3026Sopenharmony_ci/// ``` 97bcab3026Sopenharmony_ci/// 98bcab3026Sopenharmony_ci/// The following example fails to compile because 2 is magic and 2 × 2 = 2 + 2: 99bcab3026Sopenharmony_ci/// 100bcab3026Sopenharmony_ci/// ```compile_fail 101bcab3026Sopenharmony_ci/// # #[macro_use] extern crate static_assertions; fn main() {} 102bcab3026Sopenharmony_ci/// const_assert_ne!(2 + 2, 2 * 2); 103bcab3026Sopenharmony_ci/// ``` 104bcab3026Sopenharmony_ci#[macro_export(local_inner_macros)] 105bcab3026Sopenharmony_cimacro_rules! const_assert_ne { 106bcab3026Sopenharmony_ci ($x:expr, $y:expr $(,)?) => { 107bcab3026Sopenharmony_ci const_assert!($x != $y); 108bcab3026Sopenharmony_ci }; 109bcab3026Sopenharmony_ci} 110