diff --git a/src/cell.rs b/src/cell.rs index 1875a5d..aac5539 100644 --- a/src/cell.rs +++ b/src/cell.rs @@ -7,6 +7,7 @@ use std::marker::PhantomData; /// library, but always require that the internal type implements `Copy` /// and implements `Copy` itself. #[derive(PartialEq, Eq)] +#[repr(transparent)] pub struct CopyCell { /// Internal value value: T, @@ -32,17 +33,10 @@ impl CopyCell { } impl CopyCell { - #[inline] - fn mut_ptr(&self) -> *mut T { - &self.value as *const T as *mut T - } - /// Returns a copy of the contained value. #[inline] pub fn get(&self) -> T { - unsafe { - *self.mut_ptr() - } + self.value } /// Returns a mutable reference to the underlying data. @@ -50,9 +44,11 @@ impl CopyCell { /// This call borrows `CopyCell` mutably, which gives us a compile time /// memory safety guarantee. #[inline] - pub fn get_mut(&mut self) -> &mut T { + pub fn get_mut<'a>(&'a mut self) -> &'a mut T { + // We can just cast the pointer from `CopyCell` to `T` because of + // #[repr(transparent)] unsafe { - &mut *self.mut_ptr() + &mut *(self as *mut CopyCell as *mut T) } } @@ -64,7 +60,14 @@ impl CopyCell { // Regular write produces abnormal behavior when running tests in // `--release` mode. Reordering writes when the compiler assumes // things are immutable is dangerous. - unsafe { write_volatile(self.mut_ptr(), value) }; + // + // We can just cast the pointer from `CopyCell` to `T` because of + // #[repr(transparent)] + // + // This behavior is copied over from the std implementation of + // the `UnsafeCell`, and it's the best we can do right now in terms + // of soundness till we get a stable `UnsafeCell` that implements `Copy`. + unsafe { write_volatile(self as *const CopyCell as *const T as *mut T, value) }; } }