diff options
author | Benno Lossin <benno.lossin@proton.me> | 2024-08-14 11:05:20 +0300 |
---|---|---|
committer | Miguel Ojeda <ojeda@kernel.org> | 2024-08-23 07:25:59 +0300 |
commit | 0528ca0a4f858da3369d405af8c76b8248dfeb7b (patch) | |
tree | f399d58d2330aa573b2aec87aee8879e0229a6bc /rust/kernel/init | |
parent | c6945acad7a14b6afb390a4afc1d354ef5413ea6 (diff) | |
download | linux-0528ca0a4f858da3369d405af8c76b8248dfeb7b.tar.xz |
rust: init: add `assert_pinned` macro
Add a macro to statically check if a field of a struct is marked with
`#[pin]` ie that it is structurally pinned. This can be used when
`unsafe` code needs to rely on fields being structurally pinned.
The macro has a special "inline" mode for the case where the type
depends on generic parameters from the surrounding scope.
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Co-developed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240814-linked-list-v5-1-f5f5e8075da0@google.com
[ Replaced `compile_fail` with `ignore` and a TODO note. Removed
`pub` from example to clean `unreachable_pub` lint. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Diffstat (limited to 'rust/kernel/init')
-rw-r--r-- | rust/kernel/init/__internal.rs | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/rust/kernel/init/__internal.rs b/rust/kernel/init/__internal.rs index db3372619ecd..13cefd37512f 100644 --- a/rust/kernel/init/__internal.rs +++ b/rust/kernel/init/__internal.rs @@ -228,3 +228,32 @@ impl OnlyCallFromDrop { Self(()) } } + +/// Initializer that always fails. +/// +/// Used by [`assert_pinned!`]. +/// +/// [`assert_pinned!`]: crate::assert_pinned +pub struct AlwaysFail<T: ?Sized> { + _t: PhantomData<T>, +} + +impl<T: ?Sized> AlwaysFail<T> { + /// Creates a new initializer that always fails. + pub fn new() -> Self { + Self { _t: PhantomData } + } +} + +impl<T: ?Sized> Default for AlwaysFail<T> { + fn default() -> Self { + Self::new() + } +} + +// SAFETY: `__pinned_init` always fails, which is always okay. +unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> { + unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> { + Err(()) + } +} |