[PATCH v3 4/4] rust: make `build_assert` module the home of related macros
From: Gary Guo <gary@kernel.org>
Date: 2026-03-19 12:17:53
Also in:
dri-devel, driver-core, lkml, nouveau, rust-for-linux
Subsystem:
atomic infrastructure, core driver for nvidia gpus [rust], device i/o & irq [rust], dma mapping & scatterlist api [rust], drm drivers, drm drivers and common infrastructure [rust], ethernet phy library [rust], locking primitives, rust, rust [num], the rest, xarray api [rust] · Maintainers:
Will Deacon, Peter Zijlstra, Boqun Feng, Danilo Krummrich, Alexandre Courbot, Alice Ryhl, Daniel Almeida, David Airlie, Simona Vetter, FUJITA Tomonori, Ingo Molnar, Miguel Ojeda, Linus Torvalds, Tamir Duberstein, Andreas Hindborg
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> --- drivers/gpu/nova-core/bitfield.rs | 4 ++-- drivers/gpu/nova-core/num.rs | 2 +- rust/kernel/build_assert.rs | 19 ++++++++++++------- rust/kernel/dma.rs | 5 +++-- rust/kernel/io/register.rs | 19 ++++++++++++------- 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/internal.rs | 9 ++++++--- rust/kernel/sync/atomic/predefine.rs | 2 +- rust/kernel/sync/locked_by.rs | 2 +- rust/kernel/sync/refcount.rs | 8 +++++--- rust/kernel/xarray.rs | 10 ++++++++-- 15 files changed, 61 insertions(+), 36 deletions(-)
diff --git a/drivers/gpu/nova-core/bitfield.rs b/drivers/gpu/nova-core/bitfield.rs
index 16e143658c51..c3e1235ad7fb 100644
--- a/drivers/gpu/nova-core/bitfield.rs
+++ b/drivers/gpu/nova-core/bitfield.rs@@ -170,7 +170,7 @@ impl $name { (@check_field_bounds $hi:tt:$lo:tt $field:ident as bool) => { #[allow(clippy::eq_op)] const _: () = { - ::kernel::build_assert!( + ::kernel::build_assert::build_assert!( $hi == $lo, concat!("boolean field `", stringify!($field), "` covers more than one bit") );
@@ -181,7 +181,7 @@ impl $name { (@check_field_bounds $hi:tt:$lo:tt $field:ident as $type:tt) => { #[allow(clippy::eq_op)] const _: () = { - ::kernel::build_assert!( + ::kernel::build_assert::build_assert!( $hi >= $lo, concat!("field `", stringify!($field), "`'s MSB is smaller than its LSB") );
diff --git a/drivers/gpu/nova-core/num.rs b/drivers/gpu/nova-core/num.rs
index c952a834e662..329169b21b28 100644
--- a/drivers/gpu/nova-core/num.rs
+++ b/drivers/gpu/nova-core/num.rs@@ -49,7 +49,7 @@ macro_rules! impl_safe_as { #[allow(unused)] #[inline(always)] pub(crate) const fn [<$from _as_ $into>](value: $from) -> $into { - kernel::static_assert!(size_of::<$into>() >= size_of::<$from>()); + ::kernel::build_assert::static_assert!(size_of::<$into>() >= size_of::<$from>()); value as $into }
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
index 726d0b76ca2b..11ac83e515ac 100644
--- a/rust/kernel/build_assert.rs
+++ b/rust/kernel/build_assert.rs@@ -61,15 +61,16 @@ //! 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. +#[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) }}; }
@@ -200,15 +204,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..f209fb334c85 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs@@ -5,12 +5,13 @@ //! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h) use crate::{ - bindings, build_assert, device, + bindings, + 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/register.rs b/rust/kernel/io/register.rs
index abc49926abfe..2133d3e62fd5 100644
--- a/rust/kernel/io/register.rs
+++ b/rust/kernel/io/register.rs@@ -108,9 +108,10 @@ use core::marker::PhantomData; -use crate::io::IoLoc; - -use kernel::build_assert; +use crate::{ + build_assert::build_assert, + io::IoLoc, // +}; /// Trait implemented by all registers. pub trait Register: Sized {
@@ -872,7 +873,7 @@ macro_rules! register { @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr, stride = $stride:expr ] @ $offset:literal { $($fields:tt)* } ) => { - ::kernel::static_assert!(::core::mem::size_of::<$storage>() <= $stride); + $crate::build_assert::static_assert!(::core::mem::size_of::<$storage>() <= $stride); $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storage) { $($fields)* }); $crate::register!(@io_base $name($storage) @ $offset);
@@ -895,7 +896,9 @@ macro_rules! register { @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) => $alias:ident [ $idx:expr ] { $($fields:tt)* } ) => { - ::kernel::static_assert!($idx < <$alias as $crate::io::register::RegisterArray>::SIZE); + $crate::build_assert::static_assert!( + $idx < <$alias as $crate::io::register::RegisterArray>::SIZE + ); $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storage) { $($fields)* }); $crate::register!(
@@ -912,7 +915,7 @@ macro_rules! register { [ $size:expr, stride = $stride:expr ] @ $base:ident + $offset:literal { $($fields:tt)* } ) => { - ::kernel::static_assert!(::core::mem::size_of::<$storage>() <= $stride); + $crate::build_assert::static_assert!(::core::mem::size_of::<$storage>() <= $stride); $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storage) { $($fields)* }); $crate::register!(@io_base $name($storage) @ $offset);
@@ -938,7 +941,9 @@ macro_rules! register { @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) => $base:ident + $alias:ident [ $idx:expr ] { $($fields:tt)* } ) => { - ::kernel::static_assert!($idx < <$alias as $crate::io::register::RegisterArray>::SIZE); + $crate::build_assert::static_assert!( + $idx < <$alias as $crate::io::register::RegisterArray>::SIZE + ); $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storage) { $($fields)* }); $crate::register!(
diff --git a/rust/kernel/io/resource.rs b/rust/kernel/io/resource.rs
index b7ac9faf141d..17b0c174cfc5 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); + 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 f9f90d6ec482..dafe77782d79 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/internal.rs b/rust/kernel/sync/atomic/internal.rs
index ad810c2172ec..9c8a7a203abd 100644
--- a/rust/kernel/sync/atomic/internal.rs
+++ b/rust/kernel/sync/atomic/internal.rs@@ -4,8 +4,11 @@ //! //! Provides 1:1 mapping to the C atomic operations. -use crate::bindings; -use crate::macros::paste; +use crate::{ + bindings, + build_assert::static_assert, + macros::paste, // +}; use core::cell::UnsafeCell; use ffi::c_void;
@@ -46,7 +49,7 @@ pub trait AtomicImpl: Sized + Copy + private::Sealed { // In the future when a CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n architecture plans to support Rust, the // load/store helpers that guarantee atomicity against RmW operations (usually via a lock) need to // be added. -crate::static_assert!( +static_assert!( cfg!(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW), "The current implementation of atomic i8/i16/ptr relies on the architecure being \ ARCH_SUPPORTS_ATOMIC_RMW"
diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs
index 1d53834fcb12..2c92de040f03 100644
--- a/rust/kernel/sync/atomic/predefine.rs
+++ b/rust/kernel/sync/atomic/predefine.rs@@ -2,7 +2,7 @@ //! Pre-defined atomic types -use crate::static_assert; +use crate::prelude::*; use core::mem::{align_of, size_of}; use ffi::c_void;
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..8fc4eab02642 100644
--- a/rust/kernel/xarray.rs
+++ b/rust/kernel/xarray.rs@@ -5,10 +5,16 @@ //! 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