kernel/safety.rs
1// SPDX-License-Identifier: GPL-2.0
2
3//! Safety related APIs.
4
5/// Checks that a precondition of an unsafe function is followed.
6///
7/// The check is enabled at runtime if debug assertions (`CONFIG_RUST_DEBUG_ASSERTIONS`)
8/// are enabled. Otherwise, this macro is a no-op.
9///
10/// # Examples
11///
12/// ```no_run
13/// use kernel::unsafe_precondition_assert;
14///
15/// struct RawBuffer<T: Copy, const N: usize> {
16/// data: [T; N],
17/// }
18///
19/// impl<T: Copy, const N: usize> RawBuffer<T, N> {
20/// /// # Safety
21/// ///
22/// /// The caller must ensure that `index` is less than `N`.
23/// unsafe fn set_unchecked(&mut self, index: usize, value: T) {
24/// unsafe_precondition_assert!(
25/// index < N,
26/// "RawBuffer::set_unchecked() requires index ({index}) < N ({N})"
27/// );
28///
29/// // SAFETY: By the safety requirements of this function, `index` is valid.
30/// unsafe {
31/// *self.data.get_unchecked_mut(index) = value;
32/// }
33/// }
34/// }
35/// ```
36///
37/// # Panics
38///
39/// Panics if the expression is evaluated to [`false`] at runtime.
40#[macro_export]
41macro_rules! unsafe_precondition_assert {
42 ($cond:expr $(,)?) => {
43 $crate::unsafe_precondition_assert!(@inner $cond, ::core::stringify!($cond))
44 };
45
46 ($cond:expr, $($arg:tt)+) => {
47 $crate::unsafe_precondition_assert!(@inner $cond, $crate::prelude::fmt!($($arg)+))
48 };
49
50 (@inner $cond:expr, $msg:expr) => {
51 ::core::debug_assert!($cond, "unsafe precondition violated: {}", $msg)
52 };
53}