1 /// Asserts that constant expressions evaluate to `true`. 2 /// 3 /// Constant expressions can be ensured to have certain properties via this 4 /// macro If the expression evaluates to `false`, the file will fail to compile. 5 /// This is synonymous to [`static_assert` in C++][static_assert]. 6 /// 7 /// # Alternatives 8 /// 9 /// There also exists [`const_assert_eq`](macro.const_assert_eq.html) for 10 /// validating whether a sequence of expressions are equal to one another. 11 /// 12 /// # Examples 13 /// 14 /// A common use case is to guarantee properties about a constant value that's 15 /// generated via meta-programming. 16 /// 17 /// ``` 18 /// # #[macro_use] extern crate static_assertions; fn main() {} 19 /// const VALUE: i32 = // ... 20 /// # 3; 21 /// 22 /// const_assert!(VALUE >= 2); 23 /// ``` 24 /// 25 /// Inputs are type-checked as booleans: 26 /// 27 /// ```compile_fail 28 /// # #[macro_use] extern crate static_assertions; fn main() {} 29 /// const_assert!(!0); 30 /// ``` 31 /// 32 /// Despite this being a macro, we see this produces a type error: 33 /// 34 /// ```txt 35 /// | const_assert!(!0); 36 /// | ^^ expected bool, found integral variable 37 /// | 38 /// = note: expected type `bool` 39 /// found type `{integer}` 40 /// ``` 41 /// 42 /// The following fails to compile because multiplying by 5 does not have an 43 /// identity property: 44 /// 45 /// ```compile_fail 46 /// # #[macro_use] extern crate static_assertions; fn main() {} 47 /// const_assert!(5 * 5 == 5); 48 /// ``` 49 /// 50 /// [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert 51 #[macro_export(local_inner_macros)] 52 macro_rules! const_assert { 53 ($x:expr $(,)?) => { 54 const _: $crate::True = _to_bool!($x); 55 }; 56 } 57 58 /// Asserts that constants are equal in value. 59 /// 60 /// Use [`const_assert_eq_usize!`](macro.const_assert_eq_usize.html) for better 61 /// error messages when asserting 62 /// [`usize`](https://doc.rust-lang.org/std/primitive.usize.html) equality. 63 /// 64 /// # Examples 65 /// 66 /// This works as a shorthand for `const_assert!(a == b)`: 67 /// 68 /// ``` 69 /// # #[macro_use] extern crate static_assertions; fn main() {} 70 /// const TWO: i32 = 2; 71 /// 72 /// const_assert_eq!(TWO * TWO, TWO + TWO); 73 /// ``` 74 /// 75 /// Just because 2 × 2 = 2 + 2 doesn't mean it holds true for other numbers: 76 /// 77 /// ```compile_fail 78 /// # #[macro_use] extern crate static_assertions; fn main() {} 79 /// const_assert_eq!(4 + 4, 4 * 4); 80 /// ``` 81 #[macro_export(local_inner_macros)] 82 macro_rules! const_assert_eq { 83 ($x:expr, $($y:expr),+ $(,)?) => { 84 const_assert!($($x == $y)&&+); 85 }; 86 } 87 88 /// Asserts that constants of type 89 /// [`usize`](https://doc.rust-lang.org/std/primitive.usize.html) are equal in 90 /// value. 91 /// 92 /// This is equivalent to [`const_assert_eq!`](macro.const_assert_eq.html) but 93 /// allows for inspecting the values in error messages. 94 #[macro_export] 95 macro_rules! const_assert_eq_usize { 96 ($x:expr, $($y:expr),+ $(,)?) => { 97 // Assigned instance must match the annotated type or else it will fail. 98 $(const _: [(); $x] = [(); $y];)+ 99 }; 100 } 101 102 /// Asserts that constants are **not** equal in value. 103 /// 104 /// # Examples 105 /// 106 /// This works as a shorthand for `const_assert!(a != b)`: 107 /// 108 /// ``` 109 /// # #[macro_use] extern crate static_assertions; fn main() {} 110 /// const NUM: usize = 32; 111 /// 112 /// const_assert_ne!(NUM * NUM, 64); 113 /// ``` 114 /// 115 /// The following example fails to compile because 2 is magic and 2 × 2 = 2 + 2: 116 /// 117 /// ```compile_fail 118 /// # #[macro_use] extern crate static_assertions; fn main() {} 119 /// const_assert_ne!(2 + 2, 2 * 2); 120 /// ``` 121 #[macro_export(local_inner_macros)] 122 macro_rules! const_assert_ne { 123 ($x:expr, $($y:expr),+ $(,)?) => { 124 const_assert!($($x != $y)&&+); 125 }; 126 } 127 128 /// Asserts that constants are less than each other. 129 #[macro_export(local_inner_macros)] 130 macro_rules! const_assert_lt { 131 ($x:expr, $($y:expr),+ $(,)?) => { 132 const_assert_lt!(@build $x, $($y),+); 133 }; 134 (@build $x:expr) => {}; 135 (@build $x:expr, $($y:expr),+) => { 136 const_assert!($x < _head!($($y),+)); 137 const_assert_lt!(@build $($y),+); 138 }; 139 } 140 141 /// Asserts that constants are less than or equal to each other. 142 #[macro_export(local_inner_macros)] 143 macro_rules! const_assert_le { 144 ($x:expr, $($y:expr),+ $(,)?) => { 145 const_assert_le!(@build $x, $($y),+); 146 }; 147 (@build $x:expr) => {}; 148 (@build $x:expr, $($y:expr),+) => { 149 const_assert!($x <= _head!($($y),+)); 150 const_assert_le!(@build $($y),+); 151 }; 152 } 153 154 /// Asserts that constants are greater than each other. 155 #[macro_export(local_inner_macros)] 156 macro_rules! const_assert_gt { 157 ($x:expr, $($y:expr),+ $(,)?) => { 158 const_assert_gt!(@build $x, $($y),+); 159 }; 160 (@build $x:expr) => {}; 161 (@build $x:expr, $($y:expr),+) => { 162 const_assert!($x > _head!($($y),+)); 163 const_assert_gt!(@build $($y),+); 164 }; 165 } 166 167 /// Asserts that constants are less than or equal to each other. 168 #[macro_export(local_inner_macros)] 169 macro_rules! const_assert_ge { 170 ($x:expr, $($y:expr),+ $(,)?) => { 171 const_assert_ge!(@build $x, $($y),+); 172 }; 173 (@build $x:expr) => {}; 174 (@build $x:expr, $($y:expr),+) => { 175 const_assert!($x >= _head!($($y),+)); 176 const_assert_ge!(@build $($y),+); 177 }; 178 } 179