xref: /openbmc/linux/rust/kernel/build_assert.rs (revision 3ed03f4d)
10f595babSGary Guo // SPDX-License-Identifier: GPL-2.0
20f595babSGary Guo 
30f595babSGary Guo //! Build-time assert.
40f595babSGary Guo 
50f595babSGary Guo /// Fails the build if the code path calling `build_error!` can possibly be executed.
60f595babSGary Guo ///
70f595babSGary Guo /// If the macro is executed in const context, `build_error!` will panic.
80f595babSGary Guo /// If the compiler or optimizer cannot guarantee that `build_error!` can never
90f595babSGary Guo /// be called, a build error will be triggered.
100f595babSGary Guo ///
110f595babSGary Guo /// # Examples
120f595babSGary Guo ///
130f595babSGary Guo /// ```
140f595babSGary Guo /// # use kernel::build_error;
150f595babSGary Guo /// #[inline]
160f595babSGary Guo /// fn foo(a: usize) -> usize {
170f595babSGary Guo ///     a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
180f595babSGary Guo /// }
190f595babSGary Guo ///
200f595babSGary Guo /// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
210f595babSGary Guo /// // foo(usize::MAX); // Fails to compile.
220f595babSGary Guo /// ```
230f595babSGary Guo #[macro_export]
240f595babSGary Guo macro_rules! build_error {
250f595babSGary Guo     () => {{
260f595babSGary Guo         $crate::build_error("")
270f595babSGary Guo     }};
280f595babSGary Guo     ($msg:expr) => {{
290f595babSGary Guo         $crate::build_error($msg)
300f595babSGary Guo     }};
310f595babSGary Guo }
320f595babSGary Guo 
330f595babSGary Guo /// Asserts that a boolean expression is `true` at compile time.
340f595babSGary Guo ///
350f595babSGary Guo /// If the condition is evaluated to `false` in const context, `build_assert!`
360f595babSGary Guo /// will panic. If the compiler or optimizer cannot guarantee the condition will
370f595babSGary Guo /// be evaluated to `true`, a build error will be triggered.
380f595babSGary Guo ///
390f595babSGary Guo /// [`static_assert!`] should be preferred to `build_assert!` whenever possible.
400f595babSGary Guo ///
410f595babSGary Guo /// # Examples
420f595babSGary Guo ///
430f595babSGary Guo /// These examples show that different types of [`assert!`] will trigger errors
440f595babSGary Guo /// at different stage of compilation. It is preferred to err as early as
450f595babSGary Guo /// possible, so [`static_assert!`] should be used whenever possible.
460f595babSGary Guo /// ```ignore
470f595babSGary Guo /// fn foo() {
480f595babSGary Guo ///     static_assert!(1 > 1); // Compile-time error
490f595babSGary Guo ///     build_assert!(1 > 1); // Build-time error
500f595babSGary Guo ///     assert!(1 > 1); // Run-time error
510f595babSGary Guo /// }
520f595babSGary Guo /// ```
530f595babSGary Guo ///
540f595babSGary Guo /// When the condition refers to generic parameters or parameters of an inline function,
550f595babSGary Guo /// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.
560f595babSGary Guo /// ```
570f595babSGary Guo /// fn foo<const N: usize>() {
580f595babSGary Guo ///     // `static_assert!(N > 1);` is not allowed
590f595babSGary Guo ///     build_assert!(N > 1); // Build-time check
600f595babSGary Guo ///     assert!(N > 1); // Run-time check
610f595babSGary Guo /// }
620f595babSGary Guo ///
630f595babSGary Guo /// #[inline]
640f595babSGary Guo /// fn bar(n: usize) {
650f595babSGary Guo ///     // `static_assert!(n > 1);` is not allowed
660f595babSGary Guo ///     build_assert!(n > 1); // Build-time check
670f595babSGary Guo ///     assert!(n > 1); // Run-time check
680f595babSGary Guo /// }
690f595babSGary Guo /// ```
70*3ed03f4dSMiguel Ojeda ///
71*3ed03f4dSMiguel Ojeda /// [`static_assert!`]: crate::static_assert!
720f595babSGary Guo #[macro_export]
730f595babSGary Guo macro_rules! build_assert {
740f595babSGary Guo     ($cond:expr $(,)?) => {{
750f595babSGary Guo         if !$cond {
760f595babSGary Guo             $crate::build_error(concat!("assertion failed: ", stringify!($cond)));
770f595babSGary Guo         }
780f595babSGary Guo     }};
790f595babSGary Guo     ($cond:expr, $msg:expr) => {{
800f595babSGary Guo         if !$cond {
810f595babSGary Guo             $crate::build_error($msg);
820f595babSGary Guo         }
830f595babSGary Guo     }};
840f595babSGary Guo }
85