* [PATCH v2 1/4] rust: move `static_assert` into `build_assert`
2026-03-16 15:07 [PATCH v2 0/4] add `const_assert!` macro and rework documentation Gary Guo
@ 2026-03-16 15:07 ` Gary Guo
2026-03-16 15:07 ` [PATCH v2 2/4] rust: add `const_assert!` macro Gary Guo
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Gary Guo @ 2026-03-16 15:07 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich
Cc: Yury Norov, rust-for-linux, linux-kernel
From: Gary Guo <gary@garyguo.net>
Conceptually, `static_assert` is also a build-time assertion that occurs
earlier in the pipeline. Conslidate the implementation so that we can use
this as the canonical place to add more useful build-time assertions.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/kernel/build_assert.rs | 40 +++++++++++++++++++++++++++++++++---
rust/kernel/lib.rs | 1 -
rust/kernel/prelude.rs | 4 +---
rust/kernel/static_assert.rs | 39 -----------------------------------
4 files changed, 38 insertions(+), 46 deletions(-)
delete mode 100644 rust/kernel/static_assert.rs
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
index f8124dbc663f..d464494d430a 100644
--- a/rust/kernel/build_assert.rs
+++ b/rust/kernel/build_assert.rs
@@ -1,10 +1,46 @@
// SPDX-License-Identifier: GPL-2.0
-//! Build-time assert.
+//! Various assertions that happen during build-time.
#[doc(hidden)]
pub use build_error::build_error;
+/// Static assert (i.e. compile-time assert).
+///
+/// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`].
+///
+/// An optional panic message can be supplied after the expression.
+/// Currently only a string literal without formatting is supported
+/// due to constness limitations of the [`assert!`] macro.
+///
+/// The feature may be added to Rust in the future: see [RFC 2790].
+///
+/// [`_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
+///
+/// # Examples
+///
+/// ```
+/// static_assert!(42 > 24);
+/// static_assert!(core::mem::size_of::<u8>() == 1);
+///
+/// const X: &[u8] = b"bar";
+/// static_assert!(X[1] == b'a');
+///
+/// const fn f(x: i32) -> i32 {
+/// x + 2
+/// }
+/// static_assert!(f(40) == 42);
+/// static_assert!(f(40) == 42, "f(x) must add 2 to the given input.");
+/// ```
+#[macro_export]
+macro_rules! static_assert {
+ ($condition:expr $(,$arg:literal)?) => {
+ const _: () = ::core::assert!($condition $(,$arg)?);
+ };
+}
+
/// 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.
@@ -74,8 +110,6 @@ macro_rules! build_error {
/// assert!(n > 1); // Run-time check
/// }
/// ```
-///
-/// [`static_assert!`]: crate::static_assert!
#[macro_export]
macro_rules! build_assert {
($cond:expr $(,)?) => {{
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index d93292d47420..d590f7af54bf 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -148,7 +148,6 @@
pub mod slice;
#[cfg(CONFIG_SOC_BUS)]
pub mod soc;
-mod static_assert;
#[doc(hidden)]
pub mod std_vendor;
pub mod str;
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 2877e3f7b6d3..c7e91b80d301 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -29,7 +29,7 @@
pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};
-pub use super::{build_assert, build_error};
+pub use super::{build_assert, build_error, static_assert};
// `super::std_vendor` is hidden, which makes the macro inline for some reason.
#[doc(no_inline)]
@@ -39,8 +39,6 @@
pub use super::{try_init, try_pin_init};
-pub use super::static_assert;
-
pub use super::error::{code::*, Error, Result};
pub use super::{str::CStrExt as _, ThisModule};
diff --git a/rust/kernel/static_assert.rs b/rust/kernel/static_assert.rs
deleted file mode 100644
index a57ba14315a0..000000000000
--- a/rust/kernel/static_assert.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-//! Static assert.
-
-/// Static assert (i.e. compile-time assert).
-///
-/// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`].
-///
-/// An optional panic message can be supplied after the expression.
-/// Currently only a string literal without formatting is supported
-/// due to constness limitations of the [`assert!`] macro.
-///
-/// The feature may be added to Rust in the future: see [RFC 2790].
-///
-/// [`_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
-///
-/// # Examples
-///
-/// ```
-/// static_assert!(42 > 24);
-/// static_assert!(core::mem::size_of::<u8>() == 1);
-///
-/// const X: &[u8] = b"bar";
-/// static_assert!(X[1] == b'a');
-///
-/// const fn f(x: i32) -> i32 {
-/// x + 2
-/// }
-/// static_assert!(f(40) == 42);
-/// static_assert!(f(40) == 42, "f(x) must add 2 to the given input.");
-/// ```
-#[macro_export]
-macro_rules! static_assert {
- ($condition:expr $(,$arg:literal)?) => {
- const _: () = ::core::assert!($condition $(,$arg)?);
- };
-}
--
2.51.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v2 2/4] rust: add `const_assert!` macro
2026-03-16 15:07 [PATCH v2 0/4] add `const_assert!` macro and rework documentation Gary Guo
2026-03-16 15:07 ` [PATCH v2 1/4] rust: move `static_assert` into `build_assert` Gary Guo
@ 2026-03-16 15:07 ` Gary Guo
2026-03-16 17:34 ` Yury Norov
2026-03-16 15:07 ` [PATCH v2 3/4] rust: rework `build_assert!` documentation Gary Guo
2026-03-16 15:07 ` [PATCH v2 4/4] rust: make `build_assert` module the home of related macros Gary Guo
3 siblings, 1 reply; 9+ messages in thread
From: Gary Guo @ 2026-03-16 15:07 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot, Yury Norov,
Nathan Chancellor, Nicolas Schier
Cc: rust-for-linux, linux-kernel, linux-kbuild
From: Gary Guo <gary@garyguo.net>
The macro is a more powerful version of `static_assert!` for use inside
function contexts. This is powered by inline consts, so enable the feature
for old compiler versions that does not have it stably.
While it is possible already to write `const { assert!(...) }`, this
provides a short hand that is more uniform with other assertions. It also
formats nicer with rustfmt where it will not be formatted into multiple
lines.
Two users that would route via the Rust tree are converted.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/kernel/build_assert.rs | 24 ++++++++++++++++++++++++
rust/kernel/num/bounded.rs | 24 +++++++++---------------
rust/kernel/prelude.rs | 7 ++++++-
rust/kernel/ptr.rs | 12 ++++++------
scripts/Makefile.build | 5 +++--
5 files changed, 48 insertions(+), 24 deletions(-)
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
index d464494d430a..51c0f85a9014 100644
--- a/rust/kernel/build_assert.rs
+++ b/rust/kernel/build_assert.rs
@@ -41,6 +41,30 @@ macro_rules! static_assert {
};
}
+/// Assertion during constant evaluation.
+///
+/// This is a more powerful version of [`static_assert!`] that can refer to generics inside 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.
+///
+/// # Examples
+///
+/// ```
+/// fn foo<const N: usize>() {
+/// const_assert!(N > 1);
+/// }
+///
+/// fn bar<T>() {
+/// const_assert!(size_of::<T>() > 0, "T cannot be ZST");
+/// }
+/// ```
+#[macro_export]
+macro_rules! const_assert {
+ ($condition:expr $(,$arg:literal)?) => {
+ const { ::core::assert!($condition $(,$arg)?) };
+ };
+}
+
/// 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.
diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs
index fa81acbdc8c2..54d0ce3ba595 100644
--- a/rust/kernel/num/bounded.rs
+++ b/rust/kernel/num/bounded.rs
@@ -255,9 +255,7 @@ impl<const N: u32> Bounded<$type, N> {
/// ```
pub const fn new<const VALUE: $type>() -> Self {
// Statically assert that `VALUE` fits within the set number of bits.
- const {
- assert!(fits_within!(VALUE, $type, N));
- }
+ const_assert!(fits_within!(VALUE, $type, N));
// SAFETY: `fits_within` confirmed that `VALUE` can be represented within
// `N` bits.
@@ -287,12 +285,10 @@ impl<T, const N: u32> Bounded<T, N>
/// The caller must ensure that `value` can be represented within `N` bits.
const unsafe fn __new(value: T) -> Self {
// Enforce the type invariants.
- const {
- // `N` cannot be zero.
- assert!(N != 0);
- // The backing type is at least as large as `N` bits.
- assert!(N <= T::BITS);
- }
+ // `N` cannot be zero.
+ const_assert!(N != 0);
+ // The backing type is at least as large as `N` bits.
+ const_assert!(N <= T::BITS);
// INVARIANT: The caller ensures `value` fits within `N` bits.
Self(value)
@@ -406,12 +402,10 @@ pub fn get(self) -> T {
/// assert_eq!(larger_v, v);
/// ```
pub const fn extend<const M: u32>(self) -> Bounded<T, M> {
- const {
- assert!(
- M >= N,
- "Requested number of bits is less than the current representation."
- );
- }
+ const_assert!(
+ M >= N,
+ "Requested number of bits is less than the current representation."
+ );
// SAFETY: The value did fit within `N` bits, so it will all the more fit within
// the larger `M` bits.
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index c7e91b80d301..6a54597fa0a2 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -29,7 +29,12 @@
pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};
-pub use super::{build_assert, build_error, static_assert};
+pub use super::{
+ build_assert,
+ build_error,
+ const_assert,
+ static_assert, //
+};
// `super::std_vendor` is hidden, which makes the macro inline for some reason.
#[doc(no_inline)]
diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
index bdc2d79ff669..d05e5888e80c 100644
--- a/rust/kernel/ptr.rs
+++ b/rust/kernel/ptr.rs
@@ -11,6 +11,8 @@
};
use core::num::NonZero;
+use crate::const_assert;
+
/// Type representing an alignment, which is always a power of two.
///
/// It is used to validate that a given value is a valid alignment, and to perform masking and
@@ -44,12 +46,10 @@ impl Alignment {
/// ```
#[inline(always)]
pub const fn new<const ALIGN: usize>() -> Self {
- const {
- assert!(
- ALIGN.is_power_of_two(),
- "Provided alignment is not a power of two."
- );
- }
+ const_assert!(
+ ALIGN.is_power_of_two(),
+ "Provided alignment is not a power of two."
+ );
// INVARIANT: `align` is a power of two.
// SAFETY: `align` is a power of two, and thus non-zero.
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 3652b85be545..960b4630cb2c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -310,7 +310,8 @@ $(obj)/%.lst: $(obj)/%.c FORCE
# The features in this list are the ones allowed for non-`rust/` code.
#
-# - Stable since Rust 1.79.0: `feature(slice_ptr_len)`.
+# - Stable since Rust 1.79.0: `feature(inline_const)`,
+# `feature(slice_ptr_len)`,
# - Stable since Rust 1.81.0: `feature(lint_reasons)`.
# - Stable since Rust 1.82.0: `feature(asm_const)`,
# `feature(offset_of_nested)`, `feature(raw_ref_op)`.
@@ -321,7 +322,7 @@ $(obj)/%.lst: $(obj)/%.c FORCE
#
# Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
# the unstable features in use.
-rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,slice_ptr_len,strict_provenance,used_with_arg
+rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,inline_const,lint_reasons,offset_of_nested,raw_ref_op,slice_ptr_len,strict_provenance,used_with_arg
# `--out-dir` is required to avoid temporaries being created by `rustc` in the
# current working directory, which may be not accessible in the out-of-tree
--
2.51.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 2/4] rust: add `const_assert!` macro
2026-03-16 15:07 ` [PATCH v2 2/4] rust: add `const_assert!` macro Gary Guo
@ 2026-03-16 17:34 ` Yury Norov
2026-03-16 18:35 ` Miguel Ojeda
0 siblings, 1 reply; 9+ messages in thread
From: Yury Norov @ 2026-03-16 17:34 UTC (permalink / raw)
To: Gary Guo
Cc: Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Alexandre Courbot, Yury Norov, Nathan Chancellor, Nicolas Schier,
rust-for-linux, linux-kernel, linux-kbuild
On Mon, Mar 16, 2026 at 03:07:13PM +0000, Gary Guo wrote:
> From: Gary Guo <gary@garyguo.net>
>
> The macro is a more powerful version of `static_assert!` for use inside
> function contexts. This is powered by inline consts, so enable the feature
> for old compiler versions that does not have it stably.
>
> While it is possible already to write `const { assert!(...) }`, this
> provides a short hand that is more uniform with other assertions. It also
> formats nicer with rustfmt where it will not be formatted into multiple
> lines.
>
> Two users that would route via the Rust tree are converted.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
> ---
> rust/kernel/build_assert.rs | 24 ++++++++++++++++++++++++
> rust/kernel/num/bounded.rs | 24 +++++++++---------------
> rust/kernel/prelude.rs | 7 ++++++-
> rust/kernel/ptr.rs | 12 ++++++------
> scripts/Makefile.build | 5 +++--
> 5 files changed, 48 insertions(+), 24 deletions(-)
>
> diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
> index d464494d430a..51c0f85a9014 100644
> --- a/rust/kernel/build_assert.rs
> +++ b/rust/kernel/build_assert.rs
> @@ -41,6 +41,30 @@ macro_rules! static_assert {
> };
> }
>
> +/// Assertion during constant evaluation.
> +///
> +/// This is a more powerful version of [`static_assert!`] that can refer to generics inside functions
This line is 101 lanes. Can you split it?
> +/// 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.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// fn foo<const N: usize>() {
> +/// const_assert!(N > 1);
> +/// }
> +///
> +/// fn bar<T>() {
> +/// const_assert!(size_of::<T>() > 0, "T cannot be ZST");
> +/// }
> +/// ```
> +#[macro_export]
> +macro_rules! const_assert {
> + ($condition:expr $(,$arg:literal)?) => {
> + const { ::core::assert!($condition $(,$arg)?) };
> + };
> +}
> +
> /// 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.
> diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs
> index fa81acbdc8c2..54d0ce3ba595 100644
> --- a/rust/kernel/num/bounded.rs
> +++ b/rust/kernel/num/bounded.rs
> @@ -255,9 +255,7 @@ impl<const N: u32> Bounded<$type, N> {
> /// ```
> pub const fn new<const VALUE: $type>() -> Self {
> // Statically assert that `VALUE` fits within the set number of bits.
> - const {
> - assert!(fits_within!(VALUE, $type, N));
> - }
> + const_assert!(fits_within!(VALUE, $type, N));
>
> // SAFETY: `fits_within` confirmed that `VALUE` can be represented within
> // `N` bits.
> @@ -287,12 +285,10 @@ impl<T, const N: u32> Bounded<T, N>
> /// The caller must ensure that `value` can be represented within `N` bits.
> const unsafe fn __new(value: T) -> Self {
> // Enforce the type invariants.
> - const {
> - // `N` cannot be zero.
> - assert!(N != 0);
> - // The backing type is at least as large as `N` bits.
> - assert!(N <= T::BITS);
> - }
> + // `N` cannot be zero.
> + const_assert!(N != 0);
> + // The backing type is at least as large as `N` bits.
> + const_assert!(N <= T::BITS);
>
> // INVARIANT: The caller ensures `value` fits within `N` bits.
> Self(value)
> @@ -406,12 +402,10 @@ pub fn get(self) -> T {
> /// assert_eq!(larger_v, v);
> /// ```
> pub const fn extend<const M: u32>(self) -> Bounded<T, M> {
> - const {
> - assert!(
> - M >= N,
> - "Requested number of bits is less than the current representation."
> - );
> - }
> + const_assert!(
> + M >= N,
> + "Requested number of bits is less than the current representation."
> + );
>
> // SAFETY: The value did fit within `N` bits, so it will all the more fit within
> // the larger `M` bits.
> diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
> index c7e91b80d301..6a54597fa0a2 100644
> --- a/rust/kernel/prelude.rs
> +++ b/rust/kernel/prelude.rs
> @@ -29,7 +29,12 @@
>
> pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};
>
> -pub use super::{build_assert, build_error, static_assert};
> +pub use super::{
> + build_assert,
> + build_error,
> + const_assert,
> + static_assert, //
> +};
>
> // `super::std_vendor` is hidden, which makes the macro inline for some reason.
> #[doc(no_inline)]
> diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
> index bdc2d79ff669..d05e5888e80c 100644
> --- a/rust/kernel/ptr.rs
> +++ b/rust/kernel/ptr.rs
> @@ -11,6 +11,8 @@
> };
> use core::num::NonZero;
>
> +use crate::const_assert;
> +
> /// Type representing an alignment, which is always a power of two.
> ///
> /// It is used to validate that a given value is a valid alignment, and to perform masking and
> @@ -44,12 +46,10 @@ impl Alignment {
> /// ```
> #[inline(always)]
> pub const fn new<const ALIGN: usize>() -> Self {
> - const {
> - assert!(
> - ALIGN.is_power_of_two(),
> - "Provided alignment is not a power of two."
> - );
> - }
> + const_assert!(
> + ALIGN.is_power_of_two(),
> + "Provided alignment is not a power of two."
> + );
>
> // INVARIANT: `align` is a power of two.
> // SAFETY: `align` is a power of two, and thus non-zero.
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 3652b85be545..960b4630cb2c 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -310,7 +310,8 @@ $(obj)/%.lst: $(obj)/%.c FORCE
>
> # The features in this list are the ones allowed for non-`rust/` code.
> #
> -# - Stable since Rust 1.79.0: `feature(slice_ptr_len)`.
> +# - Stable since Rust 1.79.0: `feature(inline_const)`,
> +# `feature(slice_ptr_len)`,
> # - Stable since Rust 1.81.0: `feature(lint_reasons)`.
> # - Stable since Rust 1.82.0: `feature(asm_const)`,
> # `feature(offset_of_nested)`, `feature(raw_ref_op)`.
> @@ -321,7 +322,7 @@ $(obj)/%.lst: $(obj)/%.c FORCE
> #
> # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
> # the unstable features in use.
> -rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,slice_ptr_len,strict_provenance,used_with_arg
> +rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,inline_const,lint_reasons,offset_of_nested,raw_ref_op,slice_ptr_len,strict_provenance,used_with_arg
Same here. Miguel mentioned in the other thread that newer version of
rust will make this list shorter, but once that didn't happen, let's
follow rules?
>
> # `--out-dir` is required to avoid temporaries being created by `rustc` in the
> # current working directory, which may be not accessible in the out-of-tree
> --
> 2.51.2
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v2 2/4] rust: add `const_assert!` macro
2026-03-16 17:34 ` Yury Norov
@ 2026-03-16 18:35 ` Miguel Ojeda
0 siblings, 0 replies; 9+ messages in thread
From: Miguel Ojeda @ 2026-03-16 18:35 UTC (permalink / raw)
To: Yury Norov
Cc: Gary Guo, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Alexandre Courbot, Yury Norov,
Nathan Chancellor, Nicolas Schier, rust-for-linux, linux-kernel,
linux-kbuild
On Mon, Mar 16, 2026 at 6:34 PM Yury Norov <ynorov@nvidia.com> wrote:
>
> Same here. Miguel mentioned in the other thread that newer version of
> rust will make this list shorter, but once that didn't happen, let's
> follow rules?
It is not a hard limit, and there are a couple other nearby lines even
longer than this one. The new one will be 82 columns long (including
the addition here).
To be honest, I don't think it is worth making this patch series more
involved for a single line that will be temporary (or it may not even
happen depending on the order things land).
If we want to do it, then I would suggest doing it in another patch
(and likely in another patch series too).
Cheers,
Miguel
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/4] rust: rework `build_assert!` documentation
2026-03-16 15:07 [PATCH v2 0/4] add `const_assert!` macro and rework documentation Gary Guo
2026-03-16 15:07 ` [PATCH v2 1/4] rust: move `static_assert` into `build_assert` Gary Guo
2026-03-16 15:07 ` [PATCH v2 2/4] rust: add `const_assert!` macro Gary Guo
@ 2026-03-16 15:07 ` Gary Guo
2026-03-16 17:36 ` Yury Norov
2026-03-16 15:07 ` [PATCH v2 4/4] rust: make `build_assert` module the home of related macros Gary Guo
3 siblings, 1 reply; 9+ messages in thread
From: Gary Guo @ 2026-03-16 15:07 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich
Cc: Yury Norov, rust-for-linux, linux-kernel
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.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/kernel/build_assert.rs | 113 +++++++++++++++++++++++++++---------
rust/kernel/lib.rs | 1 -
2 files changed, 87 insertions(+), 27 deletions(-)
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
index 51c0f85a9014..acdfcbeb73f3 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 {
/// 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,28 @@ 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.
+/// 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)]
+/// 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(1);
/// }
-/// ```
///
-/// 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
+/// 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 d590f7af54bf..1857e06e51f3 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -77,7 +77,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
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 3/4] rust: rework `build_assert!` documentation
2026-03-16 15:07 ` [PATCH v2 3/4] rust: rework `build_assert!` documentation Gary Guo
@ 2026-03-16 17:36 ` Yury Norov
0 siblings, 0 replies; 9+ messages in thread
From: Yury Norov @ 2026-03-16 17:36 UTC (permalink / raw)
To: Gary Guo
Cc: Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Yury Norov, rust-for-linux, linux-kernel
On Mon, Mar 16, 2026 at 03:07:14PM +0000, Gary Guo wrote:
> 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.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
> ---
> rust/kernel/build_assert.rs | 113 +++++++++++++++++++++++++++---------
> rust/kernel/lib.rs | 1 -
> 2 files changed, 87 insertions(+), 27 deletions(-)
>
> diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
> index 51c0f85a9014..acdfcbeb73f3 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, //
> +};
Solid wording, thank you!
For the series:
Reviewed-by: Yury Norov <ynorov@nvidia.com>
> #[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 {
> /// 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,28 @@ 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.
> +/// 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)]
> +/// 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(1);
> /// }
> -/// ```
> ///
> -/// 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
> +/// 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 d590f7af54bf..1857e06e51f3 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -77,7 +77,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
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 4/4] rust: make `build_assert` module the home of related macros
2026-03-16 15:07 [PATCH v2 0/4] add `const_assert!` macro and rework documentation Gary Guo
` (2 preceding siblings ...)
2026-03-16 15:07 ` [PATCH v2 3/4] rust: rework `build_assert!` documentation Gary Guo
@ 2026-03-16 15:07 ` Gary Guo
2026-03-16 17:44 ` Danilo Krummrich
3 siblings, 1 reply; 9+ messages in thread
From: Gary Guo @ 2026-03-16 15:07 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Abdiel Janulgue, Daniel Almeida, Robin Murphy,
FUJITA Tomonori, Alexandre Courbot, Yury Norov, Will Deacon,
Peter Zijlstra, Mark Rutland, Ingo Molnar, Waiman Long,
Tamir Duberstein
Cc: rust-for-linux, linux-kernel, driver-core, netdev
From: Gary Guo <gary@garyguo.net>
Given the macro scoping rules, all macros are rendered 3 times, in the
module, in the top-level of kernel crate, and in the prelude.
Add `#[doc(no_inline)]` to the prelude so it just shows up as re-export.
Add `#[doc(hidden)]` to the macro definition and `#[doc(inline)]` to the
re-export inside `build_assert` module so the top-level items are hidden.
Signed-off-by: Gary Guo <gary@garyguo.net>
---
rust/kernel/build_assert.rs | 19 ++++++++++++-------
rust/kernel/dma.rs | 6 ++++--
rust/kernel/io/resource.rs | 2 +-
rust/kernel/ioctl.rs | 2 +-
rust/kernel/net/phy/reg.rs | 8 +++++---
rust/kernel/num/bounded.rs | 2 +-
rust/kernel/prelude.rs | 3 ++-
rust/kernel/sync/atomic/predefine.rs | 3 +--
rust/kernel/sync/locked_by.rs | 2 +-
rust/kernel/sync/refcount.rs | 8 +++++---
rust/kernel/xarray.rs | 6 ++++--
11 files changed, 37 insertions(+), 24 deletions(-)
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
index acdfcbeb73f3..5d671761c446 100644
--- a/rust/kernel/build_assert.rs
+++ b/rust/kernel/build_assert.rs
@@ -61,15 +61,16 @@
//! 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.
+#[doc(inline)]
pub use crate::{
- build_assert,
+ build_assert_macro as build_assert,
build_error,
const_assert,
static_assert, //
};
#[doc(hidden)]
-pub use build_error::build_error;
+pub use build_error::build_error as build_error_fn;
/// Static assert (i.e. compile-time assert).
///
@@ -105,6 +106,7 @@
/// static_assert!(f(40) == 42, "f(x) must add 2 to the given input.");
/// ```
#[macro_export]
+#[doc(hidden)]
macro_rules! static_assert {
($condition:expr $(,$arg:literal)?) => {
const _: () = ::core::assert!($condition $(,$arg)?);
@@ -133,6 +135,7 @@ macro_rules! static_assert {
/// }
/// ```
#[macro_export]
+#[doc(hidden)]
macro_rules! const_assert {
($condition:expr $(,$arg:literal)?) => {
const { ::core::assert!($condition $(,$arg)?) };
@@ -157,12 +160,13 @@ macro_rules! const_assert {
/// // foo(usize::MAX); // Fails to compile.
/// ```
#[macro_export]
+#[doc(hidden)]
macro_rules! build_error {
() => {{
- $crate::build_assert::build_error("")
+ $crate::build_assert::build_error_fn("")
}};
($msg:expr) => {{
- $crate::build_assert::build_error($msg)
+ $crate::build_assert::build_error_fn($msg)
}};
}
@@ -196,15 +200,16 @@ macro_rules! build_error {
/// const _: () = const_bar(2);
/// ```
#[macro_export]
-macro_rules! build_assert {
+#[doc(hidden)]
+macro_rules! build_assert_macro {
($cond:expr $(,)?) => {{
if !$cond {
- $crate::build_assert::build_error(concat!("assertion failed: ", stringify!($cond)));
+ $crate::build_assert::build_error_fn(concat!("assertion failed: ", stringify!($cond)));
}
}};
($cond:expr, $msg:expr) => {{
if !$cond {
- $crate::build_assert::build_error($msg);
+ $crate::build_assert::build_error_fn($msg);
}
}};
}
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index a396f8435739..bef3f33cf2ea 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -5,12 +5,14 @@
//! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h)
use crate::{
- bindings, build_assert, device,
+ bindings,
+ build_assert::build_assert,
+ device,
device::{Bound, Core},
error::{to_result, Result},
prelude::*,
sync::aref::ARef,
- transmute::{AsBytes, FromBytes},
+ transmute::{AsBytes, FromBytes}, //
};
use core::ptr::NonNull;
diff --git a/rust/kernel/io/resource.rs b/rust/kernel/io/resource.rs
index b7ac9faf141d..9cb18ce1c479 100644
--- a/rust/kernel/io/resource.rs
+++ b/rust/kernel/io/resource.rs
@@ -229,7 +229,7 @@ impl Flags {
// Always inline to optimize out error path of `build_assert`.
#[inline(always)]
const fn new(value: u32) -> Self {
- crate::build_assert!(value as u64 <= c_ulong::MAX as u64);
+ crate::build_assert::build_assert!(value as u64 <= c_ulong::MAX as u64);
Flags(value as c_ulong)
}
}
diff --git a/rust/kernel/ioctl.rs b/rust/kernel/ioctl.rs
index 2fc7662339e5..5bb5b48cf949 100644
--- a/rust/kernel/ioctl.rs
+++ b/rust/kernel/ioctl.rs
@@ -6,7 +6,7 @@
#![expect(non_snake_case)]
-use crate::build_assert;
+use crate::build_assert::build_assert;
/// Build an ioctl number, analogous to the C macro of the same name.
#[inline(always)]
diff --git a/rust/kernel/net/phy/reg.rs b/rust/kernel/net/phy/reg.rs
index a7db0064cb7d..80e22c264ea8 100644
--- a/rust/kernel/net/phy/reg.rs
+++ b/rust/kernel/net/phy/reg.rs
@@ -9,9 +9,11 @@
//! defined in IEEE 802.3.
use super::Device;
-use crate::build_assert;
-use crate::error::*;
-use crate::uapi;
+use crate::{
+ build_assert::build_assert,
+ error::*,
+ uapi, //
+};
mod private {
/// Marker that a trait cannot be implemented outside of this crate
diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs
index 54d0ce3ba595..c09abfab1ce2 100644
--- a/rust/kernel/num/bounded.rs
+++ b/rust/kernel/num/bounded.rs
@@ -364,7 +364,7 @@ pub fn try_new(value: T) -> Option<Self> {
// Always inline to optimize out error path of `build_assert`.
#[inline(always)]
pub fn from_expr(expr: T) -> Self {
- crate::build_assert!(
+ crate::build_assert::build_assert!(
fits_within(expr, N),
"Requested value larger than maximal representable value."
);
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 6a54597fa0a2..baf8f6a94ea1 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -29,7 +29,8 @@
pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};
-pub use super::{
+#[doc(no_inline)]
+pub use crate::build_assert::{
build_assert,
build_error,
const_assert,
diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs
index 67a0406d3ea4..77f4a5c91a80 100644
--- a/rust/kernel/sync/atomic/predefine.rs
+++ b/rust/kernel/sync/atomic/predefine.rs
@@ -2,8 +2,7 @@
//! Pre-defined atomic types
-use crate::static_assert;
-use core::mem::{align_of, size_of};
+use crate::prelude::*;
// Ensure size and alignment requirements are checked.
static_assert!(size_of::<bool>() == size_of::<i8>());
diff --git a/rust/kernel/sync/locked_by.rs b/rust/kernel/sync/locked_by.rs
index 61f100a45b35..fb4a1430b3b4 100644
--- a/rust/kernel/sync/locked_by.rs
+++ b/rust/kernel/sync/locked_by.rs
@@ -3,7 +3,7 @@
//! A wrapper for data protected by a lock that does not wrap it.
use super::{lock::Backend, lock::Lock};
-use crate::build_assert;
+use crate::build_assert::build_assert;
use core::{cell::UnsafeCell, mem::size_of, ptr};
/// Allows access to some data to be serialised by a lock that does not wrap it.
diff --git a/rust/kernel/sync/refcount.rs b/rust/kernel/sync/refcount.rs
index 6c7ae8b05a0b..23a5d201f343 100644
--- a/rust/kernel/sync/refcount.rs
+++ b/rust/kernel/sync/refcount.rs
@@ -4,9 +4,11 @@
//!
//! C header: [`include/linux/refcount.h`](srctree/include/linux/refcount.h)
-use crate::build_assert;
-use crate::sync::atomic::Atomic;
-use crate::types::Opaque;
+use crate::{
+ build_assert::build_assert,
+ sync::atomic::Atomic,
+ types::Opaque, //
+};
/// Atomic reference counter.
///
diff --git a/rust/kernel/xarray.rs b/rust/kernel/xarray.rs
index a49d6db28845..50b9feca7f10 100644
--- a/rust/kernel/xarray.rs
+++ b/rust/kernel/xarray.rs
@@ -5,10 +5,12 @@
//! C header: [`include/linux/xarray.h`](srctree/include/linux/xarray.h)
use crate::{
- alloc, bindings, build_assert,
+ alloc,
+ bindings,
+ build_assert::build_assert,
error::{Error, Result},
ffi::c_void,
- types::{ForeignOwnable, NotThreadSafe, Opaque},
+ types::{ForeignOwnable, NotThreadSafe, Opaque}, //
};
use core::{iter, marker::PhantomData, pin::Pin, ptr::NonNull};
use pin_init::{pin_data, pin_init, pinned_drop, PinInit};
--
2.51.2
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 4/4] rust: make `build_assert` module the home of related macros
2026-03-16 15:07 ` [PATCH v2 4/4] rust: make `build_assert` module the home of related macros Gary Guo
@ 2026-03-16 17:44 ` Danilo Krummrich
0 siblings, 0 replies; 9+ messages in thread
From: Danilo Krummrich @ 2026-03-16 17:44 UTC (permalink / raw)
To: Gary Guo
Cc: Gary Guo, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Abdiel Janulgue, Daniel Almeida, Robin Murphy, FUJITA Tomonori,
Alexandre Courbot, Yury Norov, Will Deacon, Peter Zijlstra,
Mark Rutland, Ingo Molnar, Waiman Long, Tamir Duberstein,
rust-for-linux, linux-kernel, driver-core, netdev
On Mon Mar 16, 2026 at 4:07 PM CET, Gary Guo wrote:
> diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> index a396f8435739..bef3f33cf2ea 100644
> --- a/rust/kernel/dma.rs
> +++ b/rust/kernel/dma.rs
> @@ -5,12 +5,14 @@
> //! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h)
>
> use crate::{
> - bindings, build_assert, device,
> + bindings,
> + build_assert::build_assert,
I think we can just drop it, as we already include prelude.
> + device,
> device::{Bound, Core},
> error::{to_result, Result},
> prelude::*,
> sync::aref::ARef,
> - transmute::{AsBytes, FromBytes},
> + transmute::{AsBytes, FromBytes}, //
> };
> use core::ptr::NonNull;
>
> diff --git a/rust/kernel/io/resource.rs b/rust/kernel/io/resource.rs
> index b7ac9faf141d..9cb18ce1c479 100644
> --- a/rust/kernel/io/resource.rs
> +++ b/rust/kernel/io/resource.rs
> @@ -229,7 +229,7 @@ impl Flags {
> // Always inline to optimize out error path of `build_assert`.
> #[inline(always)]
> const fn new(value: u32) -> Self {
> - crate::build_assert!(value as u64 <= c_ulong::MAX as u64);
> + crate::build_assert::build_assert!(value as u64 <= c_ulong::MAX as u64);
We include the prelude here as well, so this should also be just
build_assert!().
> Flags(value as c_ulong)
> }
> }
^ permalink raw reply [flat|nested] 9+ messages in thread