rust: make build_assert module the home of related macros

Given the macro scoping rules, all macros are rendered twice, in the
module and in the top-level of kernel crate.

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.

[ Sadly, because the definition is hidden, `rustdoc` decides to not list
  them as re-exports in the `prelude` page anymore, even if we refer to
  the not-actually-hidden item.

    - Miguel ]

Acked-by: Danilo Krummrich <dakr@kernel.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Acked-by: Boqun Feng <boqun@kernel.org>
Signed-off-by: Gary Guo <gary@garyguo.net>
Link: https://patch.msgid.link/20260609142637.373347-1-gary@kernel.org
[ Kept a single declaration in the prelude, and reworded since they
  already had `no_inline`. Removed other imports from `predefine` since
  we now use the prelude. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Gary Guo 2026-06-09 15:26:33 +01:00 committed by Miguel Ojeda
parent 3fff427180
commit 8d49d90fb9
14 changed files with 62 additions and 39 deletions

View File

@ -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")
);

View File

@ -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
}

View File

@ -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);
}
}};
}

View File

@ -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!(

View File

@ -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)
}
}

View File

@ -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)]

View File

@ -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

View File

@ -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."
);

View File

@ -79,9 +79,12 @@
VVec,
Vec, //
},
build_assert,
build_error,
const_assert,
build_assert::{
build_assert,
build_error,
const_assert,
static_assert, //
},
current,
dev_alert,
dev_crit,
@ -105,7 +108,6 @@
pr_info,
pr_notice,
pr_warn,
static_assert,
str::CStrExt as _,
try_init,
try_pin_init,

View File

@ -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"

View File

@ -2,9 +2,7 @@
//! Pre-defined atomic types
use crate::static_assert;
use core::mem::{align_of, size_of};
use ffi::c_void;
use crate::prelude::*;
// Ensure size and alignment requirements are checked.
static_assert!(size_of::<bool>() == size_of::<i8>());

View File

@ -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.

View File

@ -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.
///

View File

@ -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};