Skip to content

Commit b507cd1

Browse files
authored
Rollup merge of #86344 - est31:maybe-uninit-extra, r=RalfJung
Split MaybeUninit::write into new feature gate and stabilize it This splits off the `MaybeUninit::write` function from the `maybe_uninit_extra` feature gate into a new `maybe_uninit_write` feature gate and stabilizes it. Earlier work to improve the documentation of the write function: #86220 Tracking issue: #63567
2 parents 955b9c0 + 848a621 commit b507cd1

File tree

1 file changed

+43
-15
lines changed

1 file changed

+43
-15
lines changed

library/core/src/mem/maybe_uninit.rs

+43-15
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ use crate::ptr;
7979
/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
8080
/// let mut x = MaybeUninit::<&i32>::uninit();
8181
/// // Set it to a valid value.
82-
/// unsafe { x.as_mut_ptr().write(&0); }
82+
/// x.write(&0);
8383
/// // Extract the initialized data -- this is only allowed *after* properly
8484
/// // initializing `x`!
8585
/// let x = unsafe { x.assume_init() };
@@ -135,7 +135,7 @@ use crate::ptr;
135135
/// // this loop, we have a memory leak, but there is no memory safety
136136
/// // issue.
137137
/// for elem in &mut data[..] {
138-
/// *elem = MaybeUninit::new(vec![42]);
138+
/// elem.write(vec![42]);
139139
/// }
140140
///
141141
/// // Everything is initialized. Transmute the array to the
@@ -161,7 +161,7 @@ use crate::ptr;
161161
/// let mut data_len: usize = 0;
162162
///
163163
/// for elem in &mut data[0..500] {
164-
/// *elem = MaybeUninit::new(String::from("hello"));
164+
/// elem.write(String::from("hello"));
165165
/// data_len += 1;
166166
/// }
167167
///
@@ -410,7 +410,7 @@ impl<T> MaybeUninit<T> {
410410
/// (now safely initialized) contents of `self`.
411411
///
412412
/// As the content is stored inside a `MaybeUninit`, the destructor is not
413-
/// ran for the inner data if the MaybeUninit leaves scope without a call to
413+
/// run for the inner data if the MaybeUninit leaves scope without a call to
414414
/// [`assume_init`], [`assume_init_drop`], or similar. Code that receives
415415
/// the mutable reference returned by this function needs to keep this in
416416
/// mind. The safety model of Rust regards leaks as safe, but they are
@@ -426,7 +426,6 @@ impl<T> MaybeUninit<T> {
426426
/// Correct usage of this method:
427427
///
428428
/// ```rust
429-
/// #![feature(maybe_uninit_extra)]
430429
/// use std::mem::MaybeUninit;
431430
///
432431
/// let mut x = MaybeUninit::<Vec<u8>>::uninit();
@@ -445,7 +444,6 @@ impl<T> MaybeUninit<T> {
445444
/// This usage of the method causes a leak:
446445
///
447446
/// ```rust
448-
/// #![feature(maybe_uninit_extra)]
449447
/// use std::mem::MaybeUninit;
450448
///
451449
/// let mut x = MaybeUninit::<String>::uninit();
@@ -456,8 +454,38 @@ impl<T> MaybeUninit<T> {
456454
/// // x is initialized now:
457455
/// let s = unsafe { x.assume_init() };
458456
/// ```
459-
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
460-
#[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")]
457+
///
458+
/// This method can be used to avoid unsafe in some cases. The example below
459+
/// shows a part of an implementation of a fixed sized arena that lends out
460+
/// pinned references.
461+
/// With `write`, we can avoid the need to write through a raw pointer:
462+
///
463+
/// ```rust
464+
/// #![feature(maybe_uninit_extra)]
465+
/// use core::pin::Pin;
466+
/// use core::mem::MaybeUninit;
467+
///
468+
/// struct PinArena<T> {
469+
/// memory: Box<[MaybeUninit<T>]>,
470+
/// len: usize,
471+
/// }
472+
///
473+
/// impl <T> PinArena<T> {
474+
/// pub fn capacity(&self) -> usize {
475+
/// self.memory.len()
476+
/// }
477+
/// pub fn push(&mut self, val: T) -> Pin<&mut T> {
478+
/// if self.len >= self.capacity() {
479+
/// panic!("Attempted to push to a full pin arena!");
480+
/// }
481+
/// let ref_ = self.memory[self.len].write(val);
482+
/// self.len += 1;
483+
/// unsafe { Pin::new_unchecked(ref_) }
484+
/// }
485+
/// }
486+
/// ```
487+
#[stable(feature = "maybe_uninit_write", since = "1.55.0")]
488+
#[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")]
461489
#[inline(always)]
462490
pub const fn write(&mut self, val: T) -> &mut T {
463491
*self = MaybeUninit::new(val);
@@ -478,7 +506,7 @@ impl<T> MaybeUninit<T> {
478506
/// use std::mem::MaybeUninit;
479507
///
480508
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
481-
/// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
509+
/// x.write(vec![0, 1, 2]);
482510
/// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
483511
/// let x_vec = unsafe { &*x.as_ptr() };
484512
/// assert_eq!(x_vec.len(), 3);
@@ -515,7 +543,7 @@ impl<T> MaybeUninit<T> {
515543
/// use std::mem::MaybeUninit;
516544
///
517545
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
518-
/// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
546+
/// x.write(vec![0, 1, 2]);
519547
/// // Create a reference into the `MaybeUninit<Vec<u32>>`.
520548
/// // This is okay because we initialized it.
521549
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
@@ -574,7 +602,7 @@ impl<T> MaybeUninit<T> {
574602
/// use std::mem::MaybeUninit;
575603
///
576604
/// let mut x = MaybeUninit::<bool>::uninit();
577-
/// unsafe { x.as_mut_ptr().write(true); }
605+
/// x.write(true);
578606
/// let x_init = unsafe { x.assume_init() };
579607
/// assert_eq!(x_init, true);
580608
/// ```
@@ -723,7 +751,7 @@ impl<T> MaybeUninit<T> {
723751
///
724752
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
725753
/// // Initialize `x`:
726-
/// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); }
754+
/// x.write(vec![1, 2, 3]);
727755
/// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
728756
/// // create a shared reference to it:
729757
/// let x: &Vec<u32> = unsafe {
@@ -897,9 +925,9 @@ impl<T> MaybeUninit<T> {
897925
/// use std::mem::MaybeUninit;
898926
///
899927
/// let mut array: [MaybeUninit<i32>; 3] = MaybeUninit::uninit_array();
900-
/// array[0] = MaybeUninit::new(0);
901-
/// array[1] = MaybeUninit::new(1);
902-
/// array[2] = MaybeUninit::new(2);
928+
/// array[0].write(0);
929+
/// array[1].write(1);
930+
/// array[2].write(2);
903931
///
904932
/// // SAFETY: Now safe as we initialised all elements
905933
/// let array = unsafe {

0 commit comments

Comments
 (0)