@@ -7,6 +7,7 @@ use std::marker::PhantomData;
77/// library, but always require that the internal type implements `Copy`
88/// and implements `Copy` itself.
99#[ derive( PartialEq , Eq ) ]
10+ #[ repr( transparent) ]
1011pub struct CopyCell < T > {
1112 /// Internal value
1213 value : T ,
@@ -32,27 +33,22 @@ impl<T> CopyCell<T> {
3233}
3334
3435impl < T : Copy > CopyCell < T > {
35- #[ inline]
36- fn mut_ptr ( & self ) -> * mut T {
37- & self . value as * const T as * mut T
38- }
39-
4036 /// Returns a copy of the contained value.
4137 #[ inline]
4238 pub fn get ( & self ) -> T {
43- unsafe {
44- * self . mut_ptr ( )
45- }
39+ self . value
4640 }
4741
4842 /// Returns a mutable reference to the underlying data.
4943 ///
5044 /// This call borrows `CopyCell` mutably, which gives us a compile time
5145 /// memory safety guarantee.
5246 #[ inline]
53- pub fn get_mut ( & mut self ) -> & mut T {
47+ pub fn get_mut < ' a > ( & ' a mut self ) -> & ' a mut T {
48+ // We can just cast the pointer from `CopyCell<T>` to `T` because of
49+ // #[repr(transparent)]
5450 unsafe {
55- & mut * self . mut_ptr ( )
51+ & mut * ( self as * mut CopyCell < T > as * mut T )
5652 }
5753 }
5854
@@ -64,7 +60,14 @@ impl<T: Copy> CopyCell<T> {
6460 // Regular write produces abnormal behavior when running tests in
6561 // `--release` mode. Reordering writes when the compiler assumes
6662 // things are immutable is dangerous.
67- unsafe { write_volatile ( self . mut_ptr ( ) , value) } ;
63+ //
64+ // We can just cast the pointer from `CopyCell<T>` to `T` because of
65+ // #[repr(transparent)]
66+ //
67+ // This behavior is copied over from the std implementation of
68+ // the `UnsafeCell`, and it's the best we can do right now in terms
69+ // of soundness till we get a stable `UnsafeCell` that implements `Copy`.
70+ unsafe { write_volatile ( self as * const CopyCell < T > as * const T as * mut T , value) } ;
6871 }
6972}
7073
0 commit comments