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