@@ -7,7 +7,7 @@ use crate::{
7
7
cell:: { Cell , UnsafeCell } ,
8
8
fmt,
9
9
marker:: PhantomData ,
10
- mem:: { self , MaybeUninit } ,
10
+ mem:: MaybeUninit ,
11
11
ops:: { Deref , Drop } ,
12
12
panic:: { RefUnwindSafe , UnwindSafe } ,
13
13
sync:: Once ,
@@ -316,13 +316,7 @@ impl<T> SyncOnceCell<T> {
316
316
/// ```
317
317
#[ unstable( feature = "once_cell" , issue = "74465" ) ]
318
318
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 ( )
326
320
}
327
321
328
322
/// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state.
@@ -348,22 +342,12 @@ impl<T> SyncOnceCell<T> {
348
342
/// ```
349
343
#[ unstable( feature = "once_cell" , issue = "74465" ) ]
350
344
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.
364
345
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 ( ) ) }
367
351
} else {
368
352
None
369
353
}
@@ -416,9 +400,12 @@ impl<T> SyncOnceCell<T> {
416
400
417
401
unsafe impl < #[ may_dangle] T > Drop for SyncOnceCell < T > {
418
402
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
+ }
422
409
}
423
410
}
424
411
0 commit comments