build_assert.rs 2.5 KB

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