Closed pitdicker closed 4 years ago
It probably works better to swap the types to MaybeUninit<UnsafeCell<T>>
. Then the decision whether to get a mutable reference or not can be made later. This helps making a nicer abstraction for a consume operation, and the maybe_uninit
feature wouldn't depend on nightly. Have to think it through a bit more.
Late night ideas don't always work :smile:.
To initialize a MaybeUninit<UnsafeCell<T>>
you either have to do:
let slot = (&*self.value.as_ptr()).get() as *mut T;
slot.write(value);
which is UB, because it is creating a shared reference to an uninitialized type.
let slot = self.value.as_mut_ptr();
slot.write(UnsafeCell::new(value));
which is not possible, because we don't have a mutable reference to the MaybeUninit
.
The mention of UnsafeCell
in the description of MaybeUninit::as_ptr
threw me off.
Turns out we can't use MaybeUninit -- we'll need #[may_dangle]
for dropcheck, and it only is avable in nightly.
Replace
UnsafeCell<Option<T>>
withUnsafeCell<MaybeUninit<T>>
.I included a terrible imitation of
MaybeUninit
based onOption
, so there is no change in behavior right now. The real implementation that usesstd::mem::MaybeUninit
is behind a feature flagmaybe_uninit
and only usable with nightly.I did find one complexity:
OnceCell
now has to implementDrop
itself. Therefore it has to checkis_initialized
.into_inner
now has to use themem::replace
trick to move thevalue
field out of theOnceCell
, and then free the cell without dropping (becauseinitialized
is not reset).Conclusion: a bit messy. But I think it makes sense, as a preparation for the future. And it is a plus that
is_initialized
is now the single source of truth.