Bug 1549596 - Use PhantomData<T> in servo_arc. r=bholley
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 08 May 2019 08:01:01 +0000
changeset 534901 63d77dbcfda80e420a7e35c2b4244a7a67a5bef2
parent 534900 48edd877bde3ebbf5efc525eddad22099c0673ad
child 534902 7602b3fa01c780c9159329c9f99202b7c26462bb
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1549596, 60594
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1549596 - Use PhantomData<T> in servo_arc. r=bholley See https://github.com/rust-lang/rust/pull/60594#issuecomment-489966933 Differential Revision: https://phabricator.services.mozilla.com/D30169
servo/components/servo_arc/lib.rs
--- a/servo/components/servo_arc/lib.rs
+++ b/servo/components/servo_arc/lib.rs
@@ -81,20 +81,24 @@ const MAX_REFCOUNT: usize = (isize::MAX)
 /// and that the `Arc` is really acting as a read-only static reference.
 const STATIC_REFCOUNT: usize = usize::MAX;
 
 /// An atomically reference counted shared pointer
 ///
 /// See the documentation for [`Arc`] in the standard library. Unlike the
 /// standard library `Arc`, this `Arc` does not support weak reference counting.
 ///
+/// See the discussion in https://github.com/rust-lang/rust/pull/60594 for the
+/// usage of PhantomData.
+///
 /// [`Arc`]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html
 #[repr(C)]
 pub struct Arc<T: ?Sized> {
     p: ptr::NonNull<ArcInner<T>>,
+    phantom: PhantomData<T>,
 }
 
 /// An `Arc` that is known to be uniquely owned
 ///
 /// When `Arc`s are constructed, they are known to be
 /// uniquely owned. In such a case it is safe to mutate
 /// the contents of the `Arc`. Normally, one would just handle
 /// this by mutating the data on the stack before allocating the
@@ -164,16 +168,17 @@ impl<T> Arc<T> {
     pub fn new(data: T) -> Self {
         let x = Box::new(ArcInner {
             count: atomic::AtomicUsize::new(1),
             data: data,
         });
         unsafe {
             Arc {
                 p: ptr::NonNull::new_unchecked(Box::into_raw(x)),
+                phantom: PhantomData,
             }
         }
     }
 
     /// Convert the Arc<T> to a raw pointer, suitable for use across FFI
     ///
     /// Note: This returns a pointer to the data T, which is offset in the allocation.
     ///
@@ -193,16 +198,17 @@ impl<T> Arc<T> {
     /// It is recommended to use RawOffsetArc for this
     #[inline]
     unsafe fn from_raw(ptr: *const T) -> Self {
         // To find the corresponding pointer to the `ArcInner` we need
         // to subtract the offset of the `data` field from the pointer.
         let ptr = (ptr as *const u8).offset(-offset_of!(ArcInner<T>, data));
         Arc {
             p: ptr::NonNull::new_unchecked(ptr as *mut ArcInner<T>),
+            phantom: PhantomData,
         }
     }
 
     /// Create a new static Arc<T> (one that won't reference count the object)
     /// and place it in the allocation provided by the specified `alloc`
     /// function.
     ///
     /// `alloc` must return a pointer into a static allocation suitable for
@@ -219,16 +225,17 @@ impl<T> Arc<T> {
             count: atomic::AtomicUsize::new(STATIC_REFCOUNT),
             data,
         };
 
         ptr::write(ptr, x);
 
         Arc {
             p: ptr::NonNull::new_unchecked(ptr),
+            phantom: PhantomData,
         }
     }
 
     /// Produce a pointer to the data that can be converted back
     /// to an Arc. This is basically an `&Arc<T>`, without the extra indirection.
     /// It has the benefits of an `&T` but also knows about the underlying refcount
     /// and can be converted into more `Arc<T>`s if necessary.
     #[inline]
@@ -329,16 +336,17 @@ impl<T: ?Sized> Clone for Arc<T> {
             if old_size > MAX_REFCOUNT {
                 process::abort();
             }
         }
 
         unsafe {
             Arc {
                 p: ptr::NonNull::new_unchecked(self.ptr()),
+                phantom: PhantomData,
             }
         }
     }
 }
 
 impl<T: ?Sized> Deref for Arc<T> {
     type Target = T;
 
@@ -682,16 +690,17 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
         assert_eq!(
             size_of::<Self>(),
             size_of::<usize>() * 2,
             "The Arc will be fat"
         );
         unsafe {
             Arc {
                 p: ptr::NonNull::new_unchecked(ptr),
+                phantom: PhantomData,
             }
         }
     }
 
     /// Creates an Arc for a HeaderSlice using the given header struct and
     /// iterator to generate the slice. The resulting Arc will be fat.
     #[inline]
     pub fn from_header_and_iter<I>(header: H, items: I) -> Self
@@ -763,16 +772,17 @@ type HeaderSliceWithLength<H, T> = Heade
 /// have a thin pointer instead, perhaps for FFI compatibility
 /// or space efficiency.
 ///
 /// `ThinArc` solves this by storing the length in the allocation itself,
 /// via `HeaderSliceWithLength`.
 #[repr(C)]
 pub struct ThinArc<H, T> {
     ptr: ptr::NonNull<ArcInner<HeaderSliceWithLength<H, [T; 1]>>>,
+    phantom: PhantomData<(H, T)>,
 }
 
 unsafe impl<H: Sync + Send, T: Sync + Send> Send for ThinArc<H, T> {}
 unsafe impl<H: Sync + Send, T: Sync + Send> Sync for ThinArc<H, T> {}
 
 // Synthesize a fat pointer from a thin pointer.
 //
 // See the comment around the analogous operation in from_header_and_iter.
@@ -792,16 +802,17 @@ impl<H, T> ThinArc<H, T> {
     pub fn with_arc<F, U>(&self, f: F) -> U
     where
         F: FnOnce(&Arc<HeaderSliceWithLength<H, [T]>>) -> U,
     {
         // Synthesize transient Arc, which never touches the refcount of the ArcInner.
         let transient = unsafe {
             NoDrop::new(Arc {
                 p: ptr::NonNull::new_unchecked(thin_to_thick(self.ptr.as_ptr())),
+                phantom: PhantomData,
             })
         };
 
         // Expose the transient Arc to the callback, which may clone it if it wants.
         let result = f(&transient);
 
         // Forget the transient Arc to leave the refcount untouched.
         // XXXManishearth this can be removed when unions stabilize,
@@ -870,17 +881,17 @@ impl<H, T> Clone for ThinArc<H, T> {
     fn clone(&self) -> Self {
         ThinArc::with_arc(self, |a| Arc::into_thin(a.clone()))
     }
 }
 
 impl<H, T> Drop for ThinArc<H, T> {
     #[inline]
     fn drop(&mut self) {
-        let _ = Arc::from_thin(ThinArc { ptr: self.ptr });
+        let _ = Arc::from_thin(ThinArc { ptr: self.ptr, phantom: PhantomData, });
     }
 }
 
 impl<H, T> Arc<HeaderSliceWithLength<H, [T]>> {
     /// Converts an `Arc` into a `ThinArc`. This consumes the `Arc`, so the refcount
     /// is not modified.
     #[inline]
     pub fn into_thin(a: Self) -> ThinArc<H, T> {
@@ -891,28 +902,30 @@ impl<H, T> Arc<HeaderSliceWithLength<H, 
         );
         let fat_ptr: *mut ArcInner<HeaderSliceWithLength<H, [T]>> = a.ptr();
         mem::forget(a);
         let thin_ptr = fat_ptr as *mut [usize] as *mut usize;
         ThinArc {
             ptr: unsafe {
                 ptr::NonNull::new_unchecked(thin_ptr as *mut ArcInner<HeaderSliceWithLength<H, [T; 1]>>)
             },
+            phantom: PhantomData,
         }
     }
 
     /// Converts a `ThinArc` into an `Arc`. This consumes the `ThinArc`, so the refcount
     /// is not modified.
     #[inline]
     pub fn from_thin(a: ThinArc<H, T>) -> Self {
         let ptr = thin_to_thick(a.ptr.as_ptr());
         mem::forget(a);
         unsafe {
             Arc {
                 p: ptr::NonNull::new_unchecked(ptr),
+                phantom: PhantomData,
             }
         }
     }
 }
 
 impl<H: PartialEq, T: PartialEq> PartialEq for ThinArc<H, T> {
     #[inline]
     fn eq(&self, other: &ThinArc<H, T>) -> bool {