Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Gary Guo and committed by
Miguel Ojeda
560a7a9b abfe5ee9

+42 -22
+24
rust/kernel/build_assert.rs
··· 41 41 }; 42 42 } 43 43 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 + 44 68 /// Fails the build if the code path calling `build_error!` can possibly be executed. 45 69 /// 46 70 /// If the macro is executed in const context, `build_error!` will panic.
+9 -15
rust/kernel/num/bounded.rs
··· 255 255 /// ``` 256 256 pub const fn new<const VALUE: $type>() -> Self { 257 257 // 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)); 261 259 262 260 // SAFETY: `fits_within` confirmed that `VALUE` can be represented within 263 261 // `N` bits. ··· 285 287 /// The caller must ensure that `value` can be represented within `N` bits. 286 288 const unsafe fn __new(value: T) -> Self { 287 289 // Enforce the type invariants. 288 - const { 289 - // `N` cannot be zero. 290 - assert!(N != 0); 291 - // The backing type is at least as large as `N` bits. 292 - assert!(N <= T::BITS); 293 - } 290 + // `N` cannot be zero. 291 + const_assert!(N != 0); 292 + // The backing type is at least as large as `N` bits. 293 + const_assert!(N <= T::BITS); 294 294 295 295 // INVARIANT: The caller ensures `value` fits within `N` bits. 296 296 Self(value) ··· 402 406 /// assert_eq!(larger_v, v); 403 407 /// ``` 404 408 pub const fn extend<const M: u32>(self) -> Bounded<T, M> { 405 - const { 406 - assert!( 407 - M >= N, 408 - "Requested number of bits is less than the current representation." 409 - ); 410 - } 409 + const_assert!( 410 + M >= N, 411 + "Requested number of bits is less than the current representation." 412 + ); 411 413 412 414 // SAFETY: The value did fit within `N` bits, so it will all the more fit within 413 415 // the larger `M` bits.
+1
rust/kernel/prelude.rs
··· 32 32 pub use super::{ 33 33 build_assert, 34 34 build_error, 35 + const_assert, 35 36 static_assert, // 36 37 }; 37 38
+6 -6
rust/kernel/ptr.rs
··· 5 5 use core::mem::align_of; 6 6 use core::num::NonZero; 7 7 8 + use crate::const_assert; 9 + 8 10 /// Type representing an alignment, which is always a power of two. 9 11 /// 10 12 /// It is used to validate that a given value is a valid alignment, and to perform masking and ··· 40 38 /// ``` 41 39 #[inline(always)] 42 40 pub const fn new<const ALIGN: usize>() -> Self { 43 - const { 44 - assert!( 45 - ALIGN.is_power_of_two(), 46 - "Provided alignment is not a power of two." 47 - ); 48 - } 41 + const_assert!( 42 + ALIGN.is_power_of_two(), 43 + "Provided alignment is not a power of two." 44 + ); 49 45 50 46 // INVARIANT: `align` is a power of two. 51 47 // SAFETY: `align` is a power of two, and thus non-zero.
+2 -1
scripts/Makefile.build
··· 310 310 311 311 # The features in this list are the ones allowed for non-`rust/` code. 312 312 # 313 + # - Stable since Rust 1.79.0: `feature(inline_const)`. 313 314 # - Stable since Rust 1.81.0: `feature(lint_reasons)`. 314 315 # - Stable since Rust 1.82.0: `feature(asm_const)`, 315 316 # `feature(offset_of_nested)`, `feature(raw_ref_op)`. ··· 320 319 # 321 320 # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on 322 321 # the unstable features in use. 323 - rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,used_with_arg 322 + rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,inline_const,lint_reasons,offset_of_nested,raw_ref_op,used_with_arg 324 323 325 324 # `--out-dir` is required to avoid temporaries being created by `rustc` in the 326 325 # current working directory, which may be not accessible in the out-of-tree