A fix that stops panics from the old MaybeUninit impl

This commit is contained in:
Emil Fresk 2019-08-09 14:08:44 +02:00
parent eca12fecef
commit d5b665e28f

View file

@ -64,13 +64,11 @@ impl Priority {
} }
} }
#[cfg(feature = "nightly")]
pub struct MaybeUninit<T> { pub struct MaybeUninit<T> {
// we newtype so the end-user doesn't need `#![feature(maybe_uninit)]` in their code // we newtype so the end-user doesn't need `#![feature(maybe_uninit)]` in their code
inner: core::mem::MaybeUninit<T>, inner: core::mem::MaybeUninit<T>,
} }
#[cfg(feature = "nightly")]
impl<T> MaybeUninit<T> { impl<T> MaybeUninit<T> {
pub const fn uninit() -> Self { pub const fn uninit() -> Self {
MaybeUninit { MaybeUninit {
@ -86,61 +84,28 @@ impl<T> MaybeUninit<T> {
self.inner.as_mut_ptr() self.inner.as_mut_ptr()
} }
#[cfg(feature = "nightly")]
pub fn write(&mut self, value: T) -> &mut T { pub fn write(&mut self, value: T) -> &mut T {
self.inner.write(value) self.inner.write(value)
} }
}
#[cfg(not(feature = "nightly"))]
pub struct MaybeUninit<T> {
value: Option<T>,
}
#[cfg(not(feature = "nightly"))]
const MSG: &str =
"you have hit a bug (UB) in RTFM implementation; try enabling this crate 'nightly' feature";
#[cfg(not(feature = "nightly"))]
impl<T> MaybeUninit<T> {
pub const fn uninit() -> Self {
MaybeUninit { value: None }
}
pub fn as_ptr(&self) -> *const T {
if let Some(x) = self.value.as_ref() {
x
} else {
unreachable!(MSG)
}
}
pub fn as_mut_ptr(&mut self) -> *mut T {
if let Some(x) = self.value.as_mut() {
x
} else {
unreachable!(MSG)
}
}
#[cfg(not(feature = "nightly"))]
pub unsafe fn get_ref(&self) -> &T { pub unsafe fn get_ref(&self) -> &T {
if let Some(x) = self.value.as_ref() { &*self.inner.as_ptr()
x
} else {
unreachable!(MSG)
}
} }
#[cfg(not(feature = "nightly"))]
pub unsafe fn get_mut(&mut self) -> &mut T { pub unsafe fn get_mut(&mut self) -> &mut T {
if let Some(x) = self.value.as_mut() { &mut *self.inner.as_mut_ptr()
x
} else {
unreachable!(MSG)
}
} }
pub fn write(&mut self, val: T) { #[cfg(not(feature = "nightly"))]
// NOTE(volatile) we have observed UB when this uses a plain `ptr::write` pub fn write(&mut self, value: T) -> &mut T {
unsafe { ptr::write_volatile(&mut self.value, Some(val)) } let ptr = self.inner.as_mut_ptr();
unsafe {
ptr::write_volatile(ptr, value);
&mut *ptr
}
} }
} }