Skip to content

Commit 7b02b9f

Browse files
committed
Add new_uninit and assume_init on Box, Rc, and Arc
1 parent 1613fda commit 7b02b9f

File tree

4 files changed

+231
-0
lines changed

4 files changed

+231
-0
lines changed

src/liballoc/boxed.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ use core::ops::{
9393
use core::ptr::{self, NonNull, Unique};
9494
use core::task::{Context, Poll};
9595

96+
use crate::alloc;
9697
use crate::vec::Vec;
9798
use crate::raw_vec::RawVec;
9899
use crate::str::from_boxed_utf8_unchecked;
@@ -121,6 +122,32 @@ impl<T> Box<T> {
121122
box x
122123
}
123124

125+
/// Construct a new box with uninitialized contents.
126+
///
127+
/// # Examples
128+
///
129+
/// ```
130+
/// #![feature(new_uninit)]
131+
///
132+
/// let mut five = Box::<u32>::new_uninit();
133+
///
134+
/// let five = unsafe {
135+
/// // Deferred initialization:
136+
/// five.as_mut_ptr().write(5);
137+
///
138+
/// Box::assume_init(five)
139+
/// };
140+
///
141+
/// assert_eq!(*five, 5)
142+
/// ```
143+
#[unstable(feature = "new_uninit", issue = "0")]
144+
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
145+
let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
146+
let ptr = unsafe { alloc::alloc(layout) };
147+
let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout));
148+
Box(unique.cast())
149+
}
150+
124151
/// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then
125152
/// `x` will be pinned in memory and unable to be moved.
126153
#[stable(feature = "pin", since = "1.33.0")]
@@ -130,6 +157,40 @@ impl<T> Box<T> {
130157
}
131158
}
132159

160+
impl<T> Box<mem::MaybeUninit<T>> {
161+
/// Convert to `Box<T>`.
162+
///
163+
/// # Safety
164+
///
165+
/// As with [`MaybeUninit::assume_init`],
166+
/// it is up to the caller to guarantee that the value
167+
/// really is in an initialized state.
168+
/// Calling this when the content is not yet fully initialized
169+
/// causes immediate undefined behavior.
170+
///
171+
/// # Examples
172+
///
173+
/// ```
174+
/// #![feature(new_uninit)]
175+
///
176+
/// let mut five = Box::<u32>::new_uninit();
177+
///
178+
/// let five: Box<u32> = unsafe {
179+
/// // Deferred initialization:
180+
/// five.as_mut_ptr().write(5);
181+
///
182+
/// Box::assume_init(five)
183+
/// };
184+
///
185+
/// assert_eq!(*five, 5)
186+
/// ```
187+
#[unstable(feature = "new_uninit", issue = "0")]
188+
#[inline]
189+
pub unsafe fn assume_init(this: Self) -> Box<T> {
190+
Box(Box::into_unique(this).cast())
191+
}
192+
}
193+
133194
impl<T: ?Sized> Box<T> {
134195
/// Constructs a box from a raw pointer.
135196
///

src/liballoc/rc.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,43 @@ impl<T> Rc<T> {
327327
}))
328328
}
329329

330+
/// Construct a new Rc with uninitialized contents.
331+
///
332+
/// # Examples
333+
///
334+
/// ```
335+
/// #![feature(new_uninit)]
336+
/// #![feature(get_mut_unchecked)]
337+
///
338+
/// use std::rc::Rc;
339+
///
340+
/// let mut five = Rc::<u32>::new_uninit();
341+
///
342+
/// let five = unsafe {
343+
/// // Deferred initialization:
344+
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
345+
///
346+
/// Rc::assume_init(five)
347+
/// };
348+
///
349+
/// assert_eq!(*five, 5)
350+
/// ```
351+
#[unstable(feature = "new_uninit", issue = "0")]
352+
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
353+
let layout = Layout::new::<RcBox<mem::MaybeUninit<T>>>();
354+
unsafe {
355+
let mut ptr = Global.alloc(layout)
356+
.unwrap_or_else(|_| handle_alloc_error(layout))
357+
.cast::<RcBox<mem::MaybeUninit<T>>>();
358+
ptr::write(&mut ptr.as_mut().strong, Cell::new(1));
359+
ptr::write(&mut ptr.as_mut().weak, Cell::new(1));
360+
Rc {
361+
ptr,
362+
phantom: PhantomData,
363+
}
364+
}
365+
}
366+
330367
/// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then
331368
/// `value` will be pinned in memory and unable to be moved.
332369
#[stable(feature = "pin", since = "1.33.0")]
@@ -377,6 +414,48 @@ impl<T> Rc<T> {
377414
}
378415
}
379416

417+
impl<T> Rc<mem::MaybeUninit<T>> {
418+
/// Convert to `Rc<T>`.
419+
///
420+
/// # Safety
421+
///
422+
/// As with [`MaybeUninit::assume_init`],
423+
/// it is up to the caller to guarantee that the value
424+
/// really is in an initialized state.
425+
/// Calling this when the content is not yet fully initialized
426+
/// causes immediate undefined behavior.
427+
///
428+
/// # Examples
429+
///
430+
/// ```
431+
/// #![feature(new_uninit)]
432+
/// #![feature(get_mut_unchecked)]
433+
///
434+
/// use std::rc::Rc;
435+
///
436+
/// let mut five = Rc::<u32>::new_uninit();
437+
///
438+
/// let five = unsafe {
439+
/// // Deferred initialization:
440+
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
441+
///
442+
/// Rc::assume_init(five)
443+
/// };
444+
///
445+
/// assert_eq!(*five, 5)
446+
/// ```
447+
#[unstable(feature = "new_uninit", issue = "0")]
448+
#[inline]
449+
pub unsafe fn assume_init(this: Self) -> Rc<T> {
450+
let ptr = this.ptr.cast();
451+
mem::forget(this);
452+
Rc {
453+
ptr,
454+
phantom: PhantomData,
455+
}
456+
}
457+
}
458+
380459
impl<T: ?Sized> Rc<T> {
381460
/// Consumes the `Rc`, returning the wrapped pointer.
382461
///
@@ -582,6 +661,8 @@ impl<T: ?Sized> Rc<T> {
582661
/// # Examples
583662
///
584663
/// ```
664+
/// #![feature(get_mut_unchecked)]
665+
///
585666
/// use std::rc::Rc;
586667
///
587668
/// let mut x = Rc::new(String::new());

src/liballoc/sync.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,43 @@ impl<T> Arc<T> {
311311
Self::from_inner(Box::into_raw_non_null(x))
312312
}
313313

314+
/// Construct a Arc box with uninitialized contents.
315+
///
316+
/// # Examples
317+
///
318+
/// ```
319+
/// #![feature(new_uninit)]
320+
/// #![feature(get_mut_unchecked)]
321+
///
322+
/// use std::sync::Arc;
323+
///
324+
/// let mut five = Arc::<u32>::new_uninit();
325+
///
326+
/// let five = unsafe {
327+
/// // Deferred initialization:
328+
/// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
329+
///
330+
/// Arc::assume_init(five)
331+
/// };
332+
///
333+
/// assert_eq!(*five, 5)
334+
/// ```
335+
#[unstable(feature = "new_uninit", issue = "0")]
336+
pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
337+
let layout = Layout::new::<ArcInner<mem::MaybeUninit<T>>>();
338+
unsafe {
339+
let mut ptr = Global.alloc(layout)
340+
.unwrap_or_else(|_| handle_alloc_error(layout))
341+
.cast::<ArcInner<mem::MaybeUninit<T>>>();
342+
ptr::write(&mut ptr.as_mut().strong, atomic::AtomicUsize::new(1));
343+
ptr::write(&mut ptr.as_mut().weak, atomic::AtomicUsize::new(1));
344+
Arc {
345+
ptr,
346+
phantom: PhantomData,
347+
}
348+
}
349+
}
350+
314351
/// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then
315352
/// `data` will be pinned in memory and unable to be moved.
316353
#[stable(feature = "pin", since = "1.33.0")]
@@ -361,6 +398,48 @@ impl<T> Arc<T> {
361398
}
362399
}
363400

401+
impl<T> Arc<mem::MaybeUninit<T>> {
402+
/// Convert to `Arc<T>`.
403+
///
404+
/// # Safety
405+
///
406+
/// As with [`MaybeUninit::assume_init`],
407+
/// it is up to the caller to guarantee that the value
408+
/// really is in an initialized state.
409+
/// Calling this when the content is not yet fully initialized
410+
/// causes immediate undefined behavior.
411+
///
412+
/// # Examples
413+
///
414+
/// ```
415+
/// #![feature(new_uninit)]
416+
/// #![feature(get_mut_unchecked)]
417+
///
418+
/// use std::sync::Arc;
419+
///
420+
/// let mut five = Arc::<u32>::new_uninit();
421+
///
422+
/// let five = unsafe {
423+
/// // Deferred initialization:
424+
/// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
425+
///
426+
/// Arc::assume_init(five)
427+
/// };
428+
///
429+
/// assert_eq!(*five, 5)
430+
/// ```
431+
#[unstable(feature = "new_uninit", issue = "0")]
432+
#[inline]
433+
pub unsafe fn assume_init(this: Self) -> Arc<T> {
434+
let ptr = this.ptr.cast();
435+
mem::forget(this);
436+
Arc {
437+
ptr,
438+
phantom: PhantomData,
439+
}
440+
}
441+
}
442+
364443
impl<T: ?Sized> Arc<T> {
365444
/// Consumes the `Arc`, returning the wrapped pointer.
366445
///
@@ -967,6 +1046,8 @@ impl<T: ?Sized> Arc<T> {
9671046
/// # Examples
9681047
///
9691048
/// ```
1049+
/// #![feature(get_mut_unchecked)]
1050+
///
9701051
/// use std::sync::Arc;
9711052
///
9721053
/// let mut x = Arc::new(String::new());

src/libcore/ptr/unique.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ impl<T: ?Sized> Unique<T> {
122122
pub unsafe fn as_mut(&mut self) -> &mut T {
123123
&mut *self.as_ptr()
124124
}
125+
126+
/// Cast to a pointer of another type
127+
#[inline]
128+
pub const fn cast<U>(self) -> Unique<U> {
129+
unsafe {
130+
Unique::new_unchecked(self.as_ptr() as *mut U)
131+
}
132+
}
125133
}
126134

127135
#[unstable(feature = "ptr_internals", issue = "0")]

0 commit comments

Comments
 (0)