Skip to content

Commit b9c0fe7

Browse files
committed
stablize weak pointers and uniqueness ops on Rc
1 parent 0649b16 commit b9c0fe7

File tree

1 file changed

+52
-34
lines changed

1 file changed

+52
-34
lines changed

src/liballoc/rc.rs

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ use core::fmt;
161161
use core::hash::{Hasher, Hash};
162162
use core::intrinsics::{assume, drop_in_place, abort};
163163
use core::marker::{self, Unsize};
164-
use core::mem::{self, align_of, size_of, align_of_val, size_of_val, forget};
164+
use core::mem::{self, align_of_val, size_of_val, forget};
165165
use core::nonzero::NonZero;
166166
use core::ops::{CoerceUnsized, Deref};
167167
use core::ptr;
@@ -218,10 +218,10 @@ impl<T> Rc<T> {
218218
}
219219
}
220220

221-
/// Unwraps the contained value if the `Rc<T>` is unique.
221+
/// Unwraps the contained value if the `Rc<T>` has only one strong reference.
222+
/// This will succeed even if there are outstanding weak references.
222223
///
223-
/// If the `Rc<T>` is not unique, an `Err` is returned with the same
224-
/// `Rc<T>`.
224+
/// Otherwise, an `Err` is returned with the same `Rc<T>`.
225225
///
226226
/// # Examples
227227
///
@@ -238,15 +238,22 @@ impl<T> Rc<T> {
238238
/// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4)));
239239
/// ```
240240
#[inline]
241-
#[unstable(feature = "rc_unique")]
241+
#[stable(feature = "rc_unique", since="1.4.0")]
242242
pub fn try_unwrap(rc: Rc<T>) -> Result<T, Rc<T>> {
243-
if Rc::is_unique(&rc) {
243+
if Rc::strong_count(&rc) == 1 {
244244
unsafe {
245+
let ptr = *rc._ptr;
245246
let val = ptr::read(&*rc); // copy the contained object
246-
// destruct the box and skip our Drop
247-
// we can ignore the refcounts because we know we're unique
248-
deallocate(*rc._ptr as *mut u8, size_of::<RcBox<T>>(),
249-
align_of::<RcBox<T>>());
247+
248+
// remove the implicit "strong weak" pointer now that we've
249+
// destroyed the contents.
250+
rc.dec_weak();
251+
252+
if rc.weak() == 0 {
253+
deallocate(ptr as *mut u8,
254+
size_of_val(&*ptr),
255+
align_of_val(&*ptr))
256+
}
250257
forget(rc);
251258
Ok(val)
252259
}
@@ -270,21 +277,20 @@ impl<T: ?Sized> Rc<T> {
270277
///
271278
/// let weak_five = five.downgrade();
272279
/// ```
273-
#[unstable(feature = "rc_weak",
274-
reason = "Weak pointers may not belong in this module")]
280+
#[stable(feature = "rc_weak", since = "1.4.0")]
275281
pub fn downgrade(&self) -> Weak<T> {
276282
self.inc_weak();
277283
Weak { _ptr: self._ptr }
278284
}
279285

280286
/// Get the number of weak references to this value.
281287
#[inline]
282-
#[unstable(feature = "rc_counts")]
288+
#[unstable(feature = "rc_counts", reason = "not clearly useful", issue = "27718")]
283289
pub fn weak_count(this: &Rc<T>) -> usize { this.weak() - 1 }
284290

285291
/// Get the number of strong references to this value.
286292
#[inline]
287-
#[unstable(feature = "rc_counts")]
293+
#[unstable(feature = "rc_counts", reason = "not clearly useful", issue = "27718")]
288294
pub fn strong_count(this: &Rc<T>) -> usize { this.strong() }
289295

290296
/// Returns true if there are no other `Rc` or `Weak<T>` values that share
@@ -302,13 +308,13 @@ impl<T: ?Sized> Rc<T> {
302308
/// assert!(Rc::is_unique(&five));
303309
/// ```
304310
#[inline]
305-
#[unstable(feature = "rc_unique")]
311+
#[unstable(feature = "rc_counts", reason = "uniqueness has unclear meaning", issue = "27718")]
306312
pub fn is_unique(rc: &Rc<T>) -> bool {
307313
Rc::weak_count(rc) == 0 && Rc::strong_count(rc) == 1
308314
}
309315

310-
/// Returns a mutable reference to the contained value if the `Rc<T>` is
311-
/// unique.
316+
/// Returns a mutable reference to the contained value if the `Rc<T>` has
317+
/// one strong reference and no weak references.
312318
///
313319
/// Returns `None` if the `Rc<T>` is not unique.
314320
///
@@ -327,7 +333,7 @@ impl<T: ?Sized> Rc<T> {
327333
/// assert!(Rc::get_mut(&mut x).is_none());
328334
/// ```
329335
#[inline]
330-
#[unstable(feature = "rc_unique")]
336+
#[stable(feature = "rc_unique", since = "1.4.0")]
331337
pub fn get_mut(rc: &mut Rc<T>) -> Option<&mut T> {
332338
if Rc::is_unique(rc) {
333339
let inner = unsafe { &mut **rc._ptr };
@@ -339,25 +345,40 @@ impl<T: ?Sized> Rc<T> {
339345
}
340346

341347
impl<T: Clone> Rc<T> {
342-
/// Make a mutable reference from the given `Rc<T>`.
348+
#[inline]
349+
#[unstable(feature = "renamed_rc_unique", reason = "renamed to make_mut", issue = "27718")]
350+
#[deprecated(since = "1.4.0", reason = "renamed to make_mut")]
351+
pub fn make_unique(&mut self) -> &mut T {
352+
Rc::make_mut(self)
353+
}
354+
355+
/// Make a mutable reference into the given `Rc<T>` by cloning the inner
356+
/// data if the `Rc<T>` doesn't have one strong reference and no weak
357+
/// references.
343358
///
344-
/// This is also referred to as a copy-on-write operation because the inner
345-
/// data is cloned if the reference count is greater than one.
359+
/// This is also referred to as a copy-on-write.
346360
///
347361
/// # Examples
348362
///
349363
/// ```
350-
/// #![feature(rc_unique)]
351-
///
352364
/// use std::rc::Rc;
353365
///
354-
/// let mut five = Rc::new(5);
366+
/// let mut data = Rc::new(5);
367+
///
368+
/// *data.make_mut() += 1; // Won't clone anything
369+
/// let mut other_data = data.clone(); // Won't clone inner data
370+
/// *data.make_mut() += 1; // Clones inner data
371+
/// *data.make_mut() += 1; // Won't clone anything
372+
/// *other_data.make_mut() *= 2; // Won't clone anything
373+
///
374+
/// // Note: data and other_data now point to different numbers
375+
/// assert_eq!(*data, 8);
376+
/// assert_eq!(*other_data, 12);
355377
///
356-
/// let mut_five = five.make_unique();
357378
/// ```
358379
#[inline]
359-
#[unstable(feature = "rc_unique")]
360-
pub fn make_unique(&mut self) -> &mut T {
380+
#[stable(feature = "rc_unique", since = "1.4.0")]
381+
pub fn make_mut(&mut self) -> &mut T {
361382
if !Rc::is_unique(self) {
362383
*self = Rc::new((**self).clone())
363384
}
@@ -412,7 +433,7 @@ impl<T: ?Sized> Drop for Rc<T> {
412433
unsafe {
413434
let ptr = *self._ptr;
414435
if !(*(&ptr as *const _ as *const *const ())).is_null() &&
415-
ptr as *const () as usize != mem::POST_DROP_USIZE {
436+
ptr as *const () as usize != mem::POST_DROP_USIZE {
416437
self.dec_strong();
417438
if self.strong() == 0 {
418439
// destroy the contained object
@@ -652,8 +673,7 @@ impl<T> fmt::Pointer for Rc<T> {
652673
///
653674
/// See the [module level documentation](./index.html) for more.
654675
#[unsafe_no_drop_flag]
655-
#[unstable(feature = "rc_weak",
656-
reason = "Weak pointers may not belong in this module.")]
676+
#[stable(feature = "rc_weak", since = "1.4.0")]
657677
pub struct Weak<T: ?Sized> {
658678
// FIXME #12808: strange names to try to avoid interfering with
659679
// field accesses of the contained type via Deref
@@ -665,8 +685,6 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
665685

666686
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
667687

668-
#[unstable(feature = "rc_weak",
669-
reason = "Weak pointers may not belong in this module.")]
670688
impl<T: ?Sized> Weak<T> {
671689

672690
/// Upgrades a weak reference to a strong reference.
@@ -689,6 +707,7 @@ impl<T: ?Sized> Weak<T> {
689707
///
690708
/// let strong_five: Option<Rc<_>> = weak_five.upgrade();
691709
/// ```
710+
#[stable(feature = "rc_weak", since = "1.4.0")]
692711
pub fn upgrade(&self) -> Option<Rc<T>> {
693712
if self.strong() == 0 {
694713
None
@@ -745,8 +764,7 @@ impl<T: ?Sized> Drop for Weak<T> {
745764
}
746765
}
747766

748-
#[unstable(feature = "rc_weak",
749-
reason = "Weak pointers may not belong in this module.")]
767+
#[stable(feature = "rc_weak", since = "1.4.0")]
750768
impl<T: ?Sized> Clone for Weak<T> {
751769

752770
/// Makes a clone of the `Weak<T>`.

0 commit comments

Comments
 (0)