Commit | Line | Data |
---|---|---|
0f595bab GG |
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 | } |