diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index fc0a3c0fd881a..844b70835936f 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -26,7 +26,7 @@ use core::mem::{self, align_of_val, size_of_val, uninitialized}; use core::ops::Deref; use core::ops::CoerceUnsized; use core::ptr::{self, Shared}; -use core::marker::Unsize; +use core::marker::{Unsize, PhantomData}; use core::hash::{Hash, Hasher}; use core::{isize, usize}; use core::convert::From; @@ -198,6 +198,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; #[stable(feature = "rust1", since = "1.0.0")] pub struct Arc { ptr: Shared>, + phantom: PhantomData, } #[stable(feature = "rust1", since = "1.0.0")] @@ -285,7 +286,7 @@ impl Arc { weak: atomic::AtomicUsize::new(1), data, }; - Arc { ptr: Shared::from(Box::into_unique(x)) } + Arc { ptr: Shared::from(Box::into_unique(x)), phantom: PhantomData } } /// Returns the contained value, if the `Arc` has exactly one strong reference. @@ -397,6 +398,7 @@ impl Arc { Arc { ptr: Shared::new_unchecked(arc_ptr), + phantom: PhantomData, } } @@ -580,7 +582,7 @@ impl Arc { // Free the allocation without dropping its contents box_free(bptr); - Arc { ptr: Shared::new_unchecked(ptr) } + Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData } } } } @@ -607,7 +609,7 @@ impl Arc<[T]> { &mut (*ptr).data as *mut [T] as *mut T, v.len()); - Arc { ptr: Shared::new_unchecked(ptr) } + Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData } } } @@ -667,7 +669,7 @@ impl ArcFromSlice for Arc<[T]> { // All clear. Forget the guard so it doesn't free the new ArcInner. mem::forget(guard); - Arc { ptr: Shared::new_unchecked(ptr) } + Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData } } } } @@ -725,7 +727,7 @@ impl Clone for Arc { } } - Arc { ptr: self.ptr } + Arc { ptr: self.ptr, phantom: PhantomData } } } @@ -1052,7 +1054,7 @@ impl Weak { // Relaxed is valid for the same reason it is on Arc's Clone impl match inner.strong.compare_exchange_weak(n, n + 1, Relaxed, Relaxed) { - Ok(_) => return Some(Arc { ptr: self.ptr }), + Ok(_) => return Some(Arc { ptr: self.ptr, phantom: PhantomData }), Err(old) => n = old, } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 58f08fd8bc11d..358b5934b9231 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -252,7 +252,7 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; use core::marker; -use core::marker::Unsize; +use core::marker::{Unsize, PhantomData}; use core::mem::{self, align_of_val, forget, size_of_val, uninitialized}; use core::ops::Deref; use core::ops::CoerceUnsized; @@ -283,6 +283,7 @@ struct RcBox { #[stable(feature = "rust1", since = "1.0.0")] pub struct Rc { ptr: Shared>, + phantom: PhantomData, } #[stable(feature = "rust1", since = "1.0.0")] @@ -315,6 +316,7 @@ impl Rc { weak: Cell::new(1), value, })), + phantom: PhantomData, } } @@ -427,6 +429,7 @@ impl Rc { Rc { ptr: Shared::new_unchecked(rc_ptr), + phantom: PhantomData, } } @@ -647,6 +650,7 @@ impl Rc { forget(self); Ok(Rc { ptr: Shared::new_unchecked(raw as *const RcBox as *mut _), + phantom: PhantomData, }) } } else { @@ -691,7 +695,7 @@ impl Rc { // Free the allocation without dropping its contents box_free(bptr); - Rc { ptr: Shared::new_unchecked(ptr) } + Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData } } } } @@ -718,7 +722,7 @@ impl Rc<[T]> { &mut (*ptr).value as *mut [T] as *mut T, v.len()); - Rc { ptr: Shared::new_unchecked(ptr) } + Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData } } } @@ -777,7 +781,7 @@ impl RcFromSlice for Rc<[T]> { // All clear. Forget the guard so it doesn't free the new RcBox. forget(guard); - Rc { ptr: Shared::new_unchecked(ptr) } + Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData } } } } @@ -868,7 +872,7 @@ impl Clone for Rc { #[inline] fn clone(&self) -> Rc { self.inc_strong(); - Rc { ptr: self.ptr } + Rc { ptr: self.ptr, phantom: PhantomData } } } @@ -1228,7 +1232,7 @@ impl Weak { None } else { self.inc_strong(); - Some(Rc { ptr: self.ptr }) + Some(Rc { ptr: self.ptr, phantom: PhantomData }) } } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 9c7c865771606..67ccb5cab6def 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -71,6 +71,7 @@ use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; use core::iter::{FromIterator, FusedIterator, TrustedLen}; +use core::marker::PhantomData; use core::mem; #[cfg(not(test))] use core::num::Float; @@ -1743,6 +1744,7 @@ impl IntoIterator for Vec { mem::forget(self); IntoIter { buf: Shared::new_unchecked(begin), + phantom: PhantomData, cap, ptr: begin, end, @@ -2264,6 +2266,7 @@ impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { buf: Shared, + phantom: PhantomData, cap: usize, ptr: *const T, end: *const T, diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 20f054f5a77f2..39cf2ec4c21d0 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2450,16 +2450,11 @@ impl<'a, T: ?Sized> From<&'a T> for Unique { } } -/// 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`, `Arc`, or doubly-linked lists, which -/// internally use aliased raw pointers to manage the memory that they own. +/// `*mut T` but non-zero and covariant. /// -/// This is similar to `Unique`, except that it doesn't make any aliasing -/// guarantees, and doesn't derive Send and Sync. Note that unlike `&T`, -/// Shared has no special mutability requirements. Shared may mutate data -/// aliased by other Shared pointers. More precise rules require Rust to -/// develop an actual aliasing model. +/// This is often the correct thing to use when building data structures using +/// raw pointers, but is ultimately more dangerous to use because of its additional +/// properties. If you're not sure if you should use `Shared`, just use `*mut T`! /// /// Unlike `*mut T`, the pointer must always be non-null, even if the pointer /// is never dereferenced. This is so that enums may use this forbidden value @@ -2469,20 +2464,14 @@ impl<'a, T: ?Sized> From<&'a T> for Unique { /// Unlike `*mut T`, `Shared` is covariant over `T`. If this is incorrect /// for your use case, you should include some PhantomData in your type to /// provide invariance, such as `PhantomData>` or `PhantomData<&'a mut T>`. -/// Usually this won't be necessary; covariance is correct for Rc, Arc, and LinkedList -/// because they provide a public API that follows the normal shared XOR mutable -/// rules of Rust. +/// Usually this won't be necessary; covariance is correct for most safe abstractions, +/// such as Box, Rc, Arc, Vec, and LinkedList. This is the case because they +/// provide a public API that follows the normal shared XOR mutable rules of Rust. #[allow(missing_debug_implementations)] #[unstable(feature = "shared", reason = "needs an RFC to flesh out design", issue = "27730")] pub struct Shared { 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, } /// `Shared` pointers are not `Send` because the data they reference may be aliased. @@ -2518,12 +2507,12 @@ impl Shared { /// `ptr` must be non-null. #[unstable(feature = "shared", issue = "27730")] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { - Shared { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData } + Shared { pointer: NonZero::new_unchecked(ptr) } } /// Creates a new `Shared` if `ptr` is non-null. pub fn new(ptr: *mut T) -> Option { - NonZero::new(ptr as *const T).map(|nz| Shared { pointer: nz, _marker: PhantomData }) + NonZero::new(ptr as *const T).map(|nz| Shared { pointer: nz }) } /// Acquires the underlying `*mut` pointer. @@ -2580,20 +2569,20 @@ impl fmt::Pointer for Shared { #[unstable(feature = "shared", issue = "27730")] impl From> for Shared { fn from(unique: Unique) -> Self { - Shared { pointer: unique.pointer, _marker: PhantomData } + Shared { pointer: unique.pointer } } } #[unstable(feature = "shared", issue = "27730")] impl<'a, T: ?Sized> From<&'a mut T> for Shared { fn from(reference: &'a mut T) -> Self { - Shared { pointer: NonZero::from(reference), _marker: PhantomData } + Shared { pointer: NonZero::from(reference) } } } #[unstable(feature = "shared", issue = "27730")] impl<'a, T: ?Sized> From<&'a T> for Shared { fn from(reference: &'a T) -> Self { - Shared { pointer: NonZero::from(reference), _marker: PhantomData } + Shared { pointer: NonZero::from(reference) } } }