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