From a980e7c0d581356ea20c5d946ba03985541f8755 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 29 Jul 2026 15:41:24 +0100 Subject: [PATCH 1/4] examples: use `Wrapper::pin_init` instead of manual reimplementation `UnsafeCell` gains the method via the extension trait `Wrapper`. Signed-off-by: Gary Guo --- examples/mutex.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/mutex.rs b/examples/mutex.rs index 882f3e23..e8d4dbb6 100644 --- a/examples/mutex.rs +++ b/examples/mutex.rs @@ -79,11 +79,7 @@ impl CMutex { wait_list <- ListHead::new(), spin_lock: SpinLock::new(), locked: Cell::new(false), - data <- unsafe { - pin_init_from_closure(|slot: *mut UnsafeCell| { - val.__pinned_init(slot.cast::()) - }) - }, + data <- UnsafeCell::pin_init(val), }) } From fa0a26bea185c7a7db5c556cdfaf5197d76f74a6 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 22 Jul 2026 15:52:06 +0100 Subject: [PATCH 2/4] merge `__pinned_init` and `__init` These functions have the same requirements and are also required to execute the same code. Prevent duplication by merging them to the single function and document the additional relaxation of `Init::__init` on both the merged function and the safety requirement of `Init`. The existing `__pinned_init` function is deprecated and kept for compatibility for existing users. For `cfg(kernel)`, it is soft-deprecated for now and will be removed when all users are migrated. Signed-off-by: Gary Guo --- examples/static_init.rs | 9 +- src/__internal.rs | 8 +- src/alloc.rs | 6 +- src/lib.rs | 146 +++++++----------- tests/symbol_length.rs | 4 +- .../ui/compile-fail/init/invalid_init.stderr | 2 +- .../compile-fail/pin_data/missing_pin.stderr | 2 +- 7 files changed, 71 insertions(+), 106 deletions(-) diff --git a/examples/static_init.rs b/examples/static_init.rs index 58cd4241..8e71556f 100644 --- a/examples/static_init.rs +++ b/examples/static_init.rs @@ -59,7 +59,7 @@ impl> ops::Deref for StaticInit { println!("doing init"); let ptr = self.cell.get().cast::(); match self.init.take() { - Some(f) => unsafe { f.__pinned_init(ptr).unwrap() }, + Some(f) => unsafe { f.__init(ptr).unwrap() }, None => unsafe { core::hint::unreachable_unchecked() }, } self.present.set(true); @@ -71,13 +71,10 @@ impl> ops::Deref for StaticInit { pub struct CountInit; unsafe impl PinInit> for CountInit { - unsafe fn __pinned_init( - self, - slot: *mut CMutex, - ) -> Result<(), core::convert::Infallible> { + unsafe fn __init(self, slot: *mut CMutex) -> Result<(), core::convert::Infallible> { let init = CMutex::new(0); std::thread::sleep(std::time::Duration::from_millis(1000)); - unsafe { init.__pinned_init(slot) } + unsafe { init.__init(slot) } } } diff --git a/src/__internal.rs b/src/__internal.rs index 56dc655e..ae9a0e68 100644 --- a/src/__internal.rs +++ b/src/__internal.rs @@ -181,7 +181,7 @@ impl StackInit { unsafe { this.value.assume_init_drop() }; } // SAFETY: The memory slot is valid and this type ensures that it will stay pinned. - unsafe { init.__pinned_init(this.value.as_mut_ptr())? }; + unsafe { init.__init(this.value.as_mut_ptr())? }; // INVARIANT: `this.value` is initialized above. this.is_init = true; // SAFETY: The slot is now pinned, since we will never give access to `&mut T`. @@ -289,7 +289,7 @@ impl Slot { // - when `Err` is returned, we also propagate the error without touching `ptr`; // also `self` is consumed so it cannot be touched further. // - the drop guard will not hand out `&mut` (only `Pin<&mut T>`). - unsafe { init.__pinned_init(self.ptr)? }; + unsafe { init.__init(self.ptr)? }; // SAFETY: // - `self.ptr` is valid, properly aligned and pinned per type invariant. @@ -396,9 +396,9 @@ impl Default for AlwaysFail { } } -// SAFETY: `__pinned_init` always fails, which is always okay. +// SAFETY: `__init` always fails, which is always okay. unsafe impl PinInit for AlwaysFail { - unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> { + unsafe fn __init(self, _slot: *mut T) -> Result<(), ()> { Err(()) } } diff --git a/src/alloc.rs b/src/alloc.rs index 5017f574..641f4c7c 100644 --- a/src/alloc.rs +++ b/src/alloc.rs @@ -38,7 +38,7 @@ pub trait InPlaceInit: Sized { fn pin_init(init: impl PinInit) -> Result, AllocError> { // SAFETY: We delegate to `init` and only change the error type. let init = unsafe { - pin_init_from_closure(|slot| match init.__pinned_init(slot) { + pin_init_from_closure(|slot| match init.__init(slot) { Ok(()) => Ok(()), Err(i) => match i {}, }) @@ -109,7 +109,7 @@ impl InPlaceInit for Arc { let slot = slot.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but not dropped, // slot is valid and will not be moved, because we pin it later. - unsafe { init.__pinned_init(slot)? }; + unsafe { init.__init(slot)? }; // SAFETY: All fields have been initialized and this is the only `Arc` to that data. Ok(unsafe { Pin::new_unchecked(this.assume_init()) }) } @@ -149,7 +149,7 @@ impl InPlaceWrite for Box> { let slot = self.as_mut_ptr(); // SAFETY: When init errors/panics, slot will get deallocated but not dropped, // slot is valid and will not be moved, because we pin it later. - unsafe { init.__pinned_init(slot)? }; + unsafe { init.__init(slot)? }; // SAFETY: All fields have been initialized. Ok(unsafe { self.assume_init() }.into()) } diff --git a/src/lib.rs b/src/lib.rs index f4ccb0e8..fde53473 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -889,7 +889,7 @@ macro_rules! assert_pinned { /// When implementing this trait you will need to take great care. Also there are probably very few /// cases where a manual implementation is necessary. Use [`pin_init_from_closure`] where possible. /// -/// The [`PinInit::__pinned_init`] function: +/// The [`PinInit::__init`] function: /// - returns `Ok(())` if it initialized every field of `slot`, /// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means: /// - `slot` can be deallocated without UB occurring, @@ -909,6 +909,20 @@ macro_rules! assert_pinned { #[cfg_attr(not(kernel), doc = "[`Box`]: alloc::alloc::boxed::Box")] #[must_use = "An initializer must be used in order to create its value."] pub unsafe trait PinInit: Sized { + /// Alias of [`PinInit::__init`]. + /// + /// New code should use `__init` instead. + /// + /// # Safety + /// + /// Same as `__init`. + #[inline(always)] + #[cfg_attr(not(kernel), deprecated = "use `__init` instead")] + unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { + // SAFETY: Per safety requirement. + unsafe { self.__init(slot) } + } + /// Initializes `slot`. /// /// # Safety @@ -917,7 +931,8 @@ pub unsafe trait PinInit: Sized { /// - 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. - unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>; + /// If `Self: Init`, this requirement is cancelled and it may be moved. + unsafe fn __init(self, slot: *mut T) -> Result<(), E>; /// First initializes the value using `self` then calls the function `f` with the initialized /// value. @@ -948,7 +963,7 @@ pub unsafe trait PinInit: Sized { /// An initializer returned by [`PinInit::pin_chain`]. pub struct ChainPinInit(I, F, __internal::PhantomInvariant<(E, T)>); -// SAFETY: The `__pinned_init` function is implemented such that it +// SAFETY: The `__init` function is implemented such that it // - returns `Ok(())` on successful initialization, // - returns `Err(err)` on error and in this case `slot` will be dropped. // - considers `slot` pinned. @@ -957,8 +972,8 @@ where I: PinInit, F: FnOnce(Pin<&mut T>) -> Result<(), E>, { - unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { - // SAFETY: All requirements fulfilled since this function is `__pinned_init`. + unsafe fn __init(self, slot: *mut T) -> Result<(), E> { + // SAFETY: All requirements fulfilled since this function is `__init`. let slot = unsafe { __internal::Slot::<__internal::Pinned, _>::new(slot) }; let mut guard = slot.init(self.0)?; (self.1)(guard.let_binding())?; @@ -980,19 +995,8 @@ where /// When implementing this trait you will need to take great care. Also there are probably very few /// cases where a manual implementation is necessary. Use [`init_from_closure`] where possible. /// -/// The [`Init::__init`] function: -/// - returns `Ok(())` if it initialized every field of `slot`, -/// - returns `Err(err)` if it encountered an error and then cleaned `slot`, this means: -/// - `slot` can be deallocated without UB occurring, -/// - `slot` does not need to be dropped, -/// - `slot` is not partially initialized. -/// - while constructing the `T` at `slot` it upholds the pinning invariants of `T`. -/// -/// The `__pinned_init` function from the supertrait [`PinInit`] needs to execute the exact same -/// code as `__init`. -/// -/// Contrary to its supertype [`PinInit`] the caller is allowed to -/// move the pointee after initialization. +/// The [`PinInit::__init`] function must work without the pinning requirement; the caller is +/// allowed to move the pointee after initialization. /// #[cfg_attr( kernel, @@ -1006,15 +1010,6 @@ where #[cfg_attr(not(kernel), doc = "[`Box`]: alloc::alloc::boxed::Box")] #[must_use = "An initializer must be used in order to create its value."] pub unsafe trait Init: PinInit { - /// Initializes `slot`. - /// - /// # 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. - unsafe fn __init(self, slot: *mut T) -> Result<(), E>; - /// First initializes the value using `self` then calls the function `f` with the initialized /// value. /// @@ -1053,10 +1048,18 @@ pub unsafe trait Init: PinInit { /// An initializer returned by [`Init::chain`]. pub struct ChainInit(I, F, __internal::PhantomInvariant<(E, T)>); +// SAFETY: The `__init` function does not rely on the pinning requirement. +unsafe impl Init for ChainInit +where + I: Init, + F: FnOnce(&mut T) -> Result<(), E>, +{ +} + // SAFETY: The `__init` function is implemented such that it // - returns `Ok(())` on successful initialization, // - returns `Err(err)` on error and in this case `slot` will be dropped. -unsafe impl Init for ChainInit +unsafe impl PinInit for ChainInit where I: Init, F: FnOnce(&mut T) -> Result<(), E>, @@ -1071,44 +1074,28 @@ where } } -// SAFETY: `__pinned_init` behaves exactly the same as `__init`. -unsafe impl PinInit for ChainInit -where - I: Init, - F: FnOnce(&mut T) -> Result<(), E>, -{ - unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { - // SAFETY: `__init` has less strict requirements compared to `__pinned_init`. - unsafe { self.__init(slot) } - } -} - /// Implement `PinInit` and `Init` for closures. /// /// It is unsafe to create this type, since the closure needs to fulfill the same safety -/// requirement as the `__pinned_init`/`__init` functions. +/// requirement as the `__init` functions. struct InitClosure(F, __internal::PhantomInvariant); -// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the -// `__init` invariants. -unsafe impl Init for InitClosure -where - F: FnOnce(*mut T) -> Result<(), E>, +// SAFETY: When constructing via `init_from_closure`, the `__init` function does not rely on the +// pinning requirement. When constructing via `pin_init_from_closure`, the opaque type prevents this +// implementation from being visible. +unsafe impl Init for InitClosure where + F: FnOnce(*mut T) -> Result<(), E> { - #[inline] - unsafe fn __init(self, slot: *mut T) -> Result<(), E> { - (self.0)(slot) - } } // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the -// `__pinned_init` invariants. +// `__init` invariants. unsafe impl PinInit for InitClosure where F: FnOnce(*mut T) -> Result<(), E>, { #[inline] - unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { + unsafe fn __init(self, slot: *mut T) -> Result<(), E> { (self.0)(slot) } } @@ -1160,7 +1147,7 @@ pub const unsafe fn init_from_closure( pub const unsafe fn cast_pin_init(init: impl PinInit) -> impl PinInit { // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety // requirements. - unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::())) } + unsafe { pin_init_from_closure(|ptr: *mut U| init.__init(ptr.cast::())) } } /// Changes the to be initialized type. @@ -1195,7 +1182,7 @@ where F: FnMut(usize) -> I, I: PinInit, { - unsafe fn __pinned_init(mut self, slot: *mut [T; N]) -> Result<(), E> { + unsafe fn __init(mut self, slot: *mut [T; N]) -> Result<(), E> { /// # Invariants /// /// - `ptr[..num_init]` contains initialized elements of type `T` @@ -1237,7 +1224,7 @@ where // - If `Err` is touched, the subslot is not touched further, the guard will drop // previously initialized elements only. // - `slot` is pinned so is the subslot. - unsafe { init.__pinned_init(&raw mut (*slot)[i]) }?; + unsafe { init.__init(&raw mut (*slot)[i]) }?; } // Dismiss the drop guard now that all elements are initialized. @@ -1246,18 +1233,13 @@ where } } -// SAFETY: Follows the `PinInit` impl. `__init` executes the same code as `__pinned_init`. +// SAFETY: `I: Init` cancels out the pinning requirement on subslots, which is the only place in the +// `__init` function that relies on `slot` being pinned. unsafe impl Init<[T; N], E> for ArrayInit where F: FnMut(usize) -> I, I: Init, { - #[inline(always)] - unsafe fn __init(self, slot: *mut [T; N]) -> Result<(), E> { - // SAFETY: `I: Init` cancels out the pinning requirement on subslots. The other safety - // requirements follow that of `__init`. - unsafe { self.__pinned_init(slot) } - } } /// Initializes an array by initializing each element via the provided initializer. @@ -1336,13 +1318,13 @@ where { // SAFETY: // - If `make_init` returns `Err`, `Err` is returned and `slot` is completely uninitialized, - // - If `make_init` returns `Ok`, safety requirement are fulfilled by `init.__pinned_init`. - // - The safety requirements of `init.__pinned_init` are fulfilled, since it's being called - // from an initializer. + // - If `make_init` returns `Ok`, safety requirement are fulfilled by `init.__init`. + // - The safety requirements of `init.__init` are fulfilled, since it's being called from an + // initializer. unsafe { pin_init_from_closure(move |slot: *mut T| -> Result<(), E> { let init = make_init()?; - init.__pinned_init(slot) + init.__init(slot) }) } } @@ -1390,41 +1372,27 @@ where } } -// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`. -unsafe impl Init for T { - unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> { - // SAFETY: `slot` is valid for writes by the safety requirements of this function. - unsafe { slot.write(self) }; - Ok(()) - } -} +// SAFETY: The `__init` function does not rely on slot being pinned after it returns. +unsafe impl Init for T {} -// SAFETY: the `__pinned_init` function always returns `Ok(())` and initializes every field of +// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of // `slot`. Additionally, all pinning invariants of `T` are upheld. unsafe impl PinInit for T { - unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible> { + unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> { // SAFETY: `slot` is valid for writes by the safety requirements of this function. unsafe { slot.write(self) }; Ok(()) } } -// SAFETY: when the `__init` function returns with -// - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld. -// - `Err(err)`, slot was not written to. -unsafe impl Init for Result { - unsafe fn __init(self, slot: *mut T) -> Result<(), E> { - // SAFETY: `slot` is valid for writes by the safety requirements of this function. - unsafe { slot.write(self?) }; - Ok(()) - } -} +// SAFETY: The `__init` function does not rely on slot being pinned after it returns. +unsafe impl Init for Result {} -// SAFETY: when the `__pinned_init` function returns with +// SAFETY: when the `__init` function returns with // - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld. // - `Err(err)`, slot was not written to. unsafe impl PinInit for Result { - unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { + unsafe fn __init(self, slot: *mut T) -> Result<(), E> { // SAFETY: `slot` is valid for writes by the safety requirements of this function. unsafe { slot.write(self?) }; Ok(()) @@ -1467,7 +1435,7 @@ impl InPlaceWrite for &'static mut MaybeUninit { // // The `'static` borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). - unsafe { init.__pinned_init(slot)? }; + unsafe { init.__init(slot)? }; // SAFETY: The above call initialized the memory. Ok(Pin::static_mut(unsafe { self.assume_init_mut() })) diff --git a/tests/symbol_length.rs b/tests/symbol_length.rs index b666983b..955d47f5 100644 --- a/tests/symbol_length.rs +++ b/tests/symbol_length.rs @@ -12,7 +12,7 @@ pub fn init() -> impl PinInit { } fn init_fn_ptr>(_: &I) -> *mut () { - I::__pinned_init as *mut () + I::__init as *mut () } fn read_symbols() -> Result> { @@ -57,5 +57,5 @@ fn type_name() { let symbol = &symbols[0]; println!("{}: {}", symbol.len(), symbol); - assert!(symbol.len() < 181); + assert!(symbol.len() < 174); } diff --git a/tests/ui/compile-fail/init/invalid_init.stderr b/tests/ui/compile-fail/init/invalid_init.stderr index 137c1fae..843710a5 100644 --- a/tests/ui/compile-fail/init/invalid_init.stderr +++ b/tests/ui/compile-fail/init/invalid_init.stderr @@ -17,7 +17,7 @@ help: the following other types implement trait `Init` | | F: FnOnce(&mut T) -> Result<(), E>, | |_______________________________________^ `ChainInit` ... - | unsafe impl Init for Result { + | unsafe impl Init for Result {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Result` note: required by a bound in `pin_init::__internal::Slot::::init` --> src/__internal.rs diff --git a/tests/ui/compile-fail/pin_data/missing_pin.stderr b/tests/ui/compile-fail/pin_data/missing_pin.stderr index 1ebbbdbf..f480b637 100644 --- a/tests/ui/compile-fail/pin_data/missing_pin.stderr +++ b/tests/ui/compile-fail/pin_data/missing_pin.stderr @@ -11,7 +11,7 @@ help: the trait `Init` is not implemented for `impl PinInit` but trait `Init, Infallible>` is implemented for it --> src/lib.rs | - | unsafe impl Init for T { + | unsafe impl Init for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: for that trait implementation, expected `impl PinInit`, found `usize` note: required by a bound in `pin_init::__internal::Slot::::init` From a06307e3b9321bc2aeba71c8d0f383f264fd1535 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 29 Jul 2026 15:42:45 +0100 Subject: [PATCH 3/4] add `ptr_init` and `ptr_try_init` and recommend over `__init` 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 --- examples/static_init.rs | 5 +++-- src/lib.rs | 32 +++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/examples/static_init.rs b/examples/static_init.rs index 8e71556f..109cceea 100644 --- a/examples/static_init.rs +++ b/examples/static_init.rs @@ -59,7 +59,7 @@ impl> ops::Deref for StaticInit { println!("doing init"); let ptr = self.cell.get().cast::(); 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> for CountInit { unsafe fn __init(self, slot: *mut CMutex) -> 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/src/lib.rs b/src/lib.rs index fde53473..78a67ef5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -917,7 +917,7 @@ pub unsafe trait PinInit: 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 @@ pub unsafe trait PinInit: Sized { /// 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 @@ pub unsafe trait PinInit: Sized { } } +/// 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`, this requirement is cancelled and it may be moved. +#[inline(always)] +pub unsafe fn ptr_init(slot: *mut T, init: impl PinInit) { + // 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`, this requirement is cancelled and it may be moved. +#[inline(always)] +pub unsafe fn ptr_try_init(slot: *mut T, init: impl PinInit) -> Result<(), E> { + // SAFETY: Per safety requirement. + unsafe { init.__init(slot) } +} + /// An initializer returned by [`PinInit::pin_chain`]. pub struct ChainPinInit(I, F, __internal::PhantomInvariant<(E, T)>); From c2aecf90e90393aac6d3cb7c8c8449ffee350249 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 22 Jul 2026 18:49:32 +0100 Subject: [PATCH 4/4] remove `__pinned_init` method for `cfg(kernel)` Remove `__pinned_init` for kernel configuration, with all users gone. Still perserve it temporarily as deprecated so other users have time to move off it. Signed-off-by: Gary Guo --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 78a67ef5..16f60dcb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -917,7 +917,8 @@ pub unsafe trait PinInit: Sized { /// /// Same as `__init`. #[inline(always)] - #[cfg_attr(not(kernel), deprecated = "use `ptr_try_init` instead")] + #[cfg(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) }