]> 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 83eff71e2b80fc3463732f7540839cec6297316b..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
             }
         }
     }
@@ -221,25 +223,21 @@ pub fn new(value: T) -> Rc<T> {
     ///
     /// let weak_five = five.downgrade();
     /// ```
-    #[experimental = "Weak pointers may not belong in this module"]
+    #[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 }
     }
 }
 
 /// Get the number of weak references to this value.
 #[inline]
-#[experimental]
+#[unstable]
 pub fn weak_count<T>(this: &Rc<T>) -> uint { this.weak() - 1 }
 
 /// Get the number of strong references to this value.
 #[inline]
-#[experimental]
+#[unstable]
 pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() }
 
 /// Returns true if there are no other `Rc` or `Weak<T>` values that share the same inner value.
@@ -255,7 +253,7 @@ pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() }
 /// rc::is_unique(&five);
 /// ```
 #[inline]
-#[experimental]
+#[unstable]
 pub fn is_unique<T>(rc: &Rc<T>) -> bool {
     weak_count(rc) == 0 && strong_count(rc) == 1
 }
@@ -277,7 +275,7 @@ pub fn is_unique<T>(rc: &Rc<T>) -> bool {
 /// assert_eq!(rc::try_unwrap(x), Err(Rc::new(4u)));
 /// ```
 #[inline]
-#[experimental]
+#[unstable]
 pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
     if is_unique(&rc) {
         unsafe {
@@ -311,7 +309,7 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
 /// assert!(rc::get_mut(&mut x).is_none());
 /// ```
 #[inline]
-#[experimental]
+#[unstable]
 pub fn get_mut<'a, T>(rc: &'a mut Rc<T>) -> Option<&'a mut T> {
     if is_unique(rc) {
         let inner = unsafe { &mut **rc._ptr };
@@ -337,7 +335,7 @@ impl<T: Clone> Rc<T> {
     /// let mut_five = five.make_unique();
     /// ```
     #[inline]
-    #[experimental]
+    #[unstable]
     pub fn make_unique(&mut self) -> &mut T {
         if !is_unique(self) {
             *self = Rc::new((**self).clone())
@@ -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) {
@@ -615,30 +606,43 @@ fn hash(&self, state: &mut S) {
     }
 }
 
-#[experimental = "Show is experimental."]
+#[unstable = "Show is experimental."]
 impl<T: fmt::Show> fmt::Show for Rc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "Rc({:?})", **self)
     }
 }
 
+#[stable]
+impl<T: fmt::String> fmt::String for Rc<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::String::fmt(&**self, f)
+    }
+}
+
 /// A weak version of `Rc<T>`.
 ///
 /// Weak references do not count when determining if the inner value should be dropped.
 ///
 /// See the [module level documentation](../index.html) for more.
 #[unsafe_no_drop_flag]
-#[experimental = "Weak pointers may not belong in this module."]
+#[unstable = "Weak pointers may not belong in this module."]
 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
 }
 
-#[experimental = "Weak pointers may not belong in this module."]
+#[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.
@@ -661,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 })
         }
     }
 }
@@ -710,8 +714,9 @@ fn drop(&mut self) {
     }
 }
 
-#[experimental = "Weak pointers may not belong in this module."]
+#[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.
@@ -728,11 +733,11 @@ 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 }
     }
 }
 
-#[experimental = "Show is experimental."]
+#[unstable = "Show is experimental."]
 impl<T: fmt::Show> fmt::Show for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "(Weak)")
@@ -747,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() }
@@ -764,16 +783,34 @@ 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)]
-#[allow(experimental)]
+#[allow(unstable)]
 mod tests {
     use super::{Rc, Weak, weak_count, strong_count};
     use std::cell::RefCell;