Skip to content

Commit 560a7a9

Browse files
nbdd0121ojeda
authored andcommitted
rust: add const_assert! macro
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. Reviewed-by: Yury Norov <ynorov@nvidia.com> Signed-off-by: Gary Guo <gary@garyguo.net> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Danilo Krummrich <dakr@kernel.org> Link: https://patch.msgid.link/20260319121653.2975748-3-gary@kernel.org [ Rebased. Fixed period typo. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
1 parent abfe5ee commit 560a7a9

File tree

5 files changed

+42
-22
lines changed

5 files changed

+42
-22
lines changed

rust/kernel/build_assert.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,30 @@ macro_rules! static_assert {
4141
};
4242
}
4343

44+
/// Assertion during constant evaluation.
45+
///
46+
/// This is a more powerful version of [`static_assert!`] that can refer to generics inside
47+
/// functions or implementation blocks. However, it also has a limitation where it can only appear
48+
/// in places where statements can appear; for example, you cannot use it as an item in the module.
49+
///
50+
/// # Examples
51+
///
52+
/// ```
53+
/// fn foo<const N: usize>() {
54+
/// const_assert!(N > 1);
55+
/// }
56+
///
57+
/// fn bar<T>() {
58+
/// const_assert!(size_of::<T>() > 0, "T cannot be ZST");
59+
/// }
60+
/// ```
61+
#[macro_export]
62+
macro_rules! const_assert {
63+
($condition:expr $(,$arg:literal)?) => {
64+
const { ::core::assert!($condition $(,$arg)?) };
65+
};
66+
}
67+
4468
/// Fails the build if the code path calling `build_error!` can possibly be executed.
4569
///
4670
/// If the macro is executed in const context, `build_error!` will panic.

rust/kernel/num/bounded.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,7 @@ macro_rules! impl_const_new {
255255
/// ```
256256
pub const fn new<const VALUE: $type>() -> Self {
257257
// Statically assert that `VALUE` fits within the set number of bits.
258-
const {
259-
assert!(fits_within!(VALUE, $type, N));
260-
}
258+
const_assert!(fits_within!(VALUE, $type, N));
261259

262260
// SAFETY: `fits_within` confirmed that `VALUE` can be represented within
263261
// `N` bits.
@@ -287,12 +285,10 @@ where
287285
/// The caller must ensure that `value` can be represented within `N` bits.
288286
const unsafe fn __new(value: T) -> Self {
289287
// Enforce the type invariants.
290-
const {
291-
// `N` cannot be zero.
292-
assert!(N != 0);
293-
// The backing type is at least as large as `N` bits.
294-
assert!(N <= T::BITS);
295-
}
288+
// `N` cannot be zero.
289+
const_assert!(N != 0);
290+
// The backing type is at least as large as `N` bits.
291+
const_assert!(N <= T::BITS);
296292

297293
// INVARIANT: The caller ensures `value` fits within `N` bits.
298294
Self(value)
@@ -406,12 +402,10 @@ where
406402
/// assert_eq!(larger_v, v);
407403
/// ```
408404
pub const fn extend<const M: u32>(self) -> Bounded<T, M> {
409-
const {
410-
assert!(
411-
M >= N,
412-
"Requested number of bits is less than the current representation."
413-
);
414-
}
405+
const_assert!(
406+
M >= N,
407+
"Requested number of bits is less than the current representation."
408+
);
415409

416410
// SAFETY: The value did fit within `N` bits, so it will all the more fit within
417411
// the larger `M` bits.

rust/kernel/prelude.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, Pi
3232
pub use super::{
3333
build_assert,
3434
build_error,
35+
const_assert,
3536
static_assert, //
3637
};
3738

rust/kernel/ptr.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use core::mem::align_of;
66
use core::num::NonZero;
77

8+
use crate::const_assert;
9+
810
/// Type representing an alignment, which is always a power of two.
911
///
1012
/// It is used to validate that a given value is a valid alignment, and to perform masking and
@@ -38,12 +40,10 @@ impl Alignment {
3840
/// ```
3941
#[inline(always)]
4042
pub const fn new<const ALIGN: usize>() -> Self {
41-
const {
42-
assert!(
43-
ALIGN.is_power_of_two(),
44-
"Provided alignment is not a power of two."
45-
);
46-
}
43+
const_assert!(
44+
ALIGN.is_power_of_two(),
45+
"Provided alignment is not a power of two."
46+
);
4747

4848
// INVARIANT: `align` is a power of two.
4949
// SAFETY: `align` is a power of two, and thus non-zero.

scripts/Makefile.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ $(obj)/%.lst: $(obj)/%.c FORCE
310310

311311
# The features in this list are the ones allowed for non-`rust/` code.
312312
#
313+
# - Stable since Rust 1.79.0: `feature(inline_const)`.
313314
# - Stable since Rust 1.81.0: `feature(lint_reasons)`.
314315
# - Stable since Rust 1.82.0: `feature(asm_const)`,
315316
# `feature(offset_of_nested)`, `feature(raw_ref_op)`.
@@ -319,7 +320,7 @@ $(obj)/%.lst: $(obj)/%.c FORCE
319320
#
320321
# Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
321322
# the unstable features in use.
322-
rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,used_with_arg
323+
rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,inline_const,lint_reasons,offset_of_nested,raw_ref_op,used_with_arg
323324

324325
# `--out-dir` is required to avoid temporaries being created by `rustc` in the
325326
# current working directory, which may be not accessible in the out-of-tree

0 commit comments

Comments
 (0)