Skip to content

Commit 801bc48

Browse files
committed
Rewrite Unique<T> so that it is covariant in T, implies NonZero and ownership,
and also follows the API of `NonZero` a bit more closely. More to do here I think (including perhaps a new name).
1 parent 8c841f2 commit 801bc48

File tree

3 files changed

+38
-27
lines changed

3 files changed

+38
-27
lines changed

src/libcore/nonzero.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@
1010

1111
//! Exposes the NonZero lang item which provides optimization hints.
1212
13+
use marker::{Sized, MarkerTrait};
1314
use ops::Deref;
14-
use ptr::Unique;
1515

1616
/// Unsafe trait to indicate what types are usable with the NonZero struct
17-
pub unsafe trait Zeroable {}
17+
pub unsafe trait Zeroable : MarkerTrait {}
1818

19-
unsafe impl<T> Zeroable for *const T {}
20-
unsafe impl<T> Zeroable for *mut T {}
21-
unsafe impl<T> Zeroable for Unique<T> { }
19+
unsafe impl<T:?Sized> Zeroable for *const T {}
20+
unsafe impl<T:?Sized> Zeroable for *mut T {}
2221
unsafe impl Zeroable for isize {}
2322
unsafe impl Zeroable for usize {}
2423
unsafe impl Zeroable for i8 {}

src/libcore/ptr.rs

+32-20
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,10 @@
9191
use mem;
9292
use clone::Clone;
9393
use intrinsics;
94+
use ops::Deref;
9495
use option::Option::{self, Some, None};
95-
use marker::{self, Send, Sized, Sync};
96+
use marker::{PhantomData, Send, Sized, Sync};
97+
use nonzero::NonZero;
9698

9799
use cmp::{PartialEq, Eq, Ord, PartialOrd};
98100
use cmp::Ordering::{self, Less, Equal, Greater};
@@ -517,15 +519,16 @@ impl<T> PartialOrd for *mut T {
517519

518520
/// A wrapper around a raw `*mut T` that indicates that the possessor
519521
/// of this wrapper owns the referent. This in turn implies that the
520-
/// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a
521-
/// raw `*mut T` (which conveys no particular ownership semantics).
522-
/// Useful for building abstractions like `Vec<T>` or `Box<T>`, which
522+
/// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a raw
523+
/// `*mut T` (which conveys no particular ownership semantics). It
524+
/// also implies that the referent of the pointer should not be
525+
/// modified without a unique path to the `Unique` reference. Useful
526+
/// for building abstractions like `Vec<T>` or `Box<T>`, which
523527
/// internally use raw pointers to manage the memory that they own.
524528
#[unstable(feature = "core", reason = "recently added to this module")]
525-
pub struct Unique<T: ?Sized> {
526-
/// The wrapped `*mut T`.
527-
pub ptr: *mut T,
528-
_own: marker::PhantomData<T>,
529+
pub struct Unique<T:?Sized> {
530+
pointer: NonZero<*const T>,
531+
_marker: PhantomData<T>,
529532
}
530533

531534
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
@@ -542,25 +545,34 @@ unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
542545
#[unstable(feature = "core", reason = "recently added to this module")]
543546
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
544547

545-
impl<T> Unique<T> {
546-
/// Returns a null Unique.
548+
impl<T:?Sized> Unique<T> {
549+
/// Create a new `Unique`.
547550
#[unstable(feature = "core",
548551
reason = "recently added to this module")]
549-
pub fn null() -> Unique<T> {
550-
Unique(null_mut())
552+
pub unsafe fn new(ptr: *mut T) -> Unique<T> {
553+
Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
551554
}
552555

553-
/// Return an (unsafe) pointer into the memory owned by `self`.
556+
/// Dereference the content.
554557
#[unstable(feature = "core",
555558
reason = "recently added to this module")]
556-
pub unsafe fn offset(self, offset: isize) -> *mut T {
557-
self.ptr.offset(offset)
559+
pub unsafe fn get(&self) -> &T {
560+
&**self.pointer
561+
}
562+
563+
/// Mutably dereference the content.
564+
#[unstable(feature = "core",
565+
reason = "recently added to this module")]
566+
pub unsafe fn get_mut(&mut self) -> &mut T {
567+
&mut ***self
558568
}
559569
}
560570

561-
/// Creates a `Unique` wrapped around `ptr`, taking ownership of the
562-
/// data referenced by `ptr`.
563-
#[allow(non_snake_case)]
564-
pub fn Unique<T: ?Sized>(ptr: *mut T) -> Unique<T> {
565-
Unique { ptr: ptr, _own: marker::PhantomData }
571+
impl<T:?Sized> Deref for Unique<T> {
572+
type Target = *mut T;
573+
574+
#[inline]
575+
fn deref<'a>(&'a self) -> &'a *mut T {
576+
unsafe { mem::transmute(&*self.pointer) }
577+
}
566578
}

src/libcoretest/ptr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ fn test_set_memory() {
171171
#[test]
172172
fn test_unsized_unique() {
173173
let xs: &mut [_] = &mut [1, 2, 3];
174-
let ptr = Unique(xs as *mut [_]);
175-
let ys = unsafe { &mut *ptr.ptr };
174+
let ptr = unsafe { Unique::new(xs as *mut [_]) };
175+
let ys = unsafe { &mut **ptr };
176176
let zs: &mut [_] = &mut [1, 2, 3];
177177
assert!(ys == zs);
178178
}

0 commit comments

Comments
 (0)