diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c2d7febf98e5e..e0ff3a1bca030 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME(27718): rc_counts stuff is useful internally, but was previously public +#![allow(deprecated)] + //! Thread-local reference-counted boxes (the `Rc` type). //! //! The `Rc` type provides shared ownership of an immutable value. @@ -126,8 +129,8 @@ //! //! // Add the Gadgets to their Owner. To do this we mutably borrow from //! // the RefCell holding the Owner's Gadgets. -//! gadget_owner.gadgets.borrow_mut().push(gadget1.clone().downgrade()); -//! gadget_owner.gadgets.borrow_mut().push(gadget2.clone().downgrade()); +//! gadget_owner.gadgets.borrow_mut().push(Rc::downgrade(&gadget1)); +//! gadget_owner.gadgets.borrow_mut().push(Rc::downgrade(&gadget2)); //! //! // Iterate over our Gadgets, printing their details out //! for gadget_opt in gadget_owner.gadgets.borrow().iter() { @@ -161,7 +164,7 @@ use core::fmt; use core::hash::{Hasher, Hash}; use core::intrinsics::{assume, drop_in_place, abort}; use core::marker::{self, Unsize}; -use core::mem::{self, align_of, size_of, align_of_val, size_of_val, forget}; +use core::mem::{self, align_of_val, size_of_val, forget}; use core::nonzero::NonZero; use core::ops::{CoerceUnsized, Deref}; use core::ptr; @@ -218,10 +221,10 @@ impl Rc { } } - /// Unwraps the contained value if the `Rc` is unique. + /// Unwraps the contained value if the `Rc` has only one strong reference. + /// This will succeed even if there are outstanding weak references. /// - /// If the `Rc` is not unique, an `Err` is returned with the same - /// `Rc`. + /// Otherwise, an `Err` is returned with the same `Rc`. /// /// # Examples /// @@ -238,22 +241,32 @@ impl Rc { /// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); /// ``` #[inline] - #[unstable(feature = "rc_unique", issue = "27718")] - pub fn try_unwrap(rc: Rc) -> Result> { - if Rc::is_unique(&rc) { + #[unstable(feature = "rc_unique", reason= "needs FCP", issue = "27718")] + pub fn try_unwrap(this: Self) -> Result { + if Rc::would_unwrap(&this) { unsafe { - let val = ptr::read(&*rc); // copy the contained object - // destruct the box and skip our Drop - // we can ignore the refcounts because we know we're unique - deallocate(*rc._ptr as *mut u8, size_of::>(), - align_of::>()); - forget(rc); + let val = ptr::read(&*this); // copy the contained object + + // Indicate to Weaks that they can't be promoted by decrememting + // the strong count, and then remove the implicit "strong weak" + // pointer while also handling drop logic by just crafting a + // fake Weak. + this.dec_strong(); + let _weak = Weak { _ptr: this._ptr }; + forget(this); Ok(val) } } else { - Err(rc) + Err(this) } } + + /// Checks if `Rc::try_unwrap` would return `Ok`. + #[unstable(feature = "rc_would_unwrap", reason = "just added for niche usecase", + issue = "27718")] + pub fn would_unwrap(this: &Self) -> bool { + Rc::strong_count(&this) == 1 + } } impl Rc { @@ -268,25 +281,25 @@ impl Rc { /// /// let five = Rc::new(5); /// - /// let weak_five = five.downgrade(); + /// let weak_five = Rc::downgrade(&five); /// ``` - #[unstable(feature = "rc_weak", - reason = "Weak pointers may not belong in this module", - issue = "27718")] - pub fn downgrade(&self) -> Weak { - self.inc_weak(); - Weak { _ptr: self._ptr } + #[unstable(feature = "rc_weak", reason = "needs FCP", issue = "27718")] + pub fn downgrade(this: &Self) -> Weak { + this.inc_weak(); + Weak { _ptr: this._ptr } } /// Get the number of weak references to this value. #[inline] - #[unstable(feature = "rc_counts", issue = "27718")] - pub fn weak_count(this: &Rc) -> usize { this.weak() - 1 } + #[unstable(feature = "rc_counts", reason = "not clearly useful", issue = "27718")] + #[deprecated(since = "1.4.0", reason = "not clearly useful")] + pub fn weak_count(this: &Self) -> usize { this.weak() - 1 } /// Get the number of strong references to this value. #[inline] - #[unstable(feature = "rc_counts", issue= "27718")] - pub fn strong_count(this: &Rc) -> usize { this.strong() } + #[unstable(feature = "rc_counts", reason = "not clearly useful", issue = "27718")] + #[deprecated(since = "1.4.0", reason = "not clearly useful")] + pub fn strong_count(this: &Self) -> usize { this.strong() } /// Returns true if there are no other `Rc` or `Weak` values that share /// the same inner value. @@ -294,7 +307,7 @@ impl Rc { /// # Examples /// /// ``` - /// #![feature(rc_unique)] + /// #![feature(rc_counts)] /// /// use std::rc::Rc; /// @@ -303,13 +316,14 @@ impl Rc { /// assert!(Rc::is_unique(&five)); /// ``` #[inline] - #[unstable(feature = "rc_unique", issue = "27718")] - pub fn is_unique(rc: &Rc) -> bool { - Rc::weak_count(rc) == 0 && Rc::strong_count(rc) == 1 + #[unstable(feature = "rc_counts", reason = "uniqueness has unclear meaning", issue = "27718")] + #[deprecated(since = "1.4.0", reason = "uniqueness has unclear meaning")] + pub fn is_unique(this: &Self) -> bool { + Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1 } - /// Returns a mutable reference to the contained value if the `Rc` is - /// unique. + /// Returns a mutable reference to the contained value if the `Rc` has + /// one strong reference and no weak references. /// /// Returns `None` if the `Rc` is not unique. /// @@ -328,10 +342,10 @@ impl Rc { /// assert!(Rc::get_mut(&mut x).is_none()); /// ``` #[inline] - #[unstable(feature = "rc_unique", issue = "27718")] - pub fn get_mut(rc: &mut Rc) -> Option<&mut T> { - if Rc::is_unique(rc) { - let inner = unsafe { &mut **rc._ptr }; + #[unstable(feature = "rc_unique", reason = "needs FCP", issue = "27718")] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if Rc::is_unique(this) { + let inner = unsafe { &mut **this._ptr }; Some(&mut inner.value) } else { None @@ -340,34 +354,62 @@ impl Rc { } impl Rc { - /// Make a mutable reference from the given `Rc`. + #[inline] + #[unstable(feature = "rc_unique", reason = "renamed to Rc::make_mut", issue = "27718")] + #[deprecated(since = "1.4.0", reason = "renamed to Rc::make_mut")] + pub fn make_unique(&mut self) -> &mut T { + Rc::make_mut(self) + } + + /// Make a mutable reference into the given `Rc` by cloning the inner + /// data if the `Rc` doesn't have one strong reference and no weak + /// references. /// - /// This is also referred to as a copy-on-write operation because the inner - /// data is cloned if the reference count is greater than one. + /// This is also referred to as a copy-on-write. /// /// # Examples /// /// ``` /// #![feature(rc_unique)] - /// /// use std::rc::Rc; /// - /// let mut five = Rc::new(5); + /// let mut data = Rc::new(5); + /// + /// *Rc::make_mut(&mut data) += 1; // Won't clone anything + /// let mut other_data = data.clone(); // Won't clone inner data + /// *Rc::make_mut(&mut data) += 1; // Clones inner data + /// *Rc::make_mut(&mut data) += 1; // Won't clone anything + /// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything + /// + /// // Note: data and other_data now point to different numbers + /// assert_eq!(*data, 8); + /// assert_eq!(*other_data, 12); /// - /// let mut_five = five.make_unique(); /// ``` #[inline] - #[unstable(feature = "rc_unique", issue = "27718")] - pub fn make_unique(&mut self) -> &mut T { - if !Rc::is_unique(self) { - *self = Rc::new((**self).clone()) + #[unstable(feature = "rc_unique", reason = "needs FCP", issue = "27718")] + pub fn make_mut(this: &mut Self) -> &mut T { + if Rc::strong_count(this) != 1 { + // Gotta clone the data, there are other Rcs + *this = Rc::new((**this).clone()) + } else if Rc::weak_count(this) != 0 { + // Can just steal the data, all that's left is Weaks + unsafe { + let mut swap = Rc::new(ptr::read(&(**this._ptr).value)); + mem::swap(this, &mut swap); + swap.dec_strong(); + // Remove implicit strong-weak ref (no need to craft a fake + // Weak here -- we know other Weaks can clean up for us) + swap.dec_weak(); + forget(swap); + } } // This unsafety is ok because we're guaranteed that the pointer // returned is the *only* pointer that will ever be returned to T. Our // reference count is guaranteed to be 1 at this point, and we required // the `Rc` itself to be `mut`, so we're returning the only possible // reference to the inner value. - let inner = unsafe { &mut **self._ptr }; + let inner = unsafe { &mut **this._ptr }; &mut inner.value } } @@ -413,7 +455,7 @@ impl Drop for Rc { unsafe { let ptr = *self._ptr; if !(*(&ptr as *const _ as *const *const ())).is_null() && - ptr as *const () as usize != mem::POST_DROP_USIZE { + ptr as *const () as usize != mem::POST_DROP_USIZE { self.dec_strong(); if self.strong() == 0 { // destroy the contained object @@ -653,9 +695,7 @@ impl fmt::Pointer for Rc { /// /// See the [module level documentation](./index.html) for more. #[unsafe_no_drop_flag] -#[unstable(feature = "rc_weak", - reason = "Weak pointers may not belong in this module.", - issue = "27718")] +#[unstable(feature = "rc_weak", reason = "needs FCP", issue = "27718")] pub struct Weak { // FIXME #12808: strange names to try to avoid interfering with // field accesses of the contained type via Deref @@ -667,11 +707,7 @@ impl !marker::Sync for Weak {} impl, U: ?Sized> CoerceUnsized> for Weak {} -#[unstable(feature = "rc_weak", - reason = "Weak pointers may not belong in this module.", - issue = "27718")] impl Weak { - /// Upgrades a weak reference to a strong reference. /// /// Upgrades the `Weak` reference to an `Rc`, if possible. @@ -688,10 +724,11 @@ impl Weak { /// /// let five = Rc::new(5); /// - /// let weak_five = five.downgrade(); + /// let weak_five = Rc::downgrade(&five); /// /// let strong_five: Option> = weak_five.upgrade(); /// ``` + #[unstable(feature = "rc_weak", reason = "needs FCP", issue = "27718")] pub fn upgrade(&self) -> Option> { if self.strong() == 0 { None @@ -717,7 +754,7 @@ impl Drop for Weak { /// /// { /// let five = Rc::new(5); - /// let weak_five = five.downgrade(); + /// let weak_five = Rc::downgrade(&five); /// /// // stuff /// @@ -725,7 +762,7 @@ impl Drop for Weak { /// } /// { /// let five = Rc::new(5); - /// let weak_five = five.downgrade(); + /// let weak_five = Rc::downgrade(&five); /// /// // stuff /// @@ -735,7 +772,7 @@ impl Drop for Weak { unsafe { let ptr = *self._ptr; if !(*(&ptr as *const _ as *const *const ())).is_null() && - ptr as *const () as usize != mem::POST_DROP_USIZE { + ptr as *const () as usize != mem::POST_DROP_USIZE { self.dec_weak(); // the weak count starts at 1, and will only go to zero if all // the strong pointers have disappeared. @@ -748,9 +785,7 @@ impl Drop for Weak { } } -#[unstable(feature = "rc_weak", - reason = "Weak pointers may not belong in this module.", - issue = "27718")] +#[unstable(feature = "rc_weak", reason = "needs FCP", issue = "27718")] impl Clone for Weak { /// Makes a clone of the `Weak`. @@ -764,7 +799,7 @@ impl Clone for Weak { /// /// use std::rc::Rc; /// - /// let weak_five = Rc::new(5).downgrade(); + /// let weak_five = Rc::downgrade(&Rc::new(5)); /// /// weak_five.clone(); /// ``` @@ -888,14 +923,14 @@ mod tests { #[test] fn test_live() { let x = Rc::new(5); - let y = x.downgrade(); + let y = Rc::downgrade(&x); assert!(y.upgrade().is_some()); } #[test] fn test_dead() { let x = Rc::new(5); - let y = x.downgrade(); + let y = Rc::downgrade(&x); drop(x); assert!(y.upgrade().is_none()); } @@ -907,7 +942,7 @@ mod tests { } let a = Rc::new(Cycle { x: RefCell::new(None) }); - let b = a.clone().downgrade(); + let b = Rc::downgrade(&a.clone()); *a.x.borrow_mut() = Some(b); // hopefully we don't double-free (or leak)... @@ -921,7 +956,7 @@ mod tests { assert!(!Rc::is_unique(&x)); drop(y); assert!(Rc::is_unique(&x)); - let w = x.downgrade(); + let w = Rc::downgrade(&x); assert!(!Rc::is_unique(&x)); drop(w); assert!(Rc::is_unique(&x)); @@ -931,7 +966,7 @@ mod tests { fn test_strong_count() { let a = Rc::new(0u32); assert!(Rc::strong_count(&a) == 1); - let w = a.downgrade(); + let w = Rc::downgrade(&a); assert!(Rc::strong_count(&a) == 1); let b = w.upgrade().expect("upgrade of live rc failed"); assert!(Rc::strong_count(&b) == 2); @@ -949,7 +984,7 @@ mod tests { let a = Rc::new(0u32); assert!(Rc::strong_count(&a) == 1); assert!(Rc::weak_count(&a) == 0); - let w = a.downgrade(); + let w = Rc::downgrade(&a); assert!(Rc::strong_count(&a) == 1); assert!(Rc::weak_count(&a) == 1); drop(w); @@ -969,8 +1004,8 @@ mod tests { let _y = x.clone(); assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); let x = Rc::new(5); - let _w = x.downgrade(); - assert_eq!(Rc::try_unwrap(x), Err(Rc::new(5))); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::try_unwrap(x), Ok(5)); } #[test] @@ -982,7 +1017,7 @@ mod tests { assert!(Rc::get_mut(&mut x).is_none()); drop(y); assert!(Rc::get_mut(&mut x).is_some()); - let _w = x.downgrade(); + let _w = Rc::downgrade(&x); assert!(Rc::get_mut(&mut x).is_none()); } @@ -992,13 +1027,13 @@ mod tests { let mut cow1 = cow0.clone(); let mut cow2 = cow1.clone(); - assert!(75 == *cow0.make_unique()); - assert!(75 == *cow1.make_unique()); - assert!(75 == *cow2.make_unique()); + assert!(75 == *Rc::make_mut(&mut cow0)); + assert!(75 == *Rc::make_mut(&mut cow1)); + assert!(75 == *Rc::make_mut(&mut cow2)); - *cow0.make_unique() += 1; - *cow1.make_unique() += 2; - *cow2.make_unique() += 3; + *Rc::make_mut(&mut cow0) += 1; + *Rc::make_mut(&mut cow1) += 2; + *Rc::make_mut(&mut cow2) += 3; assert!(76 == *cow0); assert!(77 == *cow1); @@ -1020,7 +1055,7 @@ mod tests { assert!(75 == *cow1); assert!(75 == *cow2); - *cow0.make_unique() += 1; + *Rc::make_mut(&mut cow0) += 1; assert!(76 == *cow0); assert!(75 == *cow1); @@ -1036,12 +1071,12 @@ mod tests { #[test] fn test_cowrc_clone_weak() { let mut cow0 = Rc::new(75); - let cow1_weak = cow0.downgrade(); + let cow1_weak = Rc::downgrade(&cow0); assert!(75 == *cow0); assert!(75 == *cow1_weak.upgrade().unwrap()); - *cow0.make_unique() += 1; + *Rc::make_mut(&mut cow0) += 1; assert!(76 == *cow0); assert!(cow1_weak.upgrade().is_none());