rust: pin-init: add `cast_[pin_]init` functions to change the initialized type
authorBenno Lossin <benno.lossin@proton.me>
Mon, 21 Apr 2025 22:17:50 +0000 (22:17 +0000)
committerBenno Lossin <benno.lossin@proton.me>
Thu, 1 May 2025 16:08:52 +0000 (18:08 +0200)
These functions cast the given pointer from one type to another. They
are particularly useful when initializing transparent wrapper types.

Link: https://github.com/Rust-for-Linux/pin-init/pull/39/commits/80c03ddee41b154f1099fd8cc7c2bbd8c80af0ad
Reviewed-by: Christian Schrefl <chrisi.schrefl@gmail.com>
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
rust/pin-init/src/lib.rs

index 0806c689f693c1e9dd3a2d41f9899b82aac3c538..a880c21d3f09d56278c14ad93c19afe8989123c3 100644 (file)
@@ -1216,6 +1216,38 @@ pub const unsafe fn init_from_closure<T: ?Sized, E>(
     __internal::InitClosure(f, PhantomData)
 }
 
+/// Changes the to be initialized type.
+///
+/// # Safety
+///
+/// - `*mut U` must be castable to `*mut T` and any value of type `T` written through such a
+///   pointer must result in a valid `U`.
+#[expect(clippy::let_and_return)]
+pub const unsafe fn cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl PinInit<U, E> {
+    // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
+    // requirements.
+    let res = unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) };
+    // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a
+    // cycle when computing the type returned by this function)
+    res
+}
+
+/// Changes the to be initialized type.
+///
+/// # Safety
+///
+/// - `*mut U` must be castable to `*mut T` and any value of type `T` written through such a
+///   pointer must result in a valid `U`.
+#[expect(clippy::let_and_return)]
+pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> {
+    // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
+    // requirements.
+    let res = unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) };
+    // FIXME: remove the let statement once the nightly-MSRV allows it (1.78 otherwise encounters a
+    // cycle when computing the type returned by this function)
+    res
+}
+
 /// An initializer that leaves the memory uninitialized.
 ///
 /// The initializer is a no-op. The `slot` memory is not changed.