diff options
| author | Andrew Paseltiner <apaseltiner@gmail.com> | 2015-10-16 11:54:05 -0400 |
|---|---|---|
| committer | Andrew Paseltiner <apaseltiner@gmail.com> | 2015-10-16 18:35:31 -0400 |
| commit | d6bd8d8491e89277edbfc9a4e0f8953847abbdd6 (patch) | |
| tree | 41bc1358ed0b4712768d308ea3e0df04e25eddf5 /src/libcore | |
| parent | 05cfd72ed1934c92af08dbcb66fd1af6b1298721 (diff) | |
| download | rust-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/libcore')
| -rw-r--r-- | src/libcore/ptr.rs | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 960240d7f5f..8adbaf56f14 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -18,11 +18,11 @@ use clone::Clone; use intrinsics; -use ops::Deref; +use ops::{CoerceUnsized, Deref}; use fmt; use hash; use option::Option::{self, Some, None}; -use marker::{PhantomData, Send, Sized, Sync}; +use marker::{Copy, PhantomData, Send, Sized, Sync, Unsize}; use mem; use nonzero::NonZero; @@ -532,3 +532,68 @@ impl<T> fmt::Pointer for Unique<T> { fmt::Pointer::fmt(&*self.pointer, f) } } + +/// A wrapper around a raw `*mut T` that indicates that the possessor +/// of this wrapper has shared ownership of the referent. Useful for +/// building abstractions like `Rc<T>` or `Arc<T>`, which internally +/// use raw pointers to manage the memory that they own. +#[unstable(feature = "shared", reason = "needs an RFC to flesh out design", + issue = "0")] +pub struct Shared<T: ?Sized> { + pointer: NonZero<*const T>, + // NOTE: this marker has no consequences for variance, but is necessary + // for dropck to understand that we logically own a `T`. + // + // For details, see: + // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data + _marker: PhantomData<T>, +} + +/// `Shared` pointers are not `Send` because the data they reference may be aliased. +// NB: This impl is unnecessary, but should provide better error messages. +#[unstable(feature = "shared", issue = "0")] +impl<T: ?Sized> !Send for Shared<T> { } + +/// `Shared` pointers are not `Sync` because the data they reference may be aliased. +// NB: This impl is unnecessary, but should provide better error messages. +#[unstable(feature = "shared", issue = "0")] +impl<T: ?Sized> !Sync for Shared<T> { } + +#[unstable(feature = "shared", issue = "0")] +impl<T: ?Sized> Shared<T> { + /// Creates a new `Shared`. + pub unsafe fn new(ptr: *mut T) -> Self { + Shared { pointer: NonZero::new(ptr), _marker: PhantomData } + } +} + +#[unstable(feature = "shared", issue = "0")] +impl<T: ?Sized> Clone for Shared<T> { + fn clone(&self) -> Self { + *self + } +} + +#[unstable(feature = "shared", issue = "0")] +impl<T: ?Sized> Copy for Shared<T> { } + +#[cfg(not(stage0))] // remove cfg after new snapshot +#[unstable(feature = "shared", issue = "0")] +impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsize<U> { } + +#[unstable(feature = "shared", issue = "0")] +impl<T: ?Sized> Deref for Shared<T> { + type Target = *mut T; + + #[inline] + fn deref(&self) -> &*mut T { + unsafe { mem::transmute(&*self.pointer) } + } +} + +#[unstable(feature = "shared", issue = "0")] +impl<T> fmt::Pointer for Shared<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Pointer::fmt(&*self.pointer, f) + } +} |
