xref: /linux-6.15/rust/kernel/build_assert.rs (revision 614724e7)
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 /// # use kernel::build_error;
18 /// #[inline]
19 /// fn foo(a: usize) -> usize {
20 ///     a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
21 /// }
22 ///
23 /// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
24 /// // foo(usize::MAX); // Fails to compile.
25 /// ```
26 #[macro_export]
27 macro_rules! build_error {
28     () => {{
29         $crate::build_assert::build_error("")
30     }};
31     ($msg:expr) => {{
32         $crate::build_assert::build_error($msg)
33     }};
34 }
35 
36 /// Asserts that a boolean expression is `true` at compile time.
37 ///
38 /// If the condition is evaluated to `false` in const context, `build_assert!`
39 /// will panic. If the compiler or optimizer cannot guarantee the condition will
40 /// be evaluated to `true`, a build error will be triggered.
41 ///
42 /// [`static_assert!`] should be preferred to `build_assert!` whenever possible.
43 ///
44 /// # Examples
45 ///
46 /// These examples show that different types of [`assert!`] will trigger errors
47 /// at different stage of compilation. It is preferred to err as early as
48 /// possible, so [`static_assert!`] should be used whenever possible.
49 /// ```ignore
50 /// fn foo() {
51 ///     static_assert!(1 > 1); // Compile-time error
52 ///     build_assert!(1 > 1); // Build-time error
53 ///     assert!(1 > 1); // Run-time error
54 /// }
55 /// ```
56 ///
57 /// When the condition refers to generic parameters or parameters of an inline function,
58 /// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.
59 /// ```
60 /// fn foo<const N: usize>() {
61 ///     // `static_assert!(N > 1);` is not allowed
62 ///     build_assert!(N > 1); // Build-time check
63 ///     assert!(N > 1); // Run-time check
64 /// }
65 ///
66 /// #[inline]
67 /// fn bar(n: usize) {
68 ///     // `static_assert!(n > 1);` is not allowed
69 ///     build_assert!(n > 1); // Build-time check
70 ///     assert!(n > 1); // Run-time check
71 /// }
72 /// ```
73 ///
74 /// [`static_assert!`]: crate::static_assert!
75 #[macro_export]
76 macro_rules! build_assert {
77     ($cond:expr $(,)?) => {{
78         if !$cond {
79             $crate::build_assert::build_error(concat!("assertion failed: ", stringify!($cond)));
80         }
81     }};
82     ($cond:expr, $msg:expr) => {{
83         if !$cond {
84             $crate::build_assert::build_error($msg);
85         }
86     }};
87 }
88