From: Gary Guo <gary@kernel.org>
To: "Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>
Cc: Yury Norov <ynorov@nvidia.com>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v3 3/4] rust: rework `build_assert!` documentation
Date: Thu, 19 Mar 2026 12:16:47 +0000 [thread overview]
Message-ID: <20260319121653.2975748-4-gary@kernel.org> (raw)
In-Reply-To: <20260319121653.2975748-1-gary@kernel.org>
From: Gary Guo <gary@garyguo.net>
Add a detailed comparison and recommendation of the three types of
build-time assertion macro as module documentation (and un-hide the module
to render them).
The documentation on the macro themselves are simplified to only cover the
scenarios where they should be used; links to the module documentation is
added instead.
Reviewed-by: Yury Norov <ynorov@nvidia.com>
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/kernel/build_assert.rs | 119 ++++++++++++++++++++++++++++--------
rust/kernel/lib.rs | 1 -
2 files changed, 92 insertions(+), 28 deletions(-)
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
index 50b0fc0a80fc..726d0b76ca2b 100644
--- a/rust/kernel/build_assert.rs
+++ b/rust/kernel/build_assert.rs
@@ -1,6 +1,72 @@
// SPDX-License-Identifier: GPL-2.0
//! Various assertions that happen during build-time.
+//!
+//! There are three types of build-time assertions that you can use:
+//! - [`static_assert!`]
+//! - [`const_assert!`]
+//! - [`build_assert!`]
+//!
+//! The ones towards the bottom of the list are more expressive, while the ones towards the top of
+//! the list are more robust and trigger earlier in the compilation pipeline. Therefore, you should
+//! prefer the ones towards the top of the list wherever possible.
+//!
+//! # Choosing the correct assertion
+//!
+//! If you're asserting outside any bodies (e.g. initializers or function bodies), you should use
+//! [`static_assert!`] as it is the only assertion that can be used in that context.
+//!
+//! Inside bodies, if your assertion condition does not depend on any variable or generics, you
+//! should use [`static_assert!`]. If the condition depends on generics, but not variables
+//! (including function arguments), you should use [`const_assert!`]. Otherwise, use
+//! [`build_assert!`]. The same is true regardless if the function is `const fn`.
+//!
+//! ```
+//! // Outside any bodies
+//! static_assert!(core::mem::size_of::<u8>() == 1);
+//! // `const_assert!` and `build_assert!` cannot be used here, they will fail to compile.
+//!
+//! #[inline(always)]
+//! fn foo<const N: usize>(v: usize) {
+//! static_assert!(core::mem::size_of::<u8>() == 1); // Preferred
+//! const_assert!(core::mem::size_of::<u8>() == 1); // Discouraged
+//! build_assert!(core::mem::size_of::<u8>() == 1); // Discouraged
+//!
+//! // `static_assert!(N > 1);` is not allowed
+//! const_assert!(N > 1); // Preferred
+//! build_assert!(N > 1); // Discouraged
+//!
+//! // `static_assert!(v > 1);` is not allowed
+//! // `const_assert!(v > 1);` is not allowed
+//! build_assert!(v > 1); // Works
+//! }
+//! ```
+//!
+//! # Detailed behavior
+//!
+//! `static_assert!()` is equivalent to `static_assert` in C. It requires `expr` to be a constant
+//! expression. This expression cannot refer to any generics. A `static_assert!(expr)` in a program
+//! is always evaluated, regardless if the function it appears in is used or not. This is also the
+//! only usable assertion outside a body.
+//!
+//! `const_assert!()` has no direct C equivalence. It is a more powerful version of
+//! `static_assert!()`, where it may refer to generics in a function. Note that due to the ability
+//! to refer to generics, the assertion is tied to a specific instance of a function. So if it is
+//! used in a generic function that is not instantiated, the assertion will not be checked. For this
+//! reason, `static_assert!()` is preferred wherever possible.
+//!
+//! `build_assert!()` is equivalent to `BUILD_BUG_ON`. It is even more powerful than
+//! `const_assert!()` because it can be used to check tautologies that depend on runtime value (this
+//! is the same as `BUILD_BUG_ON`). However, the assertion failure mechanism can possibly be
+//! undefined symbols and linker errors, it is not developer friendly to debug, so it is recommended
+//! to avoid it and prefer other two assertions where possible.
+
+pub use crate::{
+ build_assert,
+ build_error,
+ const_assert,
+ static_assert, //
+};
#[doc(hidden)]
pub use build_error::build_error;
@@ -15,6 +81,10 @@
///
/// The feature may be added to Rust in the future: see [RFC 2790].
///
+/// You cannot refer to generics or variables with [`static_assert!`]. If you need to refer to
+/// generics, use [`const_assert!`]; if you need to refer to variables, use [`build_assert!`]. See
+/// the [module documentation](self).
+///
/// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert
/// [`static_assert`]: https://en.cppreference.com/w/cpp/language/static_assert
/// [RFC 2790]: https://github.com/rust-lang/rfcs/issues/2790
@@ -47,6 +117,10 @@ macro_rules! static_assert {
/// functions or implementation blocks. However, it also has a limitation where it can only appear
/// in places where statements can appear; for example, you cannot use it as an item in the module.
///
+/// [`static_assert!`] should be preferred if no generics are referred to in the condition. You
+/// cannot refer to variables with [`const_assert!`] (even inside `const fn`); if you need the
+/// capability, use [`build_assert!`]. See the [module documentation](self).
+///
/// # Examples
///
/// ```
@@ -98,41 +172,32 @@ macro_rules! build_error {
/// 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.
+/// When a condition depends on a function argument, the function must be annotated with
+/// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the
+/// function, preventing it from optimizing out the error path.
+///
+/// If the assertion condition does not depend on any variables or generics, you should use
+/// [`static_assert!`]. If the assertion condition does not depend on variables, but does depend on
+/// generics, you should use [`const_assert!`]. See the [module documentation](self).
///
/// # 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
-/// }
/// ```
+/// #[inline(always)] // Important
+/// fn bar(n: usize) {
+/// build_assert!(n > 1);
+/// }
///
-/// 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
+/// fn foo() {
+/// bar(2);
/// }
-/// ```
///
-/// When a condition depends on a function argument, the function must be annotated with
-/// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the
-/// function, preventing it from optimizing out the error path.
-/// ```
-/// #[inline(always)]
-/// fn bar(n: usize) {
-/// // `static_assert!(n > 1);` is not allowed
-/// build_assert!(n > 1); // Build-time check
-/// assert!(n > 1); // Run-time check
+/// #[inline(always)] // Important
+/// const fn const_bar(n: usize) {
+/// build_assert!(n > 1);
/// }
+///
+/// const _: () = const_bar(2);
/// ```
#[macro_export]
macro_rules! build_assert {
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index f427cd3c8cce..d772713459a3 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -80,7 +80,6 @@
#[cfg(CONFIG_BLOCK)]
pub mod block;
pub mod bug;
-#[doc(hidden)]
pub mod build_assert;
pub mod clk;
#[cfg(CONFIG_CONFIGFS_FS)]
--
2.51.2
next prev parent reply other threads:[~2026-03-19 12:17 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-19 12:16 [PATCH v3 0/4] add `const_assert!` macro and rework documentation Gary Guo
2026-03-19 12:16 ` [PATCH v3 1/4] rust: move `static_assert` into `build_assert` Gary Guo
2026-03-19 14:09 ` Alice Ryhl
2026-03-19 12:16 ` [PATCH v3 2/4] rust: add `const_assert!` macro Gary Guo
2026-03-19 14:12 ` Alice Ryhl
2026-03-19 14:26 ` Gary Guo
2026-03-19 14:34 ` Alice Ryhl
2026-03-21 13:05 ` Alexandre Courbot
2026-03-19 12:16 ` Gary Guo [this message]
2026-03-19 14:17 ` [PATCH v3 3/4] rust: rework `build_assert!` documentation Alice Ryhl
2026-03-21 13:05 ` Alexandre Courbot
2026-03-19 12:16 ` [PATCH v3 4/4] rust: make `build_assert` module the home of related macros Gary Guo
2026-03-19 14:14 ` Danilo Krummrich
2026-03-19 14:14 ` Danilo Krummrich
2026-03-19 14:33 ` Alice Ryhl
2026-03-19 14:33 ` Alice Ryhl
2026-03-21 13:05 ` Alexandre Courbot
2026-03-21 13:05 ` Alexandre Courbot
2026-03-21 13:32 ` Gary Guo
2026-03-21 13:32 ` Gary Guo
2026-03-21 13:41 ` Miguel Ojeda
2026-03-21 13:41 ` Miguel Ojeda
2026-03-22 23:36 ` Miguel Ojeda
2026-03-22 23:36 ` Miguel Ojeda
2026-03-23 1:08 ` Alexandre Courbot
2026-03-23 1:08 ` Alexandre Courbot
2026-03-23 1:38 ` Miguel Ojeda
2026-03-23 1:38 ` Miguel Ojeda
2026-03-23 1:50 ` Alexandre Courbot
2026-03-26 12:09 ` FUJITA Tomonori
2026-03-26 12:09 ` FUJITA Tomonori
2026-03-27 18:42 ` Boqun Feng
2026-03-27 18:42 ` Boqun Feng
2026-03-23 0:15 ` Tamir Duberstein
2026-03-23 0:15 ` Tamir Duberstein
2026-03-19 14:15 ` [PATCH v3 0/4] add `const_assert!` macro and rework documentation Danilo Krummrich
2026-03-29 17:28 ` Miguel Ojeda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260319121653.2975748-4-gary@kernel.org \
--to=gary@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=ynorov@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.