[PATCH v2 3/5] rust: pin-init: add `ptr_init` and `ptr_try_init` and recommend over `__init`

Gary Guo <[email protected]> Wed, 29 Jul 2026 16:38:45 +0100
Newsgroups org.kernel.vger.linux-pwm,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
The `__init` method is not designed to be a public API (existence of "__"
is a hint for this); but currently there is no other API that allows raw
initialization on pointers. Add `ptr_init` and `ptr_try_init` and recommend
people to use this instead if raw pointer initialization is needed.

Signed-off-by: Gary Guo <[email protected]>
---
 rust/pin-init/examples/static_init.rs |  5 +++--
 rust/pin-init/src/lib.rs              | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/rust/pin-init/examples/static_init.rs b/rust/pin-init/examples/static_init.rs
index 8e71556ffe85..109cceea2eab 100644
--- a/rust/pin-init/examples/static_init.rs
+++ b/rust/pin-init/examples/static_init.rs
@@ -59,7 +59,7 @@ fn deref(&self) -> &Self::Target {
             println!("doing init");
             let ptr = self.cell.get().cast::<T>();
             match self.init.take() {
-                Some(f) => unsafe { f.__init(ptr).unwrap() },
+                Some(f) => unsafe { pin_init::ptr_init(ptr, f) },
                 None => unsafe { core::hint::unreachable_unchecked() },
             }
             self.present.set(true);
@@ -74,7 +74,8 @@ unsafe impl PinInit<CMutex<usize>> for CountInit {
     unsafe fn __init(self, slot: *mut CMutex<usize>) -> Result<(), core::convert::Infallible> {
         let init = CMutex::new(0);
         std::thread::sleep(std::time::Duration::from_millis(1000));
-        unsafe { init.__init(slot) }
+        unsafe { pin_init::ptr_init(slot, init) };
+        Ok(())
     }
 }
 
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index fde53473763f..78a67ef54f4e 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -917,7 +917,7 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
     ///
     /// Same as `__init`.
     #[inline(always)]
-    #[cfg_attr(not(kernel), deprecated = "use `__init` instead")]
+    #[cfg_attr(not(kernel), deprecated = "use `ptr_try_init` instead")]
     unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
         // SAFETY: Per safety requirement.
         unsafe { self.__init(slot) }
@@ -925,6 +925,8 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 
     /// Initializes `slot`.
     ///
+    /// It is not recommended to call this directly. Use [`ptr_init`] or [`ptr_try_init`].
+    ///
     /// # Safety
     ///
     /// - `slot` is a valid pointer to uninitialized memory.
@@ -960,6 +962,34 @@ fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
     }
 }
 
+/// Initializes `slot` with an initializer.
+///
+/// # Safety
+///
+/// - `slot` is a valid pointer to uninitialized memory.
+/// - `slot` will not move until it is dropped, i.e. it will be pinned.
+///   If `init` implements `Init<T, E>`, this requirement is cancelled and it may be moved.
+#[inline(always)]
+pub unsafe fn ptr_init<T>(slot: *mut T, init: impl PinInit<T>) {
+    // SAFETY: Per safety requirement.
+    unsafe { init.__init(slot).unwrap_or_else(|e| match e {}) }
+}
+
+/// Fallibly initializes `slot` with an initializer.
+///
+/// # Safety
+///
+/// - `slot` is a valid pointer to uninitialized memory.
+/// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
+///   deallocate.
+/// - `slot` will not move until it is dropped, i.e. it will be pinned.
+///   If `init` implements `Init<T, E>`, this requirement is cancelled and it may be moved.
+#[inline(always)]
+pub unsafe fn ptr_try_init<T, E>(slot: *mut T, init: impl PinInit<T, E>) -> Result<(), E> {
+    // SAFETY: Per safety requirement.
+    unsafe { init.__init(slot) }
+}
+
 /// An initializer returned by [`PinInit::pin_chain`].
 pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::PhantomInvariant<(E, T)>);
 

-- 
2.54.0