@@ -282,66 +282,76 @@ impl<T: ?Sized> Drop for DropGuard<T> {
282282///
283283/// Drops the already initialized elements of the array if an error or panic occurs
284284/// partway through the initialization process.
285- pub struct ArrayInitGuard < T > {
286- /// A pointer to the first element of the array.
285+ pub struct ArrayInit < T , F > {
286+ /// A pointer to the first element of the array. Null until `__init` or `__pinned_init`
287+ /// is called.
287288 ptr : * mut T ,
288- /// The length of the array.
289- len : usize ,
290289 /// The number of initialized elements in the array.
291290 num_init : usize ,
291+ /// Initialization function factory.
292+ make_init : F ,
292293}
293294
294- impl < T > ArrayInitGuard < T > {
295- /// Creates a new [`ArrayInitGuard<T>`] for the array starting at `ptr` with length `len`.
296- ///
295+ impl < T , F > ArrayInit < T , F > {
297296 /// # Safety
298297 ///
299- /// `ptr` must be a valid pointer to the first element of an array of length `len`. The
300- /// memory must be uninitialized, and it is the caller's responsibility to ensure that:
301- /// - the elements of the array will only be initialized through this guard,
302- /// - the elements of the array will not be accessed by any other means until they
303- /// are initialized, and
304- /// - the elements of the array will not be dropped by any other means for the entire
305- /// lifetime of this guard.
306- pub unsafe fn new ( ptr : * mut T , len : usize ) -> Self {
298+ /// This function may only be called from
299+ /// [`init_array_from_fn`](crate::init_array_from_fn) or
300+ /// [`pin_init_array_from_fn`](crate::pin_init_array_from_fn).
301+ pub ( crate ) unsafe fn new ( make_init : F ) -> Self {
307302 Self {
308- ptr,
309- len,
303+ ptr : core:: ptr:: null_mut ( ) ,
310304 num_init : 0 ,
305+ make_init,
311306 }
312307 }
308+ }
313309
314- /// Initializes the array using the provided closure.
315- pub fn init < I , E > ( mut self , mut make_init : impl FnMut ( usize ) -> I ) -> Result < ( ) , E >
316- where
317- I : Init < T , E > ,
318- {
319- for i in 0 ..self . len {
320- let init = make_init ( i) ;
321- // SAFETY: Since `0 <= i < self.len`, `self.ptr.add(i)` is in bounds and valid for
322- // writes by the safety contract of `new`.
310+ /// SAFETY: On success, all `N` elements of the array have been initialized through
311+ /// `I: Init`. On error or panic, the elements that have been initialized so far are
312+ /// dropped, thus leaving the array uninitialized and ready to deallocate. The `Init`
313+ /// implementation executes the same code as that of `PinInit`.
314+ unsafe impl < T , F , I , E , const N : usize > Init < [ T ; N ] , E > for ArrayInit < T , F >
315+ where
316+ F : FnMut ( usize ) -> I ,
317+ I : Init < T , E > ,
318+ {
319+ unsafe fn __init ( mut self , slot : * mut [ T ; N ] ) -> Result < ( ) , E > {
320+ self . ptr = slot. cast :: < T > ( ) ;
321+ for i in 0 ..N {
322+ let init = ( self . make_init ) ( i) ;
323+ // SAFETY: Since `0 <= i < N`, `self.ptr.add(i)` is in bounds and
324+ // valid for writes by the safety contract of `__init`.
323325 let ptr = unsafe { self . ptr . add ( i) } ;
324- // SAFETY: The pointer is derived from `self.ptr ` and thus satisfies the `__init`
325- // requirements.
326+ // SAFETY: The pointer is derived from `slot ` and thus satisfies the
327+ // `__init` requirements.
326328 unsafe { init. __init ( ptr) } ?;
327329 self . num_init += 1 ;
328330 }
329331 core:: mem:: forget ( self ) ;
330332 Ok ( ( ) )
331333 }
334+ }
332335
333- /// Initializes the array using the provided closure, which is allowed to pin the elements.
334- pub fn pin_init < I , E > ( mut self , mut make_init : impl FnMut ( usize ) -> I ) -> Result < ( ) , E >
335- where
336- I : PinInit < T , E > ,
337- {
338- for i in 0 ..self . len {
339- let init = make_init ( i) ;
340- // SAFETY: Since `0 <= i < self.len`, `self.ptr.add(i)` is in bounds and valid for
341- // writes by the safety contract of `new`.
336+ /// SAFETY: On success, all `N` elements of the array have been initialized through
337+ /// `I`. Since `I: PinInit` guarantees that the pinning invariants of `T` are upheld,
338+ /// the guarantees of `[T; N]` are also upheld. On error or panic, the elements that
339+ /// have been initialized so far are dropped, thus leaving the array uninitialized
340+ /// and ready to deallocate.
341+ unsafe impl < T , F , I , E , const N : usize > PinInit < [ T ; N ] , E > for ArrayInit < T , F >
342+ where
343+ F : FnMut ( usize ) -> I ,
344+ I : PinInit < T , E > ,
345+ {
346+ unsafe fn __pinned_init ( mut self , slot : * mut [ T ; N ] ) -> Result < ( ) , E > {
347+ self . ptr = slot. cast :: < T > ( ) ;
348+ for i in 0 ..N {
349+ let init = ( self . make_init ) ( i) ;
350+ // SAFETY: Since `0 <= i < N`, `self.ptr.add(i)` is in bounds and
351+ // valid for writes by the safety contract of `__pinned_init`.
342352 let ptr = unsafe { self . ptr . add ( i) } ;
343- // SAFETY: The pointer is derived from `self.ptr ` and thus satisfies the `__pinned_init`
344- // requirements.
353+ // SAFETY: The pointer is derived from `slot ` and thus satisfies the
354+ // `__pinned_init` requirements.
345355 unsafe { init. __pinned_init ( ptr) } ?;
346356 self . num_init += 1 ;
347357 }
@@ -350,9 +360,14 @@ impl<T> ArrayInitGuard<T> {
350360 }
351361}
352362
353- impl < T > Drop for ArrayInitGuard < T > {
363+ impl < T , F > Drop for ArrayInit < T , F > {
354364 fn drop ( & mut self ) {
355- // SAFETY: safety contract of `ArrayInitGuard` guarantees that elements
365+ if self . ptr . is_null ( ) {
366+ // No initialization had been attempted, nothing to drop.
367+ return ;
368+ }
369+
370+ // SAFETY: Safety contract of `ArrayInit` guarantees that elements
356371 // `self.ptr[0..self.num_init]` are initialized and contain valid `T`
357372 // values, so dropping them is safe.
358373 unsafe {
0 commit comments