@@ -7,7 +7,7 @@ use crate::{
77 cell:: { Cell , UnsafeCell } ,
88 fmt,
99 marker:: PhantomData ,
10- mem:: { self , MaybeUninit } ,
10+ mem:: MaybeUninit ,
1111 ops:: { Deref , Drop } ,
1212 panic:: { RefUnwindSafe , UnwindSafe } ,
1313 sync:: Once ,
@@ -316,13 +316,7 @@ impl<T> SyncOnceCell<T> {
316316 /// ```
317317 #[ unstable( feature = "once_cell" , issue = "74465" ) ]
318318 pub fn into_inner ( mut self ) -> Option < T > {
319- // SAFETY: Safe because we immediately free `self` without dropping
320- let inner = unsafe { self . take_inner ( ) } ;
321-
322- // Don't drop this `SyncOnceCell`. We just moved out one of the fields, but didn't set
323- // the state to uninitialized.
324- mem:: forget ( self ) ;
325- inner
319+ self . take ( )
326320 }
327321
328322 /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state.
@@ -348,22 +342,12 @@ impl<T> SyncOnceCell<T> {
348342 /// ```
349343 #[ unstable( feature = "once_cell" , issue = "74465" ) ]
350344 pub fn take ( & mut self ) -> Option < T > {
351- mem:: take ( self ) . into_inner ( )
352- }
353-
354- /// Takes the wrapped value out of a `SyncOnceCell`.
355- /// Afterwards the cell is no longer initialized.
356- ///
357- /// Safety: The cell must now be free'd WITHOUT dropping. No other usages of the cell
358- /// are valid. Only used by `into_inner` and `drop`.
359- unsafe fn take_inner ( & mut self ) -> Option < T > {
360- // The mutable reference guarantees there are no other threads that can observe us
361- // taking out the wrapped value.
362- // Right after this function `self` is supposed to be freed, so it makes little sense
363- // to atomically set the state to uninitialized.
364345 if self . is_initialized ( ) {
365- let value = mem:: replace ( & mut self . value , UnsafeCell :: new ( MaybeUninit :: uninit ( ) ) ) ;
366- Some ( value. into_inner ( ) . assume_init ( ) )
346+ self . once = Once :: new ( ) ;
347+ // SAFETY: `self.value` is initialized and contains a valid `T`.
348+ // `self.once` is reset, so `is_initialized()` will be false again
349+ // which prevents the value from being read twice.
350+ unsafe { Some ( ( & mut * self . value . get ( ) ) . assume_init_read ( ) ) }
367351 } else {
368352 None
369353 }
@@ -416,9 +400,12 @@ impl<T> SyncOnceCell<T> {
416400
417401unsafe impl < #[ may_dangle] T > Drop for SyncOnceCell < T > {
418402 fn drop ( & mut self ) {
419- // SAFETY: The cell is being dropped, so it can't be accessed again.
420- // We also don't touch the `T`, which validates our usage of #[may_dangle].
421- unsafe { self . take_inner ( ) } ;
403+ if self . is_initialized ( ) {
404+ // Safety: The cell is initialized and being dropped, so it can't
405+ // be accessed again. We also don't touch the `T` other than
406+ // dropping it, which validates our usage of #[may_dangle].
407+ unsafe { ( & mut * self . value . get ( ) ) . assume_init_drop ( ) } ;
408+ }
422409 }
423410}
424411
0 commit comments