kernel/build_assert.rs
1// SPDX-License-Identifier: GPL-2.0
2
3//! Various assertions that happen during build-time.
4//!
5//! There are three types of build-time assertions that you can use:
6//! - [`static_assert!`]
7//! - [`const_assert!`]
8//! - [`build_assert!`]
9//!
10//! The ones towards the bottom of the list are more expressive, while the ones towards the top of
11//! the list are more robust and trigger earlier in the compilation pipeline. Therefore, you should
12//! prefer the ones towards the top of the list wherever possible.
13//!
14//! # Choosing the correct assertion
15//!
16//! If you're asserting outside any bodies (e.g. initializers or function bodies), you should use
17//! [`static_assert!`] as it is the only assertion that can be used in that context.
18//!
19//! Inside bodies, if your assertion condition does not depend on any variable or generics, you
20//! should use [`static_assert!`]. If the condition depends on generics, but not variables
21//! (including function arguments), you should use [`const_assert!`]. Otherwise, use
22//! [`build_assert!`]. The same is true regardless if the function is `const fn`.
23//!
24//! ```
25//! // Outside any bodies.
26//! static_assert!(core::mem::size_of::<u8>() == 1);
27//! // `const_assert!` and `build_assert!` cannot be used here, they will fail to compile.
28//!
29//! #[inline(always)]
30//! fn foo<const N: usize>(v: usize) {
31//! static_assert!(core::mem::size_of::<u8>() == 1); // Preferred.
32//! const_assert!(core::mem::size_of::<u8>() == 1); // Discouraged.
33//! build_assert!(core::mem::size_of::<u8>() == 1); // Discouraged.
34//!
35//! // `static_assert!(N > 1);` is not allowed.
36//! const_assert!(N > 1); // Preferred.
37//! build_assert!(N > 1); // Discouraged.
38//!
39//! // `static_assert!(v > 1);` is not allowed.
40//! // `const_assert!(v > 1);` is not allowed.
41//! build_assert!(v > 1); // Works.
42//! }
43//! ```
44//!
45//! # Detailed behavior
46//!
47//! `static_assert!()` is equivalent to `static_assert` in C. It requires `expr` to be a constant
48//! expression. This expression cannot refer to any generics. A `static_assert!(expr)` in a program
49//! is always evaluated, regardless if the function it appears in is used or not. This is also the
50//! only usable assertion outside a body.
51//!
52//! `const_assert!()` has no direct C equivalence. It is a more powerful version of
53//! `static_assert!()`, where it may refer to generics in a function. Note that due to the ability
54//! to refer to generics, the assertion is tied to a specific instance of a function. So if it is
55//! used in a generic function that is not instantiated, the assertion will not be checked. For this
56//! reason, `static_assert!()` is preferred wherever possible.
57//!
58//! `build_assert!()` is equivalent to `BUILD_BUG_ON`. It is even more powerful than
59//! `const_assert!()` because it can be used to check tautologies that depend on runtime value (this
60//! is the same as `BUILD_BUG_ON`). However, the assertion failure mechanism can possibly be
61//! undefined symbols and linker errors, it is not developer friendly to debug, so it is recommended
62//! to avoid it and prefer other two assertions where possible.
63
64pub use crate::{
65 build_assert,
66 build_error,
67 const_assert,
68 static_assert, //
69};
70
71#[doc(hidden)]
72pub use build_error::build_error;
73
74/// Static assert (i.e. compile-time assert).
75///
76/// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`].
77///
78/// An optional panic message can be supplied after the expression.
79/// Currently only a string literal without formatting is supported
80/// due to constness limitations of the [`assert!`] macro.
81///
82/// The feature may be added to Rust in the future: see [RFC 2790].
83///
84/// You cannot refer to generics or variables with [`static_assert!`]. If you need to refer to
85/// generics, use [`const_assert!`]; if you need to refer to variables, use [`build_assert!`]. See
86/// the [module documentation](self).
87///
88/// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert
89/// [`static_assert`]: https://en.cppreference.com/w/cpp/language/static_assert
90/// [RFC 2790]: https://github.com/rust-lang/rfcs/issues/2790
91///
92/// # Examples
93///
94/// ```
95/// static_assert!(42 > 24);
96/// static_assert!(core::mem::size_of::<u8>() == 1);
97///
98/// const X: &[u8] = b"bar";
99/// static_assert!(X[1] == b'a');
100///
101/// const fn f(x: i32) -> i32 {
102/// x + 2
103/// }
104/// static_assert!(f(40) == 42);
105/// static_assert!(f(40) == 42, "f(x) must add 2 to the given input.");
106/// ```
107#[macro_export]
108macro_rules! static_assert {
109 ($condition:expr $(,$arg:literal)?) => {
110 const _: () = ::core::assert!($condition $(,$arg)?);
111 };
112}
113
114/// Assertion during constant evaluation.
115///
116/// This is a more powerful version of [`static_assert!`] that can refer to generics inside
117/// functions or implementation blocks. However, it also has a limitation where it can only appear
118/// in places where statements can appear; for example, you cannot use it as an item in the module.
119///
120/// [`static_assert!`] should be preferred if no generics are referred to in the condition. You
121/// cannot refer to variables with [`const_assert!`] (even inside `const fn`); if you need the
122/// capability, use [`build_assert!`]. See the [module documentation](self).
123///
124/// # Examples
125///
126/// ```
127/// fn foo<const N: usize>() {
128/// const_assert!(N > 1);
129/// }
130///
131/// fn bar<T>() {
132/// const_assert!(size_of::<T>() > 0, "T cannot be ZST");
133/// }
134/// ```
135#[macro_export]
136macro_rules! const_assert {
137 ($condition:expr $(,$arg:literal)?) => {
138 const { ::core::assert!($condition $(,$arg)?) };
139 };
140}
141
142/// Fails the build if the code path calling `build_error!` can possibly be executed.
143///
144/// If the macro is executed in const context, `build_error!` will panic.
145/// If the compiler or optimizer cannot guarantee that `build_error!` can never
146/// be called, a build error will be triggered.
147///
148/// # Examples
149///
150/// ```
151/// #[inline]
152/// fn foo(a: usize) -> usize {
153/// a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
154/// }
155///
156/// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
157/// // foo(usize::MAX); // Fails to compile.
158/// ```
159#[macro_export]
160macro_rules! build_error {
161 () => {{
162 $crate::build_assert::build_error("")
163 }};
164 ($msg:expr) => {{
165 $crate::build_assert::build_error($msg)
166 }};
167}
168
169/// Asserts that a boolean expression is `true` at compile time.
170///
171/// If the condition is evaluated to `false` in const context, `build_assert!`
172/// will panic. If the compiler or optimizer cannot guarantee the condition will
173/// be evaluated to `true`, a build error will be triggered.
174///
175/// When a condition depends on a function argument, the function must be annotated with
176/// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the
177/// function, preventing it from optimizing out the error path.
178///
179/// If the assertion condition does not depend on any variables or generics, you should use
180/// [`static_assert!`]. If the assertion condition does not depend on variables, but does depend on
181/// generics, you should use [`const_assert!`]. See the [module documentation](self).
182///
183/// # Examples
184///
185/// ```
186/// #[inline(always)] // Important.
187/// fn bar(n: usize) {
188/// build_assert!(n > 1);
189/// }
190///
191/// fn foo() {
192/// bar(2);
193/// }
194///
195/// #[inline(always)] // Important.
196/// const fn const_bar(n: usize) {
197/// build_assert!(n > 1);
198/// }
199///
200/// const _: () = const_bar(2);
201/// ```
202#[macro_export]
203macro_rules! build_assert {
204 ($cond:expr $(,)?) => {{
205 if !$cond {
206 $crate::build_assert::build_error(concat!("assertion failed: ", stringify!($cond)));
207 }
208 }};
209 ($cond:expr, $msg:expr) => {{
210 if !$cond {
211 $crate::build_assert::build_error($msg);
212 }
213 }};
214}