Make Rc DST-compatible

This commit is contained in:
Nick Cameron 2015-04-16 14:36:47 +12:00
parent 843db01bd9
commit 7d953538d1

View File

@ -159,7 +159,7 @@ use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{Hasher, Hash};
use core::marker;
use core::marker::{self, Sized};
use core::mem::{self, min_align_of, size_of, forget};
use core::nonzero::NonZero;
use core::ops::{Deref, Drop};
@ -170,17 +170,36 @@ use core::result::Result;
use core::result::Result::{Ok, Err};
use core::intrinsics::assume;
#[cfg(not(stage0))]
use core::intrinsics::drop_in_place;
#[cfg(not(stage0))]
use core::marker::Unsize;
#[cfg(not(stage0))]
use core::mem::{min_align_of_val, size_of_val};
#[cfg(not(stage0))]
use core::ops::CoerceUnsized;
use heap::deallocate;
#[cfg(stage0)]
struct RcBox<T> {
strong: Cell<usize>,
weak: Cell<usize>,
value: T
value: T,
}
#[cfg(not(stage0))]
struct RcBox<T: ?Sized> {
strong: Cell<usize>,
weak: Cell<usize>,
value: T,
}
/// A reference-counted pointer type over an immutable value.
///
/// See the [module level documentation](./index.html) for more details.
#[cfg(stage0)]
#[unsafe_no_drop_flag]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc<T> {
@ -188,11 +207,30 @@ pub struct Rc<T> {
// accesses of the contained type via Deref
_ptr: NonZero<*mut RcBox<T>>,
}
#[cfg(not(stage0))]
#[unsafe_no_drop_flag]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc<T: ?Sized> {
// FIXME #12808: strange names to try to avoid interfering with field
// accesses of the contained type via Deref
_ptr: NonZero<*mut RcBox<T>>,
}
#[cfg(stage0)]
impl<T> !marker::Send for Rc<T> {}
#[cfg(not(stage0))]
impl<T: ?Sized> !marker::Send for Rc<T> {}
#[cfg(stage0)]
impl<T> !marker::Sync for Rc<T> {}
#[cfg(not(stage0))]
impl<T: ?Sized> !marker::Sync for Rc<T> {}
#[cfg(not(stage0))] // SNAP c64d671
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
impl<T> Rc<T> {
/// Constructs a new `Rc<T>`.
///
@ -212,14 +250,39 @@ impl<T> Rc<T> {
// the allocation while the strong destructor is running, even
// if the weak pointer is stored inside the strong one.
_ptr: NonZero::new(boxed::into_raw(box RcBox {
value: value,
strong: Cell::new(1),
weak: Cell::new(1)
weak: Cell::new(1),
value: value
})),
}
}
}
}
#[cfg(not(stage0))]
impl<T: ?Sized> Rc<T> {
/// Downgrades the `Rc<T>` to a `Weak<T>` reference.
///
/// # Examples
///
/// ```
/// # #![feature(alloc)]
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
///
/// let weak_five = five.downgrade();
/// ```
#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module")]
pub fn downgrade(&self) -> Weak<T> {
self.inc_weak();
Weak { _ptr: self._ptr }
}
}
#[cfg(stage0)]
impl<T> Rc<T> {
/// Downgrades the `Rc<T>` to a `Weak<T>` reference.
///
/// # Examples
@ -241,14 +304,24 @@ impl<T> Rc<T> {
}
/// Get the number of weak references to this value.
#[cfg(stage0)]
#[inline]
#[unstable(feature = "alloc")]
pub fn weak_count<T>(this: &Rc<T>) -> usize { this.weak() - 1 }
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "alloc")]
pub fn weak_count<T: ?Sized>(this: &Rc<T>) -> usize { this.weak() - 1 }
/// Get the number of strong references to this value.
#[cfg(stage0)]
#[inline]
#[unstable(feature = "alloc")]
pub fn strong_count<T>(this: &Rc<T>) -> usize { this.strong() }
#[cfg(not(stage0))]
#[inline]
#[unstable(feature = "alloc")]
pub fn strong_count<T: ?Sized>(this: &Rc<T>) -> usize { this.strong() }
/// Returns true if there are no other `Rc` or `Weak<T>` values that share the
/// same inner value.
@ -365,6 +438,7 @@ impl<T: Clone> Rc<T> {
}
}
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Deref for Rc<T> {
type Target = T;
@ -374,7 +448,19 @@ impl<T> Deref for Rc<T> {
&self.inner().value
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Rc<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
&self.inner().value
}
}
#[cfg(stage0)] // SNAP c64d671
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Rc<T> {
/// Drops the `Rc<T>`.
@ -425,6 +511,61 @@ impl<T> Drop for Rc<T> {
}
}
#[cfg(not(stage0))] // SNAP c64d671
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for Rc<T> {
/// Drops the `Rc<T>`.
///
/// This will decrement the strong reference count. If the strong reference
/// count becomes zero and the only other references are `Weak<T>` ones,
/// `drop`s the inner value.
///
/// # Examples
///
/// ```
/// # #![feature(alloc)]
/// use std::rc::Rc;
///
/// {
/// let five = Rc::new(5);
///
/// // stuff
///
/// drop(five); // explicit drop
/// }
/// {
/// let five = Rc::new(5);
///
/// // stuff
///
/// } // implicit drop
/// ```
fn drop(&mut self) {
unsafe {
let ptr = *self._ptr;
if !(*(&ptr as *const _ as *const *const ())).is_null() {
self.dec_strong();
if self.strong() == 0 {
// destroy the contained object
drop_in_place(&mut (*ptr).value);
// remove the implicit "strong weak" pointer now that we've
// destroyed the contents.
self.dec_weak();
if self.weak() == 0 {
deallocate(ptr as *mut u8,
size_of_val(&*ptr),
min_align_of_val(&*ptr))
}
}
}
}
}
}
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Clone for Rc<T> {
@ -449,6 +590,31 @@ impl<T> Clone for Rc<T> {
Rc { _ptr: self._ptr }
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Clone for Rc<T> {
/// Makes a clone of the `Rc<T>`.
///
/// When you clone an `Rc<T>`, it will create another pointer to the data and
/// increase the strong reference counter.
///
/// # Examples
///
/// ```
/// # #![feature(alloc)]
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
///
/// five.clone();
/// ```
#[inline]
fn clone(&self) -> Rc<T> {
self.inc_strong();
Rc { _ptr: self._ptr }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Rc<T> {
@ -610,27 +776,50 @@ impl<T: Ord> Ord for Rc<T> {
fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
}
// FIXME (#18248) Make `T` `Sized?`
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for Rc<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized+Hash> Hash for Rc<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display> fmt::Display for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized+fmt::Display> fmt::Display for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug> fmt::Debug for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized+fmt::Debug> fmt::Debug for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Pointer for Rc<T> {
@ -645,6 +834,7 @@ impl<T> fmt::Pointer for Rc<T> {
/// dropped.
///
/// See the [module level documentation](./index.html) for more.
#[cfg(stage0)]
#[unsafe_no_drop_flag]
#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module.")]
@ -653,12 +843,28 @@ pub struct Weak<T> {
// field accesses of the contained type via Deref
_ptr: NonZero<*mut RcBox<T>>,
}
#[cfg(not(stage0))]
#[unsafe_no_drop_flag]
#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module.")]
pub struct Weak<T: ?Sized> {
// FIXME #12808: strange names to try to avoid interfering with
// field accesses of the contained type via Deref
_ptr: NonZero<*mut RcBox<T>>,
}
#[cfg(stage0)]
impl<T> !marker::Send for Weak<T> {}
#[cfg(not(stage0))]
impl<T: ?Sized> !marker::Send for Weak<T> {}
#[cfg(stage0)]
impl<T> !marker::Sync for Weak<T> {}
#[cfg(not(stage0))]
impl<T: ?Sized> !marker::Sync for Weak<T> {}
#[cfg(stage0)]
#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module.")]
impl<T> Weak<T> {
@ -691,7 +897,42 @@ impl<T> Weak<T> {
}
}
}
#[cfg(not(stage0))]
#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module.")]
impl<T: ?Sized> Weak<T> {
/// Upgrades a weak reference to a strong reference.
///
/// Upgrades the `Weak<T>` reference to an `Rc<T>`, if possible.
///
/// Returns `None` if there were no strong references and the data was
/// destroyed.
///
/// # Examples
///
/// ```
/// # #![feature(alloc)]
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
///
/// let weak_five = five.downgrade();
///
/// let strong_five: Option<Rc<_>> = weak_five.upgrade();
/// ```
pub fn upgrade(&self) -> Option<Rc<T>> {
if self.strong() == 0 {
None
} else {
self.inc_strong();
Some(Rc { _ptr: self._ptr })
}
}
}
#[cfg(stage0)] // SNAP c64d671
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Weak<T> {
/// Drops the `Weak<T>`.
@ -736,6 +977,53 @@ impl<T> Drop for Weak<T> {
}
}
#[cfg(not(stage0))] // SNAP c64d671
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for Weak<T> {
/// Drops the `Weak<T>`.
///
/// This will decrement the weak reference count.
///
/// # Examples
///
/// ```
/// # #![feature(alloc)]
/// use std::rc::Rc;
///
/// {
/// let five = Rc::new(5);
/// let weak_five = five.downgrade();
///
/// // stuff
///
/// drop(weak_five); // explicit drop
/// }
/// {
/// let five = Rc::new(5);
/// let weak_five = five.downgrade();
///
/// // stuff
///
/// } // implicit drop
/// ```
fn drop(&mut self) {
unsafe {
let ptr = *self._ptr;
if !(*(&ptr as *const _ as *const *const ())).is_null() {
self.dec_weak();
// the weak count starts at 1, and will only go to zero if all
// the strong pointers have disappeared.
if self.weak() == 0 {
deallocate(ptr as *mut u8, size_of_val(&*ptr),
min_align_of_val(&*ptr))
}
}
}
}
}
#[cfg(stage0)]
#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module.")]
impl<T> Clone for Weak<T> {
@ -760,14 +1048,48 @@ impl<T> Clone for Weak<T> {
Weak { _ptr: self._ptr }
}
}
#[cfg(not(stage0))]
#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module.")]
impl<T: ?Sized> Clone for Weak<T> {
/// Makes a clone of the `Weak<T>`.
///
/// This increases the weak reference count.
///
/// # Examples
///
/// ```
/// # #![feature(alloc)]
/// use std::rc::Rc;
///
/// let weak_five = Rc::new(5).downgrade();
///
/// weak_five.clone();
/// ```
#[inline]
fn clone(&self) -> Weak<T> {
self.inc_weak();
Weak { _ptr: self._ptr }
}
}
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(Weak)")
}
}
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized+fmt::Debug> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(Weak)")
}
}
#[cfg(stage0)]
#[doc(hidden)]
trait RcBoxPtr<T> {
fn inner(&self) -> &RcBox<T>;
@ -790,7 +1112,31 @@ trait RcBoxPtr<T> {
#[inline]
fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); }
}
#[cfg(not(stage0))]
#[doc(hidden)]
trait RcBoxPtr<T: ?Sized> {
fn inner(&self) -> &RcBox<T>;
#[inline]
fn strong(&self) -> usize { self.inner().strong.get() }
#[inline]
fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); }
#[inline]
fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
#[inline]
fn weak(&self) -> usize { self.inner().weak.get() }
#[inline]
fn inc_weak(&self) { self.inner().weak.set(self.weak() + 1); }
#[inline]
fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); }
}
#[cfg(stage0)]
impl<T> RcBoxPtr<T> for Rc<T> {
#[inline(always)]
fn inner(&self) -> &RcBox<T> {
@ -799,12 +1145,27 @@ impl<T> RcBoxPtr<T> for Rc<T> {
// 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());
assume(!(*(&self._ptr as *const _ as *const *const ())).is_null());
&(**self._ptr)
}
}
}
#[cfg(not(stage0))]
impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
#[inline(always)]
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 as *const _ as *const *const ())).is_null());
&(**self._ptr)
}
}
}
#[cfg(stage0)]
impl<T> RcBoxPtr<T> for Weak<T> {
#[inline(always)]
fn inner(&self) -> &RcBox<T> {
@ -813,7 +1174,21 @@ impl<T> RcBoxPtr<T> for Weak<T> {
// 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());
assume(!(*(&self._ptr as *const _ as *const *const ())).is_null());
&(**self._ptr)
}
}
}
#[cfg(not(stage0))]
impl<T: ?Sized> RcBoxPtr<T> for Weak<T> {
#[inline(always)]
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 as *const _ as *const *const ())).is_null());
&(**self._ptr)
}
}