Skip to content

Commit bde1924

Browse files
committed
Add new_uninit_slice and assume_init on Box, Rc, and Arc of [T]
1 parent 7b02b9f commit bde1924

File tree

3 files changed

+256
-14
lines changed

3 files changed

+256
-14
lines changed

src/liballoc/boxed.rs

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ use core::ops::{
9191
CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState
9292
};
9393
use core::ptr::{self, NonNull, Unique};
94+
use core::slice;
9495
use core::task::{Context, Poll};
9596

9697
use crate::alloc;
@@ -135,7 +136,7 @@ impl<T> Box<T> {
135136
/// // Deferred initialization:
136137
/// five.as_mut_ptr().write(5);
137138
///
138-
/// Box::assume_init(five)
139+
/// five.assume_init()
139140
/// };
140141
///
141142
/// assert_eq!(*five, 5)
@@ -148,6 +149,35 @@ impl<T> Box<T> {
148149
Box(unique.cast())
149150
}
150151

152+
/// Construct a new boxed slice with uninitialized contents.
153+
///
154+
/// # Examples
155+
///
156+
/// ```
157+
/// #![feature(new_uninit)]
158+
///
159+
/// let mut values = Box::<u32>::new_uninit_slice(3);
160+
///
161+
/// let values = unsafe {
162+
/// // Deferred initialization:
163+
/// values[0].as_mut_ptr().write(1);
164+
/// values[1].as_mut_ptr().write(2);
165+
/// values[2].as_mut_ptr().write(3);
166+
///
167+
/// values.assume_init()
168+
/// };
169+
///
170+
/// assert_eq!(*values, [1, 2, 3])
171+
/// ```
172+
#[unstable(feature = "new_uninit", issue = "0")]
173+
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
174+
let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(len).unwrap();
175+
let ptr = unsafe { alloc::alloc(layout) };
176+
let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout));
177+
let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) };
178+
Box(Unique::from(slice))
179+
}
180+
151181
/// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then
152182
/// `x` will be pinned in memory and unable to be moved.
153183
#[stable(feature = "pin", since = "1.33.0")]
@@ -179,15 +209,51 @@ impl<T> Box<mem::MaybeUninit<T>> {
179209
/// // Deferred initialization:
180210
/// five.as_mut_ptr().write(5);
181211
///
182-
/// Box::assume_init(five)
212+
/// five.assume_init()
183213
/// };
184214
///
185215
/// assert_eq!(*five, 5)
186216
/// ```
187217
#[unstable(feature = "new_uninit", issue = "0")]
188218
#[inline]
189-
pub unsafe fn assume_init(this: Self) -> Box<T> {
190-
Box(Box::into_unique(this).cast())
219+
pub unsafe fn assume_init(self) -> Box<T> {
220+
Box(Box::into_unique(self).cast())
221+
}
222+
}
223+
224+
impl<T> Box<[mem::MaybeUninit<T>]> {
225+
/// Convert to `Box<[T]>`.
226+
///
227+
/// # Safety
228+
///
229+
/// As with [`MaybeUninit::assume_init`],
230+
/// it is up to the caller to guarantee that the values
231+
/// really are in an initialized state.
232+
/// Calling this when the content is not yet fully initialized
233+
/// causes immediate undefined behavior.
234+
///
235+
/// # Examples
236+
///
237+
/// ```
238+
/// #![feature(new_uninit)]
239+
///
240+
/// let mut values = Box::<u32>::new_uninit_slice(3);
241+
///
242+
/// let values = unsafe {
243+
/// // Deferred initialization:
244+
/// values[0].as_mut_ptr().write(1);
245+
/// values[1].as_mut_ptr().write(2);
246+
/// values[2].as_mut_ptr().write(3);
247+
///
248+
/// values.assume_init()
249+
/// };
250+
///
251+
/// assert_eq!(*values, [1, 2, 3])
252+
/// ```
253+
#[unstable(feature = "new_uninit", issue = "0")]
254+
#[inline]
255+
pub unsafe fn assume_init(self) -> Box<[T]> {
256+
Box(Unique::new_unchecked(Box::into_raw(self) as _))
191257
}
192258
}
193259

src/liballoc/rc.rs

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ impl<T> Rc<T> {
343343
/// // Deferred initialization:
344344
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
345345
///
346-
/// Rc::assume_init(five)
346+
/// five.assume_init()
347347
/// };
348348
///
349349
/// assert_eq!(*five, 5)
@@ -364,6 +364,50 @@ impl<T> Rc<T> {
364364
}
365365
}
366366

367+
/// Construct a new reference-counted slice with uninitialized contents.
368+
///
369+
/// # Examples
370+
///
371+
/// ```
372+
/// #![feature(new_uninit)]
373+
/// #![feature(get_mut_unchecked)]
374+
///
375+
/// use std::rc::Rc;
376+
///
377+
/// let mut values = Rc::<u32>::new_uninit_slice(3);
378+
///
379+
/// let values = unsafe {
380+
/// // Deferred initialization:
381+
/// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
382+
/// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
383+
/// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);
384+
///
385+
/// values.assume_init()
386+
/// };
387+
///
388+
/// assert_eq!(*values, [1, 2, 3])
389+
/// ```
390+
#[unstable(feature = "new_uninit", issue = "0")]
391+
pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
392+
let data_layout = Layout::array::<mem::MaybeUninit<T>>(len).unwrap();
393+
let (layout, offset) = Layout::new::<RcBox<()>>().extend(data_layout).unwrap();
394+
unsafe {
395+
let allocated_ptr = Global.alloc(layout)
396+
.unwrap_or_else(|_| handle_alloc_error(layout))
397+
.as_ptr();
398+
let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit<T>;
399+
let slice: *mut [mem::MaybeUninit<T>] = from_raw_parts_mut(data_ptr, len);
400+
let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit<T>]>;
401+
let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr);
402+
ptr::write(&mut (*wide_ptr).strong, Cell::new(1));
403+
ptr::write(&mut (*wide_ptr).weak, Cell::new(1));
404+
Rc {
405+
ptr: NonNull::new_unchecked(wide_ptr),
406+
phantom: PhantomData,
407+
}
408+
}
409+
}
410+
367411
/// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then
368412
/// `value` will be pinned in memory and unable to be moved.
369413
#[stable(feature = "pin", since = "1.33.0")]
@@ -439,16 +483,60 @@ impl<T> Rc<mem::MaybeUninit<T>> {
439483
/// // Deferred initialization:
440484
/// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
441485
///
442-
/// Rc::assume_init(five)
486+
/// five.assume_init()
443487
/// };
444488
///
445489
/// assert_eq!(*five, 5)
446490
/// ```
447491
#[unstable(feature = "new_uninit", issue = "0")]
448492
#[inline]
449-
pub unsafe fn assume_init(this: Self) -> Rc<T> {
450-
let ptr = this.ptr.cast();
451-
mem::forget(this);
493+
pub unsafe fn assume_init(self) -> Rc<T> {
494+
let ptr = self.ptr.cast();
495+
mem::forget(self);
496+
Rc {
497+
ptr,
498+
phantom: PhantomData,
499+
}
500+
}
501+
}
502+
503+
impl<T> Rc<[mem::MaybeUninit<T>]> {
504+
/// Convert to `Rc<[T]>`.
505+
///
506+
/// # Safety
507+
///
508+
/// As with [`MaybeUninit::assume_init`],
509+
/// it is up to the caller to guarantee that the value
510+
/// really is in an initialized state.
511+
/// Calling this when the content is not yet fully initialized
512+
/// causes immediate undefined behavior.
513+
///
514+
/// # Examples
515+
///
516+
/// ```
517+
/// #![feature(new_uninit)]
518+
/// #![feature(get_mut_unchecked)]
519+
///
520+
/// use std::rc::Rc;
521+
///
522+
/// let mut values = Rc::<u32>::new_uninit_slice(3);
523+
///
524+
/// let values = unsafe {
525+
/// // Deferred initialization:
526+
/// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
527+
/// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
528+
/// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);
529+
///
530+
/// values.assume_init()
531+
/// };
532+
///
533+
/// assert_eq!(*values, [1, 2, 3])
534+
/// ```
535+
#[unstable(feature = "new_uninit", issue = "0")]
536+
#[inline]
537+
pub unsafe fn assume_init(self) -> Rc<[T]> {
538+
let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _);
539+
mem::forget(self);
452540
Rc {
453541
ptr,
454542
phantom: PhantomData,

src/liballoc/sync.rs

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ impl<T> Arc<T> {
327327
/// // Deferred initialization:
328328
/// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
329329
///
330-
/// Arc::assume_init(five)
330+
/// five.assume_init()
331331
/// };
332332
///
333333
/// assert_eq!(*five, 5)
@@ -348,6 +348,50 @@ impl<T> Arc<T> {
348348
}
349349
}
350350

351+
/// Construct a new reference-counted slice with uninitialized contents.
352+
///
353+
/// # Examples
354+
///
355+
/// ```
356+
/// #![feature(new_uninit)]
357+
/// #![feature(get_mut_unchecked)]
358+
///
359+
/// use std::sync::Arc;
360+
///
361+
/// let mut values = Arc::<u32>::new_uninit_slice(3);
362+
///
363+
/// let values = unsafe {
364+
/// // Deferred initialization:
365+
/// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
366+
/// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
367+
/// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);
368+
///
369+
/// values.assume_init()
370+
/// };
371+
///
372+
/// assert_eq!(*values, [1, 2, 3])
373+
/// ```
374+
#[unstable(feature = "new_uninit", issue = "0")]
375+
pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
376+
let data_layout = Layout::array::<mem::MaybeUninit<T>>(len).unwrap();
377+
let (layout, offset) = Layout::new::<ArcInner<()>>().extend(data_layout).unwrap();
378+
unsafe {
379+
let allocated_ptr = Global.alloc(layout)
380+
.unwrap_or_else(|_| handle_alloc_error(layout))
381+
.as_ptr();
382+
let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit<T>;
383+
let slice: *mut [mem::MaybeUninit<T>] = from_raw_parts_mut(data_ptr, len);
384+
let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit<T>]>;
385+
let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr);
386+
ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1));
387+
ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1));
388+
Arc {
389+
ptr: NonNull::new_unchecked(wide_ptr),
390+
phantom: PhantomData,
391+
}
392+
}
393+
}
394+
351395
/// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then
352396
/// `data` will be pinned in memory and unable to be moved.
353397
#[stable(feature = "pin", since = "1.33.0")]
@@ -423,16 +467,60 @@ impl<T> Arc<mem::MaybeUninit<T>> {
423467
/// // Deferred initialization:
424468
/// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);
425469
///
426-
/// Arc::assume_init(five)
470+
/// five.assume_init()
427471
/// };
428472
///
429473
/// assert_eq!(*five, 5)
430474
/// ```
431475
#[unstable(feature = "new_uninit", issue = "0")]
432476
#[inline]
433-
pub unsafe fn assume_init(this: Self) -> Arc<T> {
434-
let ptr = this.ptr.cast();
435-
mem::forget(this);
477+
pub unsafe fn assume_init(self) -> Arc<T> {
478+
let ptr = self.ptr.cast();
479+
mem::forget(self);
480+
Arc {
481+
ptr,
482+
phantom: PhantomData,
483+
}
484+
}
485+
}
486+
487+
impl<T> Arc<[mem::MaybeUninit<T>]> {
488+
/// Convert to `Arc<[T]>`.
489+
///
490+
/// # Safety
491+
///
492+
/// As with [`MaybeUninit::assume_init`],
493+
/// it is up to the caller to guarantee that the value
494+
/// really is in an initialized state.
495+
/// Calling this when the content is not yet fully initialized
496+
/// causes immediate undefined behavior.
497+
///
498+
/// # Examples
499+
///
500+
/// ```
501+
/// #![feature(new_uninit)]
502+
/// #![feature(get_mut_unchecked)]
503+
///
504+
/// use std::sync::Arc;
505+
///
506+
/// let mut values = Arc::<u32>::new_uninit_slice(3);
507+
///
508+
/// let values = unsafe {
509+
/// // Deferred initialization:
510+
/// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
511+
/// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
512+
/// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);
513+
///
514+
/// values.assume_init()
515+
/// };
516+
///
517+
/// assert_eq!(*values, [1, 2, 3])
518+
/// ```
519+
#[unstable(feature = "new_uninit", issue = "0")]
520+
#[inline]
521+
pub unsafe fn assume_init(self) -> Arc<[T]> {
522+
let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _);
523+
mem::forget(self);
436524
Arc {
437525
ptr,
438526
phantom: PhantomData,

0 commit comments

Comments
 (0)