xref: /linux/rust/kernel/build_assert.rs (revision 1b18b37a2c30f6e6698205a06de393f7e626f5d2)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Build-time assert.
4 
5 #[doc(hidden)]
6 pub use build_error::build_error;
7 
8 /// Fails the build if the code path calling `build_error!` can possibly be executed.
9 ///
10 /// If the macro is executed in const context, `build_error!` will panic.
11 /// If the compiler or optimizer cannot guarantee that `build_error!` can never
12 /// be called, a build error will be triggered.
13 ///
14 /// # Examples
15 ///
16 /// ```
17 /// #[inline]
18 /// fn foo(a: usize) -> usize {
19 ///     a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
20 /// }
21 ///
22 /// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
23 /// // foo(usize::MAX); // Fails to compile.
24 /// ```
25 #[macro_export]
26 macro_rules! build_error {
27     () => {{
28         $crate::build_assert::build_error("")
29     }};
30     ($msg:expr) => {{
31         $crate::build_assert::build_error($msg)
32     }};
33 }
34 
35 /// Asserts that a boolean expression is `true` at compile time.
36 ///
37 /// If the condition is evaluated to `false` in const context, `build_assert!`
38 /// will panic. If the compiler or optimizer cannot guarantee the condition will
39 /// be evaluated to `true`, a build error will be triggered.
40 ///
41 /// [`static_assert!`] should be preferred to `build_assert!` whenever possible.
42 ///
43 /// # Examples
44 ///
45 /// These examples show that different types of [`assert!`] will trigger errors
46 /// at different stage of compilation. It is preferred to err as early as
47 /// possible, so [`static_assert!`] should be used whenever possible.
48 /// ```ignore
49 /// fn foo() {
50 ///     static_assert!(1 > 1); // Compile-time error
51 ///     build_assert!(1 > 1); // Build-time error
52 ///     assert!(1 > 1); // Run-time error
53 /// }
54 /// ```
55 ///
56 /// When the condition refers to generic parameters or parameters of an inline function,
57 /// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.
58 /// ```
59 /// fn foo<const N: usize>() {
60 ///     // `static_assert!(N > 1);` is not allowed
61 ///     build_assert!(N > 1); // Build-time check
62 ///     assert!(N > 1); // Run-time check
63 /// }
64 /// ```
65 ///
66 /// When a condition depends on a function argument, the function must be annotated with
67 /// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the
68 /// function, preventing it from optimizing out the error path.
69 /// ```
70 /// #[inline(always)]
71 /// fn bar(n: usize) {
72 ///     // `static_assert!(n > 1);` is not allowed
73 ///     build_assert!(n > 1); // Build-time check
74 ///     assert!(n > 1); // Run-time check
75 /// }
76 /// ```
77 ///
78 /// [`static_assert!`]: crate::static_assert!
79 #[macro_export]
80 macro_rules! build_assert {
81     ($cond:expr $(,)?) => {{
82         if !$cond {
83             $crate::build_assert::build_error(concat!("assertion failed: ", stringify!($cond)));
84         }
85     }};
86     ($cond:expr, $msg:expr) => {{
87         if !$cond {
88             $crate::build_assert::build_error($msg);
89         }
90     }};
91 }
92