Skip to content

Commit 428ab7e

Browse files
committed
shadow as_ptr as as_mut_ptr in Vec to avoid going through Deref
1 parent 9d82826 commit 428ab7e

File tree

1 file changed

+71
-7
lines changed

1 file changed

+71
-7
lines changed

src/liballoc/vec.rs

+71-7
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,75 @@ impl<T> Vec<T> {
735735
self
736736
}
737737

738+
/// Returns a raw pointer to the vector's buffer.
739+
///
740+
/// The caller must ensure that the vector outlives the pointer this
741+
/// function returns, or else it will end up pointing to garbage.
742+
/// Modifying the vector may cause its buffer to be reallocated,
743+
/// which would also make any pointers to it invalid.
744+
///
745+
/// The caller must also ensure that the memory the pointer (non-transitively) points to
746+
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
747+
/// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`].
748+
///
749+
/// # Examples
750+
///
751+
/// ```
752+
/// let x = vec![1, 2, 4];
753+
/// let x_ptr = x.as_ptr();
754+
///
755+
/// unsafe {
756+
/// for i in 0..x.len() {
757+
/// assert_eq!(*x_ptr.add(i), 1 << i);
758+
/// }
759+
/// }
760+
/// ```
761+
///
762+
/// [`as_mut_ptr`]: #method.as_mut_ptr
763+
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
764+
#[inline]
765+
pub fn as_ptr(&self) -> *const T {
766+
// We shadow the slice method of the same name to avoid going through
767+
// `deref`, which creates an intermediate reference.
768+
let ptr = self.buf.ptr();
769+
unsafe { assume(!ptr.is_null()); }
770+
ptr
771+
}
772+
773+
/// Returns an unsafe mutable pointer to the vector's buffer.
774+
///
775+
/// The caller must ensure that the vector outlives the pointer this
776+
/// function returns, or else it will end up pointing to garbage.
777+
/// Modifying the vector may cause its buffer to be reallocated,
778+
/// which would also make any pointers to it invalid.
779+
///
780+
/// # Examples
781+
///
782+
/// ```
783+
/// // Allocate vector big enough for 4 elements.
784+
/// let size = 4;
785+
/// let mut x: Vec<i32> = Vec::with_capacity(size);
786+
/// let x_ptr = x.as_mut_ptr();
787+
///
788+
/// // Initialize elements via raw pointer writes, then set length.
789+
/// unsafe {
790+
/// for i in 0..size {
791+
/// *x_ptr.add(i) = i as i32;
792+
/// }
793+
/// x.set_len(size);
794+
/// }
795+
/// assert_eq!(&*x, &[0,1,2,3]);
796+
/// ```
797+
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
798+
#[inline]
799+
pub fn as_mut_ptr(&mut self) -> *mut T {
800+
// We shadow the slice method of the same name to avoid going through
801+
// `deref_mut`, which creates an intermediate reference.
802+
let ptr = self.buf.ptr();
803+
unsafe { assume(!ptr.is_null()); }
804+
ptr
805+
}
806+
738807
/// Forces the length of the vector to `new_len`.
739808
///
740809
/// This is a low-level operation that maintains none of the normal
@@ -1706,9 +1775,7 @@ impl<T> ops::Deref for Vec<T> {
17061775

17071776
fn deref(&self) -> &[T] {
17081777
unsafe {
1709-
let p = self.buf.ptr();
1710-
assume(!p.is_null());
1711-
slice::from_raw_parts(p, self.len)
1778+
slice::from_raw_parts(self.as_ptr(), self.len)
17121779
}
17131780
}
17141781
}
@@ -1717,9 +1784,7 @@ impl<T> ops::Deref for Vec<T> {
17171784
impl<T> ops::DerefMut for Vec<T> {
17181785
fn deref_mut(&mut self) -> &mut [T] {
17191786
unsafe {
1720-
let ptr = self.buf.ptr();
1721-
assume(!ptr.is_null());
1722-
slice::from_raw_parts_mut(ptr, self.len)
1787+
slice::from_raw_parts_mut(self.as_mut_ptr(), self.len)
17231788
}
17241789
}
17251790
}
@@ -1754,7 +1819,6 @@ impl<T> IntoIterator for Vec<T> {
17541819
fn into_iter(mut self) -> IntoIter<T> {
17551820
unsafe {
17561821
let begin = self.as_mut_ptr();
1757-
assume(!begin.is_null());
17581822
let end = if mem::size_of::<T>() == 0 {
17591823
arith_offset(begin as *const i8, self.len() as isize) as *const T
17601824
} else {

0 commit comments

Comments
 (0)