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