summaryrefslogtreecommitdiff
path: root/rust/kernel/init
diff options
context:
space:
mode:
authorBenno Lossin <benno.lossin@proton.me>2024-08-14 11:05:20 +0300
committerMiguel Ojeda <ojeda@kernel.org>2024-08-23 07:25:59 +0300
commit0528ca0a4f858da3369d405af8c76b8248dfeb7b (patch)
treef399d58d2330aa573b2aec87aee8879e0229a6bc /rust/kernel/init
parentc6945acad7a14b6afb390a4afc1d354ef5413ea6 (diff)
downloadlinux-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.rs29
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(())
+ }
+}