Skip to content

Commit

Permalink
Rollup merge of rust-lang#42959 - SimonSapin:nonzero-checked, r=sfackler
Browse files Browse the repository at this point in the history
Make the "main" constructors of NonZero/Shared/Unique return Option

Per discussion in rust-lang#27730 (comment).

This is a breaking change to unstable APIs.

The old behavior is still available under the name `new_unchecked`. Note that only that one can be `const fn`, since `if` is currently not allowed in constant contexts.

In the case of `NonZero` this requires adding a new `is_zero` method to the `Zeroable` trait. I mildly dislike this, but it’s not much worse than having a `Zeroable` trait in the first place. `Zeroable` and `NonZero` are both unstable, this can be reworked later.
  • Loading branch information
Mark-Simulacrum committed Jul 26, 2017
2 parents bad58f2 + 0d1864b commit b5b7266
Show file tree
Hide file tree
Showing 21 changed files with 219 additions and 87 deletions.
2 changes: 1 addition & 1 deletion src/doc/nomicon
6 changes: 3 additions & 3 deletions src/liballoc/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ pub unsafe trait Alloc {
{
let k = Layout::new::<T>();
if k.size() > 0 {
unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) }
unsafe { self.alloc(k).map(|p| Unique::new_unchecked(p as *mut T)) }
} else {
Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
}
Expand Down Expand Up @@ -963,7 +963,7 @@ pub unsafe trait Alloc {
unsafe {
self.alloc(layout.clone())
.map(|p| {
Unique::new(p as *mut T)
Unique::new_unchecked(p as *mut T)
})
}
}
Expand Down Expand Up @@ -1012,7 +1012,7 @@ pub unsafe trait Alloc {
match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
(Some(ref k_old), Some(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())
.map(|p|Unique::new(p as *mut T))
.map(|p|Unique::new_unchecked(p as *mut T))
}
_ => {
Err(AllocErr::invalid_input("invalid layout for realloc_array"))
Expand Down
6 changes: 3 additions & 3 deletions src/liballoc/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ impl<T> Arc<T> {
weak: atomic::AtomicUsize::new(1),
data: data,
};
Arc { ptr: unsafe { Shared::new(Box::into_raw(x)) } }
Arc { ptr: Shared::from(Box::into_unique(x)) }
}

/// Returns the contained value, if the `Arc` has exactly one strong reference.
Expand Down Expand Up @@ -382,7 +382,7 @@ impl<T> Arc<T> {
// `data` field from the pointer.
let ptr = (ptr as *const u8).offset(-offset_of!(ArcInner<T>, data));
Arc {
ptr: Shared::new(ptr as *mut u8 as *mut _),
ptr: Shared::new_unchecked(ptr as *mut u8 as *mut _),
}
}
}
Expand Down Expand Up @@ -842,7 +842,7 @@ impl<T> Weak<T> {
pub fn new() -> Weak<T> {
unsafe {
Weak {
ptr: Shared::new(Box::into_raw(box ArcInner {
ptr: Shared::from(Box::into_unique(box ArcInner {
strong: atomic::AtomicUsize::new(0),
weak: atomic::AtomicUsize::new(1),
data: uninitialized(),
Expand Down
31 changes: 31 additions & 0 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,37 @@ impl<T: ?Sized> Box<T> {
pub fn into_raw(b: Box<T>) -> *mut T {
unsafe { mem::transmute(b) }
}

/// Consumes the `Box`, returning the wrapped pointer as `Unique<T>`.
///
/// After calling this function, the caller is responsible for the
/// memory previously managed by the `Box`. In particular, the
/// caller should properly destroy `T` and release the memory. The
/// proper way to do so is to convert the raw pointer back into a
/// `Box` with the [`Box::from_raw`] function.
///
/// Note: this is an associated function, which means that you have
/// to call it as `Box::into_unique(b)` instead of `b.into_unique()`. This
/// is so that there is no conflict with a method on the inner type.
///
/// [`Box::from_raw`]: struct.Box.html#method.from_raw
///
/// # Examples
///
/// ```
/// #![feature(unique)]
///
/// fn main() {
/// let x = Box::new(5);
/// let ptr = Box::into_unique(x);
/// }
/// ```
#[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
issue = "27730")]
#[inline]
pub fn into_unique(b: Box<T>) -> Unique<T> {
unsafe { mem::transmute(b) }
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
20 changes: 8 additions & 12 deletions src/liballoc/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,24 +140,22 @@ struct BoxedNode<K, V> {

impl<K, V> BoxedNode<K, V> {
fn from_leaf(node: Box<LeafNode<K, V>>) -> Self {
unsafe {
BoxedNode { ptr: Unique::new(Box::into_raw(node)) }
}
BoxedNode { ptr: Box::into_unique(node) }
}

fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
unsafe {
BoxedNode { ptr: Unique::new(Box::into_raw(node) as *mut LeafNode<K, V>) }
BoxedNode { ptr: Unique::new_unchecked(Box::into_raw(node) as *mut LeafNode<K, V>) }
}
}

unsafe fn from_ptr(ptr: NonZero<*const LeafNode<K, V>>) -> Self {
BoxedNode { ptr: Unique::new(ptr.get() as *mut LeafNode<K, V>) }
BoxedNode { ptr: Unique::new_unchecked(ptr.get() as *mut LeafNode<K, V>) }
}

fn as_ptr(&self) -> NonZero<*const LeafNode<K, V>> {
unsafe {
NonZero::new(self.ptr.as_ptr())
NonZero::from(self.ptr.as_ref())
}
}
}
Expand Down Expand Up @@ -384,21 +382,19 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
>,
Self
> {
if self.as_leaf().parent.is_null() {
Err(self)
} else {
if let Some(non_zero) = NonZero::new(self.as_leaf().parent as *const LeafNode<K, V>) {
Ok(Handle {
node: NodeRef {
height: self.height + 1,
node: unsafe {
NonZero::new(self.as_leaf().parent as *mut LeafNode<K, V>)
},
node: non_zero,
root: self.root,
_marker: PhantomData
},
idx: self.as_leaf().parent_idx as usize,
_marker: PhantomData
})
} else {
Err(self)
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/liballoc/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl<T> LinkedList<T> {
unsafe {
node.next = self.head;
node.prev = None;
let node = Some(Shared::new(Box::into_raw(node)));
let node = Some(Shared::from(Box::into_unique(node)));

match self.head {
None => self.tail = node,
Expand Down Expand Up @@ -192,7 +192,7 @@ impl<T> LinkedList<T> {
unsafe {
node.next = None;
node.prev = self.tail;
let node = Some(Shared::new(Box::into_raw(node)));
let node = Some(Shared::from(Box::into_unique(node)));

match self.tail {
None => self.head = node,
Expand Down Expand Up @@ -921,7 +921,7 @@ impl<'a, T> IterMut<'a, T> {
Some(prev) => prev,
};

let node = Some(Shared::new(Box::into_raw(box Node {
let node = Some(Shared::from(Box::into_unique(box Node {
next: Some(head),
prev: Some(prev),
element: element,
Expand Down
6 changes: 3 additions & 3 deletions src/liballoc/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<T, A: Alloc> RawVec<T, A> {
};

RawVec {
ptr: Unique::new(ptr as *mut _),
ptr: Unique::new_unchecked(ptr as *mut _),
cap: cap,
a: a,
}
Expand Down Expand Up @@ -159,7 +159,7 @@ impl<T, A: Alloc> RawVec<T, A> {
/// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed.
pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self {
RawVec {
ptr: Unique::new(ptr),
ptr: Unique::new_unchecked(ptr),
cap: cap,
a: a,
}
Expand All @@ -176,7 +176,7 @@ impl<T> RawVec<T, Heap> {
/// If the ptr and capacity come from a RawVec, then this is guaranteed.
pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self {
RawVec {
ptr: Unique::new(ptr),
ptr: Unique::new_unchecked(ptr),
cap: cap,
a: Heap,
}
Expand Down
30 changes: 14 additions & 16 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,18 +303,16 @@ impl<T> Rc<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(value: T) -> Rc<T> {
unsafe {
Rc {
// there is an implicit weak pointer owned by all the strong
// 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: Shared::new(Box::into_raw(box RcBox {
strong: Cell::new(1),
weak: Cell::new(1),
value: value,
})),
}
Rc {
// there is an implicit weak pointer owned by all the strong
// 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: Shared::from(Box::into_unique(box RcBox {
strong: Cell::new(1),
weak: Cell::new(1),
value: value,
})),
}
}

Expand Down Expand Up @@ -418,7 +416,7 @@ impl<T> Rc<T> {

let ptr = (ptr as *const u8).offset(-offset_of!(RcBox<T>, value));
Rc {
ptr: Shared::new(ptr as *mut u8 as *mut _)
ptr: Shared::new_unchecked(ptr as *mut u8 as *mut _)
}
}
}
Expand All @@ -443,7 +441,7 @@ impl Rc<str> {
// Combine the allocation address and the string length into a fat pointer to `RcBox`.
let rcbox_ptr: *mut RcBox<str> = mem::transmute([ptr as usize, value.len()]);
assert!(aligned_len * size_of::<usize>() == size_of_val(&*rcbox_ptr));
Rc { ptr: Shared::new(rcbox_ptr) }
Rc { ptr: Shared::new_unchecked(rcbox_ptr) }
}
}
}
Expand Down Expand Up @@ -476,7 +474,7 @@ impl<T> Rc<[T]> {
// Free the original allocation without freeing its (moved) contents.
box_free(Box::into_raw(value));

Rc { ptr: Shared::new(ptr as *mut _) }
Rc { ptr: Shared::new_unchecked(ptr as *mut _) }
}
}
}
Expand Down Expand Up @@ -1016,7 +1014,7 @@ impl<T> Weak<T> {
pub fn new() -> Weak<T> {
unsafe {
Weak {
ptr: Shared::new(Box::into_raw(box RcBox {
ptr: Shared::from(Box::into_unique(box RcBox {
strong: Cell::new(0),
weak: Cell::new(1),
value: uninitialized(),
Expand Down
4 changes: 2 additions & 2 deletions src/liballoc/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ impl<T> Vec<T> {
tail_start: end,
tail_len: len - end,
iter: range_slice.iter(),
vec: Shared::new(self as *mut _),
vec: Shared::from(self),
}
}
}
Expand Down Expand Up @@ -1727,7 +1727,7 @@ impl<T> IntoIterator for Vec<T> {
let cap = self.buf.cap();
mem::forget(self);
IntoIter {
buf: Shared::new(begin),
buf: Shared::new_unchecked(begin),
cap: cap,
ptr: begin,
end: end,
Expand Down
2 changes: 1 addition & 1 deletion src/liballoc/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ impl<T> VecDeque<T> {
self.head = drain_tail;

Drain {
deque: unsafe { Shared::new(self as *mut _) },
deque: Shared::from(&mut *self),
after_tail: drain_head,
after_head: head,
iter: Iter {
Expand Down
Loading

0 comments on commit b5b7266

Please sign in to comment.