summaryrefslogtreecommitdiff
path: root/rust/kernel/build_assert.rs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-12-12 16:59:00 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2022-12-12 16:59:00 -0800
commit96f42635684739cb563aa48d92d0d16b8dc9bda8 (patch)
tree661a6b0a72f70702401ac65c73a6f71bd12e83de /rust/kernel/build_assert.rs
parenteb4511538191ac758faa0735fe06c5ce8202ae04 (diff)
parentb9ecf9b9ac5969d7b7ea786ce5c76e24246df2c5 (diff)
Merge tag 'rust-6.2' of https://github.com/Rust-for-Linux/linux
Pull rust updates from Miguel Ojeda: "The first set of changes after the merge, the major ones being: - String and formatting: new types 'CString', 'CStr', 'BStr' and 'Formatter'; new macros 'c_str!', 'b_str!' and 'fmt!'. - Errors: the rest of the error codes from 'errno-base.h', as well as some 'From' trait implementations for the 'Error' type. - Printing: the rest of the 'pr_*!' levels and the continuation one 'pr_cont!', as well as a new sample. - 'alloc' crate: new constructors 'try_with_capacity()' and 'try_with_capacity_in()' for 'RawVec' and 'Vec'. - Procedural macros: new macros '#[vtable]' and 'concat_idents!', as well as better ergonomics for 'module!' users. - Asserting: new macros 'static_assert!', 'build_error!' and 'build_assert!', as well as a new crate 'build_error' to support them. - Vocabulary types: new types 'Opaque' and 'Either'. - Debugging: new macro 'dbg!'" * tag 'rust-6.2' of https://github.com/Rust-for-Linux/linux: (28 commits) rust: types: add `Opaque` type rust: types: add `Either` type rust: build_assert: add `build_{error,assert}!` macros rust: add `build_error` crate rust: static_assert: add `static_assert!` macro rust: std_vendor: add `dbg!` macro based on `std`'s one rust: str: add `fmt!` macro rust: str: add `CString` type rust: str: add `Formatter` type rust: str: add `c_str!` macro rust: str: add `CStr` unit tests rust: str: implement several traits for `CStr` rust: str: add `CStr` type rust: str: add `b_str!` macro rust: str: add `BStr` type rust: alloc: add `Vec::try_with_capacity{,_in}()` constructors rust: alloc: add `RawVec::try_with_capacity_in()` constructor rust: prelude: add `error::code::*` constant items rust: error: add `From` implementations for `Error` rust: error: add codes from `errno-base.h` ...
Diffstat (limited to 'rust/kernel/build_assert.rs')
-rw-r--r--rust/kernel/build_assert.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
new file mode 100644
index 000000000000..659542393c09
--- /dev/null
+++ b/rust/kernel/build_assert.rs
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Build-time assert.
+
+/// Fails the build if the code path calling `build_error!` can possibly be executed.
+///
+/// If the macro is executed in const context, `build_error!` will panic.
+/// If the compiler or optimizer cannot guarantee that `build_error!` can never
+/// be called, a build error will be triggered.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::build_error;
+/// #[inline]
+/// fn foo(a: usize) -> usize {
+/// a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
+/// }
+///
+/// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
+/// // foo(usize::MAX); // Fails to compile.
+/// ```
+#[macro_export]
+macro_rules! build_error {
+ () => {{
+ $crate::build_error("")
+ }};
+ ($msg:expr) => {{
+ $crate::build_error($msg)
+ }};
+}
+
+/// Asserts that a boolean expression is `true` at compile time.
+///
+/// If the condition is evaluated to `false` in const context, `build_assert!`
+/// will panic. If the compiler or optimizer cannot guarantee the condition will
+/// be evaluated to `true`, a build error will be triggered.
+///
+/// [`static_assert!`] should be preferred to `build_assert!` whenever possible.
+///
+/// # Examples
+///
+/// These examples show that different types of [`assert!`] will trigger errors
+/// at different stage of compilation. It is preferred to err as early as
+/// possible, so [`static_assert!`] should be used whenever possible.
+/// ```ignore
+/// fn foo() {
+/// static_assert!(1 > 1); // Compile-time error
+/// build_assert!(1 > 1); // Build-time error
+/// assert!(1 > 1); // Run-time error
+/// }
+/// ```
+///
+/// When the condition refers to generic parameters or parameters of an inline function,
+/// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.
+/// ```
+/// fn foo<const N: usize>() {
+/// // `static_assert!(N > 1);` is not allowed
+/// build_assert!(N > 1); // Build-time check
+/// assert!(N > 1); // Run-time check
+/// }
+///
+/// #[inline]
+/// fn bar(n: usize) {
+/// // `static_assert!(n > 1);` is not allowed
+/// build_assert!(n > 1); // Build-time check
+/// assert!(n > 1); // Run-time check
+/// }
+/// ```
+#[macro_export]
+macro_rules! build_assert {
+ ($cond:expr $(,)?) => {{
+ if !$cond {
+ $crate::build_error(concat!("assertion failed: ", stringify!($cond)));
+ }
+ }};
+ ($cond:expr, $msg:expr) => {{
+ if !$cond {
+ $crate::build_error($msg);
+ }
+ }};
+}