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