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