Skip to content

Commit 6e2efe3

Browse files
committed
refactor NonZero, Shared, and Unique APIs
Major difference is that I removed Deref impls, as apparently LLVM has trouble maintaining metadata with a `&ptr -> &ptr` API. This was cited as a blocker for ever stabilizing this API. It wasn't that ergonomic anyway. * Added `get` to NonZero to replace Deref impl * Added `as_ptr` to Shared/Unique to replace Deref impl * Added Unique's `as_ref` and `as_mut` conveniences to Shared * Added `::empty()` convenience constructor for Unique/Shared * Deprecated `as_mut_ptr` on Shared in favour of `as_ptr` * Improved documentation of types Note that Shared now only refers to *mut, and not *const
1 parent ed1f26d commit 6e2efe3

File tree

2 files changed

+131
-53
lines changed

2 files changed

+131
-53
lines changed

src/libcore/nonzero.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
reason = "needs an RFC to flesh out the design",
1414
issue = "27730")]
1515

16-
use ops::{CoerceUnsized, Deref};
16+
use ops::CoerceUnsized;
1717

1818
/// Unsafe trait to indicate what types are usable with the NonZero struct
1919
pub unsafe trait Zeroable {}
@@ -46,15 +46,10 @@ impl<T: Zeroable> NonZero<T> {
4646
pub const unsafe fn new(inner: T) -> NonZero<T> {
4747
NonZero(inner)
4848
}
49-
}
50-
51-
impl<T: Zeroable> Deref for NonZero<T> {
52-
type Target = T;
5349

54-
#[inline]
55-
fn deref(&self) -> &T {
56-
let NonZero(ref inner) = *self;
57-
inner
50+
/// Gets the inner value.
51+
pub fn get(self) -> T {
52+
self.0
5853
}
5954
}
6055

src/libcore/ptr.rs

Lines changed: 127 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#![stable(feature = "rust1", since = "1.0.0")]
1818

1919
use intrinsics;
20-
use ops::{CoerceUnsized, Deref};
20+
use ops::CoerceUnsized;
2121
use fmt;
2222
use hash;
2323
use marker::{PhantomData, Unsize};
@@ -957,13 +957,25 @@ impl<T: ?Sized> PartialOrd for *mut T {
957957
}
958958

959959
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
960-
/// of this wrapper owns the referent. This in turn implies that the
961-
/// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a raw
962-
/// `*mut T` (which conveys no particular ownership semantics). It
963-
/// also implies that the referent of the pointer should not be
964-
/// modified without a unique path to the `Unique` reference. Useful
965-
/// for building abstractions like `Vec<T>` or `Box<T>`, which
966-
/// internally use raw pointers to manage the memory that they own.
960+
/// of this wrapper owns the referent. Useful for building abstractions like
961+
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
962+
///
963+
/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
964+
/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
965+
/// the kind of strong aliasing guarantees an instance of `T` can expect:
966+
/// the referent of the pointer should not be modified without a unique path to
967+
/// its owning Unique.
968+
///
969+
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
970+
/// consider using `Shared`, which has weaker semantics.
971+
///
972+
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
973+
/// is never dereferenced. This is so that enums may use this forbidden value
974+
/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
975+
/// However the pointer may still dangle if it isn't dereferenced.
976+
///
977+
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
978+
/// for any type which upholds Unique's aliasing requirements.
967979
#[allow(missing_debug_implementations)]
968980
#[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
969981
issue = "27730")]
@@ -991,6 +1003,20 @@ unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
9911003
#[unstable(feature = "unique", issue = "27730")]
9921004
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
9931005

1006+
#[unstable(feature = "unique", issue = "27730")]
1007+
impl<T: Sized> Unique<T> {
1008+
/// Creates a new `Shared` that is dangling, but well-aligned.
1009+
///
1010+
/// This is useful for initializing types which lazily allocate, like
1011+
/// `Vec::new` does.
1012+
pub fn empty() -> Self {
1013+
unsafe {
1014+
let ptr = mem::align_of::<T>() as *mut T;
1015+
Unique::new(ptr)
1016+
}
1017+
}
1018+
}
1019+
9941020
#[unstable(feature = "unique", issue = "27730")]
9951021
impl<T: ?Sized> Unique<T> {
9961022
/// Creates a new `Unique`.
@@ -1002,41 +1028,72 @@ impl<T: ?Sized> Unique<T> {
10021028
Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
10031029
}
10041030

1031+
/// Acquires the underlying `*mut` pointer.
1032+
pub fn as_ptr(self) -> *mut T {
1033+
self.pointer.get() as *mut T
1034+
}
1035+
10051036
/// Dereferences the content.
1006-
pub unsafe fn get(&self) -> &T {
1007-
&**self.pointer
1037+
///
1038+
/// The resulting lifetime is bound to self so this behaves "as if"
1039+
/// it were actually an instance of T that is getting borrowed. If a longer
1040+
/// (unbound) lifetime is needed, use `&*my_ptr.ptr()`.
1041+
pub unsafe fn as_ref(&self) -> &T {
1042+
&*self.as_ptr()
10081043
}
10091044

10101045
/// Mutably dereferences the content.
1011-
pub unsafe fn get_mut(&mut self) -> &mut T {
1012-
&mut ***self
1046+
///
1047+
/// The resulting lifetime is bound to self so this behaves "as if"
1048+
/// it were actually an instance of T that is getting borrowed. If a longer
1049+
/// (unbound) lifetime is needed, use `&mut *my_ptr.ptr()`.
1050+
pub unsafe fn as_mut(&mut self) -> &mut T {
1051+
&mut *self.as_ptr()
10131052
}
10141053
}
10151054

1016-
#[unstable(feature = "unique", issue = "27730")]
1017-
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
1018-
1019-
#[unstable(feature = "unique", issue= "27730")]
1020-
impl<T:?Sized> Deref for Unique<T> {
1021-
type Target = *mut T;
1022-
1023-
#[inline]
1024-
fn deref(&self) -> &*mut T {
1025-
unsafe { mem::transmute(&*self.pointer) }
1055+
#[unstable(feature = "shared", issue = "27730")]
1056+
impl<T: ?Sized> Clone for Unique<T> {
1057+
fn clone(&self) -> Self {
1058+
*self
10261059
}
10271060
}
10281061

1062+
#[unstable(feature = "shared", issue = "27730")]
1063+
impl<T: ?Sized> Copy for Unique<T> { }
1064+
1065+
#[unstable(feature = "unique", issue = "27730")]
1066+
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
1067+
10291068
#[unstable(feature = "unique", issue = "27730")]
1030-
impl<T> fmt::Pointer for Unique<T> {
1069+
impl<T: ?Sized> fmt::Pointer for Unique<T> {
10311070
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1032-
fmt::Pointer::fmt(&*self.pointer, f)
1071+
fmt::Pointer::fmt(&self.as_ptr(), f)
10331072
}
10341073
}
10351074

1036-
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
1075+
/// A wrapper around a raw `*mut T` that indicates that the possessor
10371076
/// of this wrapper has shared ownership of the referent. Useful for
1038-
/// building abstractions like `Rc<T>` or `Arc<T>`, which internally
1039-
/// use raw pointers to manage the memory that they own.
1077+
/// building abstractions like `Rc<T>`, `Arc<T>`, or doubly-linked lists, which
1078+
/// internally use aliased raw pointers to manage the memory that they own.
1079+
///
1080+
/// This is similar to `Unique`, except that it doesn't make any aliasing
1081+
/// guarantees, and doesn't derive Send and Sync. Note that unlike `&T`,
1082+
/// Shared has no special mutability requirements. Shared may mutate data
1083+
/// aliased by other Shared pointers. More precise rules require Rust to
1084+
/// develop an actual aliasing model.
1085+
///
1086+
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
1087+
/// is never dereferenced. This is so that enums may use this forbidden value
1088+
/// as a discriminant -- `Option<Shared<T>>` has the same size as `Shared<T>`.
1089+
/// However the pointer may still dangle if it isn't dereferenced.
1090+
///
1091+
/// Unlike `*mut T`, `Shared<T>` is covariant over `T`. If this is incorrect
1092+
/// for your use case, you should include some PhantomData in your type to
1093+
/// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
1094+
/// Usually this won't be necessary; covariance is correct for Rc, Arc, and LinkedList
1095+
/// because they provide a public API that follows the normal shared XOR mutable
1096+
/// rules of Rust.
10401097
#[allow(missing_debug_implementations)]
10411098
#[unstable(feature = "shared", reason = "needs an RFC to flesh out design",
10421099
issue = "27730")]
@@ -1060,23 +1117,59 @@ impl<T: ?Sized> !Send for Shared<T> { }
10601117
#[unstable(feature = "shared", issue = "27730")]
10611118
impl<T: ?Sized> !Sync for Shared<T> { }
10621119

1120+
#[unstable(feature = "shared", issue = "27730")]
1121+
impl<T: Sized> Shared<T> {
1122+
/// Creates a new `Shared` that is dangling, but well-aligned.
1123+
///
1124+
/// This is useful for initializing types which lazily allocate, like
1125+
/// `Vec::new` does.
1126+
pub fn empty() -> Self {
1127+
unsafe {
1128+
let ptr = mem::align_of::<T>() as *mut T;
1129+
Shared::new(ptr)
1130+
}
1131+
}
1132+
}
1133+
10631134
#[unstable(feature = "shared", issue = "27730")]
10641135
impl<T: ?Sized> Shared<T> {
10651136
/// Creates a new `Shared`.
10661137
///
10671138
/// # Safety
10681139
///
10691140
/// `ptr` must be non-null.
1070-
pub unsafe fn new(ptr: *const T) -> Self {
1141+
pub unsafe fn new(ptr: *mut T) -> Self {
10711142
Shared { pointer: NonZero::new(ptr), _marker: PhantomData }
10721143
}
1073-
}
10741144

1075-
#[unstable(feature = "shared", issue = "27730")]
1076-
impl<T: ?Sized> Shared<T> {
1145+
/// Acquires the underlying `*mut` pointer.
1146+
pub fn as_ptr(self) -> *mut T {
1147+
self.pointer.get() as *mut T
1148+
}
1149+
1150+
/// Dereferences the content.
1151+
///
1152+
/// The resulting lifetime is bound to self so this behaves "as if"
1153+
/// it were actually an instance of T that is getting borrowed. If a longer
1154+
/// (unbound) lifetime is needed, use `&*my_ptr.ptr()`.
1155+
pub unsafe fn as_ref(&self) -> &T {
1156+
&*self.as_ptr()
1157+
}
1158+
1159+
/// Mutably dereferences the content.
1160+
///
1161+
/// The resulting lifetime is bound to self so this behaves "as if"
1162+
/// it were actually an instance of T that is getting borrowed. If a longer
1163+
/// (unbound) lifetime is needed, use `&mut *my_ptr.ptr_mut()`.
1164+
pub unsafe fn as_mut(&mut self) -> &mut T {
1165+
&mut *self.as_ptr()
1166+
}
1167+
10771168
/// Acquires the underlying pointer as a `*mut` pointer.
1169+
#[rustc_deprecated(since = "1.19", reason = "renamed to `as_ptr` for ergonomics/consistency")]
1170+
#[unstable(feature = "shared", issue = "27730")]
10781171
pub unsafe fn as_mut_ptr(&self) -> *mut T {
1079-
**self as _
1172+
self.as_ptr()
10801173
}
10811174
}
10821175

@@ -1094,18 +1187,8 @@ impl<T: ?Sized> Copy for Shared<T> { }
10941187
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsize<U> { }
10951188

10961189
#[unstable(feature = "shared", issue = "27730")]
1097-
impl<T: ?Sized> Deref for Shared<T> {
1098-
type Target = *const T;
1099-
1100-
#[inline]
1101-
fn deref(&self) -> &*const T {
1102-
unsafe { mem::transmute(&*self.pointer) }
1103-
}
1104-
}
1105-
1106-
#[unstable(feature = "shared", issue = "27730")]
1107-
impl<T> fmt::Pointer for Shared<T> {
1190+
impl<T: ?Sized> fmt::Pointer for Shared<T> {
11081191
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1109-
fmt::Pointer::fmt(&*self.pointer, f)
1192+
fmt::Pointer::fmt(&self.as_ptr(), f)
11101193
}
11111194
}

0 commit comments

Comments
 (0)