xref: /linux/rust/kernel/build_assert.rs (revision 26ff969926a08eee069767ddbbbc301adbcd9676)
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 
64 pub use crate::{
65     build_assert,
66     build_error,
67     const_assert,
68     static_assert, //
69 };
70 
71 #[doc(hidden)]
72 pub 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]
108 macro_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]
136 macro_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]
160 macro_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]
203 macro_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 }
215