114114//! [`impl Init<T, E>`]: Init
115115//! [`Opaque`]: kernel::types::Opaque
116116//! [`pin_data`]: ::macros::pin_data
117- //! [`UniqueArc<T>`]: kernel::sync::UniqueArc
118117
118+ use crate :: {
119+ error:: { self , Error } ,
120+ sync:: UniqueArc ,
121+ } ;
119122use alloc:: boxed:: Box ;
120- use core:: { cell:: Cell , convert:: Infallible , marker:: PhantomData , mem:: MaybeUninit , ptr} ;
123+ use core:: {
124+ alloc:: AllocError , cell:: Cell , convert:: Infallible , marker:: PhantomData , mem:: MaybeUninit ,
125+ pin:: Pin , ptr,
126+ } ;
121127
122128#[ doc( hidden) ]
123129pub mod __internal;
@@ -309,7 +315,6 @@ pub mod macros;
309315///
310316/// [`try_pin_init!`]: kernel::try_pin_init
311317/// [`NonNull<Self>`]: core::ptr::NonNull
312- /// [`Error`]: kernel::error::Error
313318// For a detailed example of how this macro works, see the module documentation of the hidden
314319// module `__internal` inside of `init/__internal.rs`.
315320#[ macro_export]
@@ -363,8 +368,6 @@ macro_rules! pin_init {
363368/// }
364369/// }
365370/// ```
366- ///
367- /// [`Error`]: kernel::error::Error
368371// For a detailed example of how this macro works, see the module documentation of the hidden
369372// module `__internal` inside of `init/__internal.rs`.
370373#[ macro_export]
@@ -586,8 +589,6 @@ macro_rules! try_pin_init {
586589///
587590/// This initializer is for initializing data in-place that might later be moved. If you want to
588591/// pin-initialize, use [`pin_init!`].
589- ///
590- /// [`Error`]: kernel::error::Error
591592// For a detailed example of how this macro works, see the module documentation of the hidden
592593// module `__internal` inside of `init/__internal.rs`.
593594#[ macro_export]
@@ -635,8 +636,6 @@ macro_rules! init {
635636/// }
636637/// }
637638/// ```
638- ///
639- /// [`Error`]: kernel::error::Error
640639// For a detailed example of how this macro works, see the module documentation of the hidden
641640// module `__internal` inside of `init/__internal.rs`.
642641#[ macro_export]
@@ -842,7 +841,8 @@ macro_rules! try_init {
842841/// A pin-initializer for the type `T`.
843842///
844843/// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
845- /// be [`Box<T>`], [`Arc<T>`], [`UniqueArc<T>`].
844+ /// be [`Box<T>`], [`Arc<T>`], [`UniqueArc<T>`]. Use the [`InPlaceInit::pin_init`] function of a
845+ /// smart pointer like [`Arc<T>`] on this.
846846///
847847/// Also see the [module description](self).
848848///
@@ -861,7 +861,6 @@ macro_rules! try_init {
861861///
862862/// [`Arc<T>`]: crate::sync::Arc
863863/// [`Arc::pin_init`]: crate::sync::Arc::pin_init
864- /// [`UniqueArc<T>`]: kernel::sync::UniqueArc
865864#[ must_use = "An initializer must be used in order to create its value." ]
866865pub unsafe trait PinInit < T : ?Sized , E = Infallible > : Sized {
867866 /// Initializes `slot`.
@@ -878,7 +877,8 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
878877/// An initializer for `T`.
879878///
880879/// To use this initializer, you will need a suitable memory location that can hold a `T`. This can
881- /// be [`Box<T>`], [`Arc<T>`], [`UniqueArc<T>`]. Because [`PinInit<T, E>`] is a super trait, you can
880+ /// be [`Box<T>`], [`Arc<T>`], [`UniqueArc<T>`]. Use the [`InPlaceInit::init`] function of a smart
881+ /// pointer like [`Arc<T>`] on this. Because [`PinInit<T, E>`] is a super trait, you can
882882/// use every function that takes it as well.
883883///
884884/// Also see the [module description](self).
@@ -903,7 +903,6 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
903903/// move the pointee after initialization.
904904///
905905/// [`Arc<T>`]: crate::sync::Arc
906- /// [`UniqueArc<T>`]: kernel::sync::UniqueArc
907906#[ must_use = "An initializer must be used in order to create its value." ]
908907pub unsafe trait Init < T : ?Sized , E = Infallible > : Sized {
909908 /// Initializes `slot`.
@@ -982,3 +981,106 @@ unsafe impl<T> Init<T> for T {
982981 Ok ( ( ) )
983982 }
984983}
984+
985+ /// Smart pointer that can initialize memory in-place.
986+ pub trait InPlaceInit < T > : Sized {
987+ /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
988+ /// type.
989+ ///
990+ /// If `T: !Unpin` it will not be able to move afterwards.
991+ fn try_pin_init < E > ( init : impl PinInit < T , E > ) -> Result < Pin < Self > , E >
992+ where
993+ E : From < AllocError > ;
994+
995+ /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
996+ /// type.
997+ ///
998+ /// If `T: !Unpin` it will not be able to move afterwards.
999+ fn pin_init < E > ( init : impl PinInit < T , E > ) -> error:: Result < Pin < Self > >
1000+ where
1001+ Error : From < E > ,
1002+ {
1003+ // SAFETY: We delegate to `init` and only change the error type.
1004+ let init = unsafe {
1005+ pin_init_from_closure ( |slot| init. __pinned_init ( slot) . map_err ( |e| Error :: from ( e) ) )
1006+ } ;
1007+ Self :: try_pin_init ( init)
1008+ }
1009+
1010+ /// Use the given initializer to in-place initialize a `T`.
1011+ fn try_init < E > ( init : impl Init < T , E > ) -> Result < Self , E >
1012+ where
1013+ E : From < AllocError > ;
1014+
1015+ /// Use the given initializer to in-place initialize a `T`.
1016+ fn init < E > ( init : impl Init < T , E > ) -> error:: Result < Self >
1017+ where
1018+ Error : From < E > ,
1019+ {
1020+ // SAFETY: We delegate to `init` and only change the error type.
1021+ let init = unsafe {
1022+ init_from_closure ( |slot| init. __pinned_init ( slot) . map_err ( |e| Error :: from ( e) ) )
1023+ } ;
1024+ Self :: try_init ( init)
1025+ }
1026+ }
1027+
1028+ impl < T > InPlaceInit < T > for Box < T > {
1029+ #[ inline]
1030+ fn try_pin_init < E > ( init : impl PinInit < T , E > ) -> Result < Pin < Self > , E >
1031+ where
1032+ E : From < AllocError > ,
1033+ {
1034+ let mut this = Box :: try_new_uninit ( ) ?;
1035+ let slot = this. as_mut_ptr ( ) ;
1036+ // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
1037+ // slot is valid and will not be moved, because we pin it later.
1038+ unsafe { init. __pinned_init ( slot) ? } ;
1039+ // SAFETY: All fields have been initialized.
1040+ Ok ( unsafe { this. assume_init ( ) } . into ( ) )
1041+ }
1042+
1043+ #[ inline]
1044+ fn try_init < E > ( init : impl Init < T , E > ) -> Result < Self , E >
1045+ where
1046+ E : From < AllocError > ,
1047+ {
1048+ let mut this = Box :: try_new_uninit ( ) ?;
1049+ let slot = this. as_mut_ptr ( ) ;
1050+ // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
1051+ // slot is valid.
1052+ unsafe { init. __init ( slot) ? } ;
1053+ // SAFETY: All fields have been initialized.
1054+ Ok ( unsafe { this. assume_init ( ) } )
1055+ }
1056+ }
1057+
1058+ impl < T > InPlaceInit < T > for UniqueArc < T > {
1059+ #[ inline]
1060+ fn try_pin_init < E > ( init : impl PinInit < T , E > ) -> Result < Pin < Self > , E >
1061+ where
1062+ E : From < AllocError > ,
1063+ {
1064+ let mut this = UniqueArc :: try_new_uninit ( ) ?;
1065+ let slot = this. as_mut_ptr ( ) ;
1066+ // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
1067+ // slot is valid and will not be moved, because we pin it later.
1068+ unsafe { init. __pinned_init ( slot) ? } ;
1069+ // SAFETY: All fields have been initialized.
1070+ Ok ( unsafe { this. assume_init ( ) } . into ( ) )
1071+ }
1072+
1073+ #[ inline]
1074+ fn try_init < E > ( init : impl Init < T , E > ) -> Result < Self , E >
1075+ where
1076+ E : From < AllocError > ,
1077+ {
1078+ let mut this = UniqueArc :: try_new_uninit ( ) ?;
1079+ let slot = this. as_mut_ptr ( ) ;
1080+ // SAFETY: When init errors/panics, slot will get deallocated but not dropped,
1081+ // slot is valid.
1082+ unsafe { init. __init ( slot) ? } ;
1083+ // SAFETY: All fields have been initialized.
1084+ Ok ( unsafe { this. assume_init ( ) } )
1085+ }
1086+ }
0 commit comments