rust: kernel: introduce `unsafe_precondition_assert!` macro
PATCH RESEND v5 1/1 rust: kernel: introduce `unsafe_precondition_assert!` macro
Introduce a new safety module containing unsafe_precondition_assert! macro. It is a wrapper around debug_assert!, intended for validating pre-conditions of unsafe function.
When CONFIG_RUST_DEBUG_ASSERTIONS flag is enabled, this macro performs runtime checks to ensure that the preconditions for unsafe function hold. Otherwise, the macro is a no-op.
---
Changes in v5:
- Change doc example
- Use re-exported kernel::prelude::fmt! instead of core::format_args!
- Link to v4: https://lore.kernel.org/rust-for-linux/[email protected]/
Changes in v4:
- Change doc example
- Add no_run attribute to the doc example
- Link to v3: https://lore.kernel.org/rust-for-linux/[email protected]/
Changes in v3:
- Change doc example
- Link to v2: https://lore.kernel.org/all/20250730181420.6979b4f1@eugeo/T/#m9cd35a8fc02a18bd03934c7ecdcffe8667b5fbbd
Changes in v2:
- Wrap debug_assert! internally instead of using pr_err! with assert! + `cfg!(debug_assertions)
- Print “unsafe precondition(s) violated” only on assertion failure (no longer always printed)
- Use # Safety section instead of comment in the example
- Rename module-level doc
- Link to v1: https://lore.kernel.org/rust-for-linux/[email protected]/
--- rust/kernel/lib.rs | 1 + rust/kernel/safety.rs | 54 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 rust/kernel/safety.rs
rust/kernel/lib.rs +1 -0
@@ -113,6 +113,7 @@pub mod rbtree;pub mod regulator;pub mod revocable; +pub mod safety;pub mod security;pub mod seq_file;pub mod sizes;
rust/kernel/safety.rs new file +54 -0
54 lines not on this page · raw message
base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
Signature · 1 line
2.50.1
Benno Lossin
reviewerrust/kernel/safety.rs line 3
Quoted 9 lines · Ritvik Gupta
rust/kernel/safety.rs new file +3
-0@@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Safety related APIs.
I think this looks fine to start out with.
Quoted 15 lines
rust/kernel/safety.rs new file +15
-0+ +/// Checks that preconditions of an unsafe function are followed. +/// +/// The check is enabled at runtime if debug assertions (`CONFIG_RUST_DEBUG_ASSERTIONS`) +/// are enabled. Otherwise, this macro is no-op. +/// +/// # Examples +/// +/// ```no_run +/// use kernel::unsafe_precondition_assert; +/// +/// struct RawBuffer<T: Copy, const N: usize> { +/// data: [T; N], +/// } +///
rust/kernel/safety.rs line 28
Quoted 10 lines
rust/kernel/safety.rs new file +10
-0+/// impl<T: Copy, const N: usize> RawBuffer<T, N> { +/// /// # Safety +/// /// +/// /// The caller must ensure that `index` is less than `N` +/// unsafe fn set_unchecked(&mut self, index: usize, value: T) { +/// unsafe_precondition_assert!( +/// index < N, +/// "RawBuffer::set_unchecked requires index ({}) < N ({})", +/// index, +/// N,
You can move the names into the {}:
unsafe_precondition_assert!(
index < N,
"RawBuffer::set_unchecked requires index ({index}) < N ({N})",
);
Quoted 15 lines
rust/kernel/safety.rs new file +15
-0+/// ); +/// +/// // SAFETY: By the safety requirements of this function, `index` is valid +/// unsafe { +/// *self.data.get_unchecked_mut(index) = value; +/// } +/// } +/// } +/// ``` +/// +/// # Panics +/// +/// Panics if the expression is evaluated to `false` at runtime. +#[macro_export] +macro_rules! unsafe_precondition_assert {
rust/kernel/safety.rs line 53
Quoted 10 lines
rust/kernel/safety.rs new file +10
-0+ ($cond:expr $(,)?) => { + $crate::unsafe_precondition_assert!(@inner $cond, ::core::stringify!($cond)) + }; + + ($cond:expr, $($arg:tt)+) => { + $crate::unsafe_precondition_assert!(@inner $cond, $crate::prelude::fmt!($($arg)+)) + }; + + (@inner $cond:expr, $msg:expr) => { + ::core::debug_assert!($cond, "unsafe precondition(s) violated: {}", $msg) };
The closing } should be on the next line.
---
Cheers,
Benno
Quoted 3 lines
rust/kernel/safety.rs new file +1
-0+}base-commit:
8f5ae30d69d7543eee0d70083daf4de8fe15d585