about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorAndrew Paseltiner <apaseltiner@gmail.com>2015-10-16 11:54:05 -0400
committerAndrew Paseltiner <apaseltiner@gmail.com>2015-10-16 18:35:31 -0400
commitd6bd8d8491e89277edbfc9a4e0f8953847abbdd6 (patch)
tree41bc1358ed0b4712768d308ea3e0df04e25eddf5 /src/liballoc
parent05cfd72ed1934c92af08dbcb66fd1af6b1298721 (diff)
downloadrust-d6bd8d8491e89277edbfc9a4e0f8953847abbdd6.tar.gz
rust-d6bd8d8491e89277edbfc9a4e0f8953847abbdd6.zip
Add `Shared` pointer and have `{Arc, Rc}` use it
This change has two consequences:

1. It makes `Arc<T>` and `Rc<T>` covariant in `T`.

2. It causes the compiler to reject code that was unsound with respect
to dropck. See compile-fail/issue-29106.rs for an example of code that
no longer compiles. Because of this, this is a [breaking-change].

Fixes #29037.
Fixes #29106.
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/arc.rs11
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/rc.rs11
3 files changed, 13 insertions, 10 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index d8f10e6780f..33ca80ba372 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -79,9 +79,8 @@ use core::cmp::Ordering;
 use core::mem::{align_of_val, size_of_val};
 use core::intrinsics::{drop_in_place, abort};
 use core::mem;
-use core::nonzero::NonZero;
 use core::ops::{Deref, CoerceUnsized};
-use core::ptr;
+use core::ptr::{self, Shared};
 use core::marker::Unsize;
 use core::hash::{Hash, Hasher};
 use core::{usize, isize};
@@ -124,12 +123,13 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 pub struct Arc<T: ?Sized> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
-    _ptr: NonZero<*mut ArcInner<T>>,
+    _ptr: Shared<ArcInner<T>>,
 }
 
 unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> { }
 unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> { }
 
+#[cfg(not(stage0))] // remove cfg after new snapshot
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 
 /// A weak pointer to an `Arc`.
@@ -141,12 +141,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 pub struct Weak<T: ?Sized> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
-    _ptr: NonZero<*mut ArcInner<T>>,
+    _ptr: Shared<ArcInner<T>>,
 }
 
 unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> { }
 unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> { }
 
+#[cfg(not(stage0))] // remove cfg after new snapshot
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -190,7 +191,7 @@ impl<T> Arc<T> {
             weak: atomic::AtomicUsize::new(1),
             data: data,
         };
-        Arc { _ptr: unsafe { NonZero::new(Box::into_raw(x)) } }
+        Arc { _ptr: unsafe { Shared::new(Box::into_raw(x)) } }
     }
 
     /// Unwraps the contained value if the `Arc<T>` has only one strong reference.
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 8ecc78a231e..c78ebdf4340 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -90,6 +90,7 @@
 #![feature(placement_in_syntax)]
 #![feature(placement_new_protocol)]
 #![feature(raw)]
+#![feature(shared)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(unique)]
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 4753bb2379a..d695c0edd1d 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -163,9 +163,8 @@ use core::hash::{Hasher, Hash};
 use core::intrinsics::{assume, drop_in_place, abort};
 use core::marker::{self, Unsize};
 use core::mem::{self, align_of_val, size_of_val, forget};
-use core::nonzero::NonZero;
 use core::ops::{CoerceUnsized, Deref};
-use core::ptr;
+use core::ptr::{self, Shared};
 
 use heap::deallocate;
 
@@ -184,12 +183,13 @@ struct RcBox<T: ?Sized> {
 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>>,
+    _ptr: Shared<RcBox<T>>,
 }
 
 impl<T: ?Sized> !marker::Send for Rc<T> {}
 impl<T: ?Sized> !marker::Sync for Rc<T> {}
 
+#[cfg(not(stage0))] // remove cfg after new snapshot
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
 
 impl<T> Rc<T> {
@@ -210,7 +210,7 @@ impl<T> Rc<T> {
                 // pointers, which ensures that the weak destructor never frees
                 // the allocation while the strong destructor is running, even
                 // if the weak pointer is stored inside the strong one.
-                _ptr: NonZero::new(Box::into_raw(box RcBox {
+                _ptr: Shared::new(Box::into_raw(box RcBox {
                     strong: Cell::new(1),
                     weak: Cell::new(1),
                     value: value,
@@ -712,12 +712,13 @@ impl<T> fmt::Pointer for Rc<T> {
 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>>,
+    _ptr: Shared<RcBox<T>>,
 }
 
 impl<T: ?Sized> !marker::Send for Weak<T> {}
 impl<T: ?Sized> !marker::Sync for Weak<T> {}
 
+#[cfg(not(stage0))] // remove cfg after new snapshot
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
 impl<T: ?Sized> Weak<T> {