xref: /linux/rust/kernel/build_assert.rs (revision 6b3f7af57881f6d6250c6dcc4d910fe8e855a607)
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 #[doc(inline)]
65 pub use crate::{
66     build_assert_macro as build_assert,
67     build_error,
68     const_assert,
69     static_assert, //
70 };
71 
72 #[doc(hidden)]
73 pub use build_error::build_error as build_error_fn;
74 
75 /// Static assert (i.e. compile-time assert).
76 ///
77 /// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`].
78 ///
79 /// An optional panic message can be supplied after the expression.
80 /// Currently only a string literal without formatting is supported
81 /// due to constness limitations of the [`assert!`] macro.
82 ///
83 /// The feature may be added to Rust in the future: see [RFC 2790].
84 ///
85 /// You cannot refer to generics or variables with [`static_assert!`]. If you need to refer to
86 /// generics, use [`const_assert!`]; if you need to refer to variables, use [`build_assert!`]. See
87 /// the [module documentation](self).
88 ///
89 /// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert
90 /// [`static_assert`]: https://en.cppreference.com/w/cpp/language/static_assert
91 /// [RFC 2790]: https://github.com/rust-lang/rfcs/issues/2790
92 ///
93 /// # Examples
94 ///
95 /// ```
96 /// static_assert!(42 > 24);
97 /// static_assert!(core::mem::size_of::<u8>() == 1);
98 ///
99 /// const X: &[u8] = b"bar";
100 /// static_assert!(X[1] == b'a');
101 ///
102 /// const fn f(x: i32) -> i32 {
103 ///     x + 2
104 /// }
105 /// static_assert!(f(40) == 42);
106 /// static_assert!(f(40) == 42, "f(x) must add 2 to the given input.");
107 /// ```
108 #[macro_export]
109 #[doc(hidden)]
110 macro_rules! static_assert {
111     ($condition:expr $(,$arg:literal)?) => {
112         const _: () = ::core::assert!($condition $(,$arg)?);
113     };
114 }
115 
116 /// Assertion during constant evaluation.
117 ///
118 /// This is a more powerful version of [`static_assert!`] that can refer to generics inside
119 /// functions or implementation blocks. However, it also has a limitation where it can only appear
120 /// in places where statements can appear; for example, you cannot use it as an item in the module.
121 ///
122 /// [`static_assert!`] should be preferred if no generics are referred to in the condition. You
123 /// cannot refer to variables with [`const_assert!`] (even inside `const fn`); if you need the
124 /// capability, use [`build_assert!`]. See the [module documentation](self).
125 ///
126 /// # Examples
127 ///
128 /// ```
129 /// fn foo<const N: usize>() {
130 ///     const_assert!(N > 1);
131 /// }
132 ///
133 /// fn bar<T>() {
134 ///     const_assert!(size_of::<T>() > 0, "T cannot be ZST");
135 /// }
136 /// ```
137 #[macro_export]
138 #[doc(hidden)]
139 macro_rules! const_assert {
140     ($condition:expr $(,$arg:literal)?) => {
141         const { ::core::assert!($condition $(,$arg)?) };
142     };
143 }
144 
145 /// Fails the build if the code path calling `build_error!` can possibly be executed.
146 ///
147 /// If the macro is executed in const context, `build_error!` will panic.
148 /// If the compiler or optimizer cannot guarantee that `build_error!` can never
149 /// be called, a build error will be triggered.
150 ///
151 /// # Examples
152 ///
153 /// ```
154 /// #[inline]
155 /// fn foo(a: usize) -> usize {
156 ///     a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
157 /// }
158 ///
159 /// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
160 /// // foo(usize::MAX); // Fails to compile.
161 /// ```
162 #[macro_export]
163 #[doc(hidden)]
164 macro_rules! build_error {
165     () => {{
166         $crate::build_assert::build_error_fn("")
167     }};
168     ($msg:expr) => {{
169         $crate::build_assert::build_error_fn($msg)
170     }};
171 }
172 
173 /// Asserts that a boolean expression is `true` at compile time.
174 ///
175 /// If the condition is evaluated to `false` in const context, `build_assert!`
176 /// will panic. If the compiler or optimizer cannot guarantee the condition will
177 /// be evaluated to `true`, a build error will be triggered.
178 ///
179 /// When a condition depends on a function argument, the function must be annotated with
180 /// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the
181 /// function, preventing it from optimizing out the error path.
182 ///
183 /// If the assertion condition does not depend on any variables or generics, you should use
184 /// [`static_assert!`]. If the assertion condition does not depend on variables, but does depend on
185 /// generics, you should use [`const_assert!`]. See the [module documentation](self).
186 ///
187 /// # Examples
188 ///
189 /// ```
190 /// #[inline(always)] // Important.
191 /// fn bar(n: usize) {
192 ///     build_assert!(n > 1);
193 /// }
194 ///
195 /// fn foo() {
196 ///     bar(2);
197 /// }
198 ///
199 /// #[inline(always)] // Important.
200 /// const fn const_bar(n: usize) {
201 ///     build_assert!(n > 1);
202 /// }
203 ///
204 /// const _: () = const_bar(2);
205 /// ```
206 #[macro_export]
207 #[doc(hidden)]
208 macro_rules! build_assert_macro {
209     ($cond:expr $(,)?) => {{
210         if !$cond {
211             $crate::build_assert::build_error_fn(concat!("assertion failed: ", stringify!($cond)));
212         }
213     }};
214     ($cond:expr, $msg:expr) => {{
215         if !$cond {
216             $crate::build_assert::build_error_fn($msg);
217         }
218     }};
219 }
220