]> git.lizzy.rs Git - rust.git/blobdiff - src/liballoc/rc.rs
rollup merge of #21438: taralx/kill-racycell
[rust.git] / src / liballoc / rc.rs
index f42c6dbdc15a592721d2f7422e53bc2c8e3cb68e..59bdd1e968cfae4115d29db0903164c461684609 100644 (file)
 use core::ptr::{self, PtrExt};
 use core::result::Result;
 use core::result::Result::{Ok, Err};
+use core::intrinsics::assume;
 
 use heap::deallocate;
 
@@ -178,11 +179,14 @@ pub struct Rc<T> {
     // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained
     // type via Deref
     _ptr: NonZero<*mut RcBox<T>>,
-    _nosend: marker::NoSend,
-    _noshare: marker::NoSync
 }
 
+impl<T> !marker::Send for Rc<T> {}
+
+impl<T> !marker::Sync for Rc<T> {}
+
 impl<T> Rc<T> {
+
     /// Constructs a new `Rc<T>`.
     ///
     /// # Examples
@@ -204,8 +208,6 @@ pub fn new(value: T) -> Rc<T> {
                     strong: Cell::new(1),
                     weak: Cell::new(1)
                 })),
-                _nosend: marker::NoSend,
-                _noshare: marker::NoSync
             }
         }
     }
@@ -224,11 +226,7 @@ pub fn new(value: T) -> Rc<T> {
     #[unstable = "Weak pointers may not belong in this module"]
     pub fn downgrade(&self) -> Weak<T> {
         self.inc_weak();
-        Weak {
-            _ptr: self._ptr,
-            _nosend: marker::NoSend,
-            _noshare: marker::NoSync
-        }
+        Weak { _ptr: self._ptr }
     }
 }
 
@@ -418,6 +416,7 @@ fn drop(&mut self) {
 
 #[stable]
 impl<T> Clone for Rc<T> {
+
     /// Makes a clone of the `Rc<T>`.
     ///
     /// This increases the strong reference count.
@@ -434,7 +433,7 @@ impl<T> Clone for Rc<T> {
     #[inline]
     fn clone(&self) -> Rc<T> {
         self.inc_strong();
-        Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
+        Rc { _ptr: self._ptr }
     }
 }
 
@@ -600,14 +599,6 @@ fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
 }
 
 // FIXME (#18248) Make `T` `Sized?`
-#[cfg(stage0)]
-impl<S: hash::Writer, T: Hash<S>> Hash<S> for Rc<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
-    }
-}
-#[cfg(not(stage0))]
 impl<S: hash::Hasher, T: Hash<S>> Hash<S> for Rc<T> {
     #[inline]
     fn hash(&self, state: &mut S) {
@@ -640,12 +631,18 @@ pub struct Weak<T> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
     _ptr: NonZero<*mut RcBox<T>>,
-    _nosend: marker::NoSend,
-    _noshare: marker::NoSync
 }
 
+#[allow(unstable)]
+impl<T> !marker::Send for Weak<T> {}
+
+#[allow(unstable)]
+impl<T> !marker::Sync for Weak<T> {}
+
+
 #[unstable = "Weak pointers may not belong in this module."]
 impl<T> Weak<T> {
+
     /// Upgrades a weak reference to a strong reference.
     ///
     /// Upgrades the `Weak<T>` reference to an `Rc<T>`, if possible.
@@ -668,7 +665,7 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
             None
         } else {
             self.inc_strong();
-            Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync })
+            Some(Rc { _ptr: self._ptr })
         }
     }
 }
@@ -719,6 +716,7 @@ fn drop(&mut self) {
 
 #[unstable = "Weak pointers may not belong in this module."]
 impl<T> Clone for Weak<T> {
+
     /// Makes a clone of the `Weak<T>`.
     ///
     /// This increases the weak reference count.
@@ -735,7 +733,7 @@ impl<T> Clone for Weak<T> {
     #[inline]
     fn clone(&self) -> Weak<T> {
         self.inc_weak();
-        Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
+        Weak { _ptr: self._ptr }
     }
 }
 
@@ -754,10 +752,24 @@ trait RcBoxPtr<T> {
     fn strong(&self) -> uint { self.inner().strong.get() }
 
     #[inline]
-    fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); }
+    fn inc_strong(&self) {
+        let strong = self.strong();
+        // The reference count is always at least one unless we're about to drop the type
+        // This allows the bulk of the destructor to be omitted in cases where we know that
+        // the reference count must be > 0.
+        unsafe { assume(strong > 0); }
+        self.inner().strong.set(strong + 1);
+    }
 
     #[inline]
-    fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
+    fn dec_strong(&self) {
+        let strong = self.strong();
+        // The reference count is always at least one unless we're about to drop the type
+        // This allows the bulk of the destructor to be omitted in cases where we know that
+        // the reference count must be > 0
+        unsafe { assume(strong > 0); }
+        self.inner().strong.set(strong - 1);
+    }
 
     #[inline]
     fn weak(&self) -> uint { self.inner().weak.get() }
@@ -771,12 +783,30 @@ fn weak(&self) -> uint { self.inner().weak.get() }
 
 impl<T> RcBoxPtr<T> for Rc<T> {
     #[inline(always)]
-    fn inner(&self) -> &RcBox<T> { unsafe { &(**self._ptr) } }
+    fn inner(&self) -> &RcBox<T> {
+        unsafe {
+            // Safe to assume this here, as if it weren't true, we'd be breaking
+            // the contract anyway.
+            // This allows the null check to be elided in the destructor if we
+            // manipulated the reference count in the same function.
+            assume(!self._ptr.is_null());
+            &(**self._ptr)
+        }
+    }
 }
 
 impl<T> RcBoxPtr<T> for Weak<T> {
     #[inline(always)]
-    fn inner(&self) -> &RcBox<T> { unsafe { &(**self._ptr) } }
+    fn inner(&self) -> &RcBox<T> {
+        unsafe {
+            // Safe to assume this here, as if it weren't true, we'd be breaking
+            // the contract anyway
+            // This allows the null check to be elided in the destructor if we
+            // manipulated the reference count in the same function.
+            assume(!self._ptr.is_null());
+            &(**self._ptr)
+        }
+    }
 }
 
 #[cfg(test)]