diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 7ef281ff208d7..f3f0a430d1c78 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -66,7 +66,7 @@ use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop}; +use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{self, Index, IndexMut, RangeBounds}; use core::ptr::{self, NonNull}; @@ -854,6 +854,51 @@ impl Vec { ptr } + /// Returns a mutable reference to an element, without doing bounds + /// checking. + /// + /// This is generally not recommended, use with caution! + /// Calling this method with an out-of-allocation index is *[undefined behavior]* + /// even if the resulting reference is not used. + /// When you asign [`MaybeUninit::uninit()`] to the index in bounds, it is + /// *[undefined behavior]* to call other methods or drop the vector before using [`set_len`] + /// to make the index out of bounds. + /// You can have a memory leak if you forget to use [`set_len`] to make the index in bounds + /// after asigning value to the reference out of bounds. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// [`MaybeUninit::uninit()`]: ../mem/union.MaybeUninit.html#method.uninit + /// [`set_len`]: #method.set_len + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_get_uninit_unchecked, maybe_uninit_extra)] + /// + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x = Vec::with_capacity(4); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// x.get_uninit_unchecked(i).write(i as i32); + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0, 1, 2, 3]); + /// ``` + #[unstable(feature = "vec_get_uninit_unchecked", issue = "none")] + pub unsafe fn get_uninit_unchecked(&mut self, index: usize) -> &mut MaybeUninit { + debug_assert!( + index < self.capacity(), + "index out of allocation: the capacity is {} but the index is {}", + self.capacity(), + index + ); + &mut *(self.as_mut_ptr().add(index) as *mut MaybeUninit) + } + /// Forces the length of the vector to `new_len`. /// /// This is a low-level operation that maintains none of the normal