Skip to content

Commit fa98ff5

Browse files
committed
Remove ptr::Unique
#71507 (comment) discusses whether `Unique` not actually being unique is UB. `Unique` has very limited use over `NonNull`, so it doesn’t seem worth spending a lot of effort defining an abstraction and coming up with rules about what uses of it are or aren’t sound.
1 parent 0612568 commit fa98ff5

31 files changed

+112
-344
lines changed

src/liballoc/alloc.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![stable(feature = "alloc_module", since = "1.28.0")]
44

55
use core::intrinsics::{self, min_align_of_val, size_of_val};
6-
use core::ptr::{NonNull, Unique};
6+
use core::ptr::NonNull;
77

88
#[stable(feature = "alloc_module", since = "1.28.0")]
99
#[doc(inline)]
@@ -258,7 +258,7 @@ unsafe impl AllocRef for Global {
258258
}
259259
}
260260

261-
/// The allocator for unique pointers.
261+
/// The allocator for Box.
262262
// This function must not unwind. If it does, MIR codegen will fail.
263263
#[cfg(not(test))]
264264
#[lang = "exchange_malloc"]
@@ -276,9 +276,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
276276
// This signature has to be the same as `Box`, otherwise an ICE will happen.
277277
// When an additional parameter to `Box` is added (like `A: AllocRef`), this has to be added here as
278278
// well.
279-
// For example if `Box` is changed to `struct Box<T: ?Sized, A: AllocRef>(Unique<T>, A)`,
280-
// this function has to be changed to `fn box_free<T: ?Sized, A: AllocRef>(Unique<T>, A)` as well.
281-
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
279+
// For example if `Box` is changed to `struct Box<T: ?Sized, A: AllocRef>(NonNull<T>, A)`,
280+
// this function has to be changed to `fn box_free<T: ?Sized, A: AllocRef>(NonNull<T>, A)` as well.
281+
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: NonNull<T>) {
282282
let size = size_of_val(ptr.as_ref());
283283
let align = min_align_of_val(ptr.as_ref());
284284
let layout = Layout::from_size_align_unchecked(size, align);

src/liballoc/boxed.rs

+28-15
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ use core::fmt;
136136
use core::future::Future;
137137
use core::hash::{Hash, Hasher};
138138
use core::iter::{FromIterator, FusedIterator, Iterator};
139-
use core::marker::{Unpin, Unsize};
139+
use core::marker::{PhantomData, Unpin, Unsize};
140140
use core::mem;
141141
use core::ops::{
142142
CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver,
143143
};
144144
use core::pin::Pin;
145-
use core::ptr::{self, NonNull, Unique};
145+
use core::ptr::{self, NonNull};
146146
use core::task::{Context, Poll};
147147

148148
use crate::alloc::{self, AllocInit, AllocRef, Global};
@@ -156,7 +156,26 @@ use crate::vec::Vec;
156156
#[lang = "owned_box"]
157157
#[fundamental]
158158
#[stable(feature = "rust1", since = "1.0.0")]
159-
pub struct Box<T: ?Sized>(Unique<T>);
159+
pub struct Box<T: ?Sized>(BoxPtr<T>);
160+
161+
// FIXME: remove this struct and give `Box` two fields.
162+
// Currently this causes an ICE with 'assertion failed: sig.c_variadic || extra_args.is_empty()'
163+
struct BoxPtr<T: ?Sized> {
164+
ptr: NonNull<T>,
165+
166+
// NOTE: this marker has no consequences for variance, but is necessary
167+
// for dropck to understand that we logically own a `T`.
168+
//
169+
// For details, see:
170+
// https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
171+
_phantom: PhantomData<T>,
172+
}
173+
174+
#[stable(feature = "rust1", since = "1.0.0")]
175+
unsafe impl<T: Send + ?Sized> Send for Box<T> {}
176+
177+
#[stable(feature = "rust1", since = "1.0.0")]
178+
unsafe impl<T: Sync + ?Sized> Sync for Box<T> {}
160179

161180
impl<T> Box<T> {
162181
/// Allocates memory on the heap and then places `x` into it.
@@ -382,7 +401,7 @@ impl<T: ?Sized> Box<T> {
382401
#[stable(feature = "box_raw", since = "1.4.0")]
383402
#[inline]
384403
pub unsafe fn from_raw(raw: *mut T) -> Self {
385-
Box(Unique::new_unchecked(raw))
404+
Box(BoxPtr { ptr: NonNull::new_unchecked(raw), _phantom: PhantomData })
386405
}
387406

388407
/// Consumes the `Box`, returning a wrapped raw pointer.
@@ -462,22 +481,14 @@ impl<T: ?Sized> Box<T> {
462481
#[unstable(feature = "box_into_raw_non_null", issue = "47336")]
463482
#[inline]
464483
pub fn into_raw_non_null(b: Box<T>) -> NonNull<T> {
465-
Box::into_unique(b).into()
466-
}
467-
468-
#[unstable(feature = "ptr_internals", issue = "none", reason = "use into_raw_non_null instead")]
469-
#[inline]
470-
#[doc(hidden)]
471-
pub fn into_unique(b: Box<T>) -> Unique<T> {
472-
let b = mem::ManuallyDrop::new(b);
473-
let mut unique = b.0;
484+
let mut b = mem::ManuallyDrop::new(b);
474485
// Box is kind-of a library type, but recognized as a "unique pointer" by
475486
// Stacked Borrows. This function here corresponds to "reborrowing to
476487
// a raw pointer", but there is no actual reborrow here -- so
477488
// without some care, the pointer we are returning here still carries
478489
// the tag of `b`, with `Unique` permission.
479490
// We round-trip through a mutable reference to avoid that.
480-
unsafe { Unique::new_unchecked(unique.as_mut() as *mut T) }
491+
unsafe { NonNull::new_unchecked(b.0.ptr.as_mut() as *mut T) }
481492
}
482493

483494
/// Consumes and leaks the `Box`, returning a mutable reference,
@@ -910,7 +921,7 @@ impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
910921
impl<T: ?Sized> fmt::Pointer for Box<T> {
911922
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
912923
// It's not possible to extract the inner Uniq directly from the Box,
913-
// instead we cast it to a *const which aliases the Unique
924+
// instead we cast it to a *const which aliases the NonNull
914925
let ptr: *const T = &**self;
915926
fmt::Pointer::fmt(&ptr, f)
916927
}
@@ -1025,9 +1036,11 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
10251036

10261037
#[unstable(feature = "coerce_unsized", issue = "27732")]
10271038
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
1039+
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<BoxPtr<U>> for BoxPtr<T> {}
10281040

10291041
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
10301042
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
1043+
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<BoxPtr<U>> for BoxPtr<T> {}
10311044

10321045
#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")]
10331046
impl<A> FromIterator<A> for Box<[A]> {

src/liballoc/collections/btree/node.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
use core::cmp::Ordering;
3535
use core::marker::PhantomData;
3636
use core::mem::{self, MaybeUninit};
37-
use core::ptr::{self, NonNull, Unique};
37+
use core::ptr::{self, NonNull};
3838
use core::slice;
3939

4040
use crate::alloc::{AllocRef, Global, Layout};
@@ -118,20 +118,20 @@ impl<K, V> InternalNode<K, V> {
118118
/// of nodes it actually contains, and, partially due to this lack of information,
119119
/// has no destructor.
120120
struct BoxedNode<K, V> {
121-
ptr: Unique<LeafNode<K, V>>,
121+
ptr: NonNull<LeafNode<K, V>>,
122122
}
123123

124124
impl<K, V> BoxedNode<K, V> {
125125
fn from_leaf(node: Box<LeafNode<K, V>>) -> Self {
126-
BoxedNode { ptr: Box::into_unique(node) }
126+
BoxedNode { ptr: Box::into_raw_non_null(node) }
127127
}
128128

129129
fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
130-
BoxedNode { ptr: Box::into_unique(node).cast() }
130+
BoxedNode { ptr: Box::into_raw_non_null(node).cast() }
131131
}
132132

133133
unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
134-
BoxedNode { ptr: Unique::from(ptr) }
134+
BoxedNode { ptr: NonNull::from(ptr) }
135135
}
136136

137137
fn as_ptr(&self) -> NonNull<LeafNode<K, V>> {

src/liballoc/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@
105105
#![feature(optin_builtin_traits)]
106106
#![feature(or_patterns)]
107107
#![feature(pattern)]
108-
#![feature(ptr_internals)]
109108
#![feature(ptr_offset_from)]
110109
#![feature(rustc_attrs)]
111110
#![feature(receiver_trait)]

src/liballoc/raw_vec.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33

44
use core::alloc::MemoryBlock;
55
use core::cmp;
6+
use core::marker::PhantomData;
67
use core::mem::{self, ManuallyDrop, MaybeUninit};
78
use core::ops::Drop;
8-
use core::ptr::{NonNull, Unique};
9+
use core::ptr::NonNull;
910
use core::slice;
1011

1112
use crate::alloc::{
@@ -25,14 +26,15 @@ mod tests;
2526
/// involved. This type is excellent for building your own data structures like Vec and VecDeque.
2627
/// In particular:
2728
///
28-
/// * Produces `Unique::empty()` on zero-sized types.
29-
/// * Produces `Unique::empty()` on zero-length allocations.
30-
/// * Avoids freeing `Unique::empty()`.
29+
/// * Produces `NonNull::dangling()` on zero-sized types.
30+
/// * Produces `NonNull::dangling()` on zero-length allocations.
31+
/// * Avoids freeing `NonNull::dangling()`.
3132
/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics).
3233
/// * Guards against 32-bit systems allocating more than isize::MAX bytes.
3334
/// * Guards against overflowing your length.
3435
/// * Calls `handle_alloc_error` for fallible allocations.
35-
/// * Contains a `ptr::Unique` and thus endows the user with all related benefits.
36+
/// * Contains a `ptr::NonNull` and thus endows the user with enum layout optimizations.
37+
/// * Is `Send` and `Sync` when items are.
3638
/// * Uses the excess returned from the allocator to use the largest available capacity.
3739
///
3840
/// This type does not in anyway inspect the memory that it manages. When dropped it *will*
@@ -44,11 +46,24 @@ mod tests;
4446
/// `Box<[T]>`, since `capacity()` won't yield the length.
4547
#[allow(missing_debug_implementations)]
4648
pub struct RawVec<T, A: AllocRef = Global> {
47-
ptr: Unique<T>,
49+
ptr: NonNull<T>,
4850
cap: usize,
4951
alloc: A,
52+
53+
// NOTE: this marker has no consequences for variance, but is necessary
54+
// for dropck to understand that we logically own a `T`.
55+
//
56+
// For details, see:
57+
// https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
58+
_phantom: PhantomData<T>,
5059
}
5160

61+
#[stable(feature = "rust1", since = "1.0.0")]
62+
unsafe impl<T: Send, A: AllocRef + Send> Send for RawVec<T, A> {}
63+
64+
#[stable(feature = "rust1", since = "1.0.0")]
65+
unsafe impl<T: Sync, A: AllocRef + Sync> Sync for RawVec<T, A> {}
66+
5267
impl<T> RawVec<T, Global> {
5368
/// HACK(Centril): This exists because `#[unstable]` `const fn`s needn't conform
5469
/// to `min_const_fn` and so they cannot be called in `min_const_fn`s either.
@@ -125,7 +140,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
125140
/// the returned `RawVec`.
126141
pub const fn new_in(alloc: A) -> Self {
127142
// `cap: 0` means "unallocated". zero-sized types are ignored.
128-
Self { ptr: Unique::empty(), cap: 0, alloc }
143+
Self { ptr: NonNull::dangling(), cap: 0, alloc, _phantom: PhantomData }
129144
}
130145

131146
/// Like `with_capacity`, but parameterized over the choice of
@@ -154,6 +169,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
154169
ptr: memory.ptr.cast().into(),
155170
cap: Self::capacity_from_bytes(memory.size),
156171
alloc,
172+
_phantom: PhantomData,
157173
}
158174
}
159175
}
@@ -168,11 +184,11 @@ impl<T, A: AllocRef> RawVec<T, A> {
168184
/// If the `ptr` and `capacity` come from a `RawVec` created via `a`, then this is guaranteed.
169185
#[inline]
170186
pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self {
171-
Self { ptr: Unique::new_unchecked(ptr), cap: capacity, alloc: a }
187+
Self { ptr: NonNull::new_unchecked(ptr), cap: capacity, alloc: a, _phantom: PhantomData }
172188
}
173189

174190
/// Gets a raw pointer to the start of the allocation. Note that this is
175-
/// `Unique::empty()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
191+
/// `NonNull::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
176192
/// be careful.
177193
pub fn ptr(&self) -> *mut T {
178194
self.ptr.as_ptr()

src/liballoc/rc.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -984,8 +984,8 @@ impl<T: ?Sized> Rc<T> {
984984

985985
fn from_box(v: Box<T>) -> Rc<T> {
986986
unsafe {
987-
let box_unique = Box::into_unique(v);
988-
let bptr = box_unique.as_ptr();
987+
let box_non_null = Box::into_raw_non_null(v);
988+
let bptr = box_non_null.as_ptr();
989989

990990
let value_size = size_of_val(&*bptr);
991991
let ptr = Self::allocate_for_ptr(bptr);
@@ -998,7 +998,7 @@ impl<T: ?Sized> Rc<T> {
998998
);
999999

10001000
// Free the allocation without dropping its contents
1001-
box_free(box_unique);
1001+
box_free(box_non_null);
10021002

10031003
Self::from_ptr(ptr)
10041004
}

src/liballoc/sync.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -862,8 +862,8 @@ impl<T: ?Sized> Arc<T> {
862862

863863
fn from_box(v: Box<T>) -> Arc<T> {
864864
unsafe {
865-
let box_unique = Box::into_unique(v);
866-
let bptr = box_unique.as_ptr();
865+
let box_non_null = Box::into_raw_non_null(v);
866+
let bptr = box_non_null.as_ptr();
867867

868868
let value_size = size_of_val(&*bptr);
869869
let ptr = Self::allocate_for_ptr(bptr);
@@ -876,7 +876,7 @@ impl<T: ?Sized> Arc<T> {
876876
);
877877

878878
// Free the allocation without dropping its contents
879-
box_free(box_unique);
879+
box_free(box_non_null);
880880

881881
Self::from_ptr(ptr)
882882
}

src/libcore/ptr/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ mod non_null;
9191
#[stable(feature = "nonnull", since = "1.25.0")]
9292
pub use non_null::NonNull;
9393

94-
mod unique;
95-
#[unstable(feature = "ptr_internals", issue = "none")]
96-
pub use unique::Unique;
97-
9894
mod const_ptr;
9995
mod mut_ptr;
10096

src/libcore/ptr/non_null.rs

-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use crate::hash;
55
use crate::marker::Unsize;
66
use crate::mem;
77
use crate::ops::{CoerceUnsized, DispatchFromDyn};
8-
use crate::ptr::Unique;
98

109
// ignore-tidy-undocumented-unsafe
1110

@@ -201,14 +200,6 @@ impl<T: ?Sized> hash::Hash for NonNull<T> {
201200
}
202201
}
203202

204-
#[unstable(feature = "ptr_internals", issue = "none")]
205-
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
206-
#[inline]
207-
fn from(unique: Unique<T>) -> Self {
208-
unsafe { NonNull::new_unchecked(unique.as_ptr()) }
209-
}
210-
}
211-
212203
#[stable(feature = "nonnull", since = "1.25.0")]
213204
impl<T: ?Sized> From<&mut T> for NonNull<T> {
214205
#[inline]

0 commit comments

Comments
 (0)