Skip to content

Commit 31d575b

Browse files
committed
Add Vec::as_non_null
1 parent 3394557 commit 31d575b

File tree

1 file changed

+69
-2
lines changed

1 file changed

+69
-2
lines changed

alloc/src/vec/mod.rs

+69-2
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,8 @@ impl<T, A: Allocator> Vec<T, A> {
15841584
///
15851585
/// This method guarantees that for the purpose of the aliasing model, this method
15861586
/// does not materialize a reference to the underlying slice, and thus the returned pointer
1587-
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
1587+
/// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`],
1588+
/// and [`as_non_null`].
15881589
/// Note that calling other methods that materialize mutable references to the slice,
15891590
/// or mutable references to specific elements you are planning on accessing through this pointer,
15901591
/// as well as writing to those elements, may still invalidate this pointer.
@@ -1621,6 +1622,7 @@ impl<T, A: Allocator> Vec<T, A> {
16211622
///
16221623
/// [`as_mut_ptr`]: Vec::as_mut_ptr
16231624
/// [`as_ptr`]: Vec::as_ptr
1625+
/// [`as_non_null`]: Vec::as_non_null
16241626
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
16251627
#[rustc_never_returns_null_ptr]
16261628
#[inline]
@@ -1640,7 +1642,8 @@ impl<T, A: Allocator> Vec<T, A> {
16401642
///
16411643
/// This method guarantees that for the purpose of the aliasing model, this method
16421644
/// does not materialize a reference to the underlying slice, and thus the returned pointer
1643-
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
1645+
/// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`],
1646+
/// and [`as_non_null`].
16441647
/// Note that calling other methods that materialize references to the slice,
16451648
/// or references to specific elements you are planning on accessing through this pointer,
16461649
/// may still invalidate this pointer.
@@ -1680,6 +1683,7 @@ impl<T, A: Allocator> Vec<T, A> {
16801683
///
16811684
/// [`as_mut_ptr`]: Vec::as_mut_ptr
16821685
/// [`as_ptr`]: Vec::as_ptr
1686+
/// [`as_non_null`]: Vec::as_non_null
16831687
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
16841688
#[rustc_never_returns_null_ptr]
16851689
#[inline]
@@ -1689,6 +1693,69 @@ impl<T, A: Allocator> Vec<T, A> {
16891693
self.buf.ptr()
16901694
}
16911695

1696+
/// Returns a `NonNull` pointer to the vector's buffer, or a dangling
1697+
/// `NonNull` pointer valid for zero sized reads if the vector didn't allocate.
1698+
///
1699+
/// The caller must ensure that the vector outlives the pointer this
1700+
/// function returns, or else it will end up dangling.
1701+
/// Modifying the vector may cause its buffer to be reallocated,
1702+
/// which would also make any pointers to it invalid.
1703+
///
1704+
/// This method guarantees that for the purpose of the aliasing model, this method
1705+
/// does not materialize a reference to the underlying slice, and thus the returned pointer
1706+
/// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`],
1707+
/// and [`as_non_null`].
1708+
/// Note that calling other methods that materialize references to the slice,
1709+
/// or references to specific elements you are planning on accessing through this pointer,
1710+
/// may still invalidate this pointer.
1711+
/// See the second example below for how this guarantee can be used.
1712+
///
1713+
/// # Examples
1714+
///
1715+
/// ```
1716+
/// #![feature(box_vec_non_null)]
1717+
///
1718+
/// // Allocate vector big enough for 4 elements.
1719+
/// let size = 4;
1720+
/// let mut x: Vec<i32> = Vec::with_capacity(size);
1721+
/// let x_ptr = x.as_non_null();
1722+
///
1723+
/// // Initialize elements via raw pointer writes, then set length.
1724+
/// unsafe {
1725+
/// for i in 0..size {
1726+
/// x_ptr.add(i).write(i as i32);
1727+
/// }
1728+
/// x.set_len(size);
1729+
/// }
1730+
/// assert_eq!(&*x, &[0, 1, 2, 3]);
1731+
/// ```
1732+
///
1733+
/// Due to the aliasing guarantee, the following code is legal:
1734+
///
1735+
/// ```rust
1736+
/// #![feature(box_vec_non_null)]
1737+
///
1738+
/// unsafe {
1739+
/// let mut v = vec![0];
1740+
/// let ptr1 = v.as_non_null();
1741+
/// ptr1.write(1);
1742+
/// let ptr2 = v.as_non_null();
1743+
/// ptr2.write(2);
1744+
/// // Notably, the write to `ptr2` did *not* invalidate `ptr1`:
1745+
/// ptr1.write(3);
1746+
/// }
1747+
/// ```
1748+
///
1749+
/// [`as_mut_ptr`]: Vec::as_mut_ptr
1750+
/// [`as_ptr`]: Vec::as_ptr
1751+
/// [`as_non_null`]: Vec::as_non_null
1752+
#[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
1753+
#[inline]
1754+
pub fn as_non_null(&mut self) -> NonNull<T> {
1755+
// SAFETY: A `Vec` always has a non-null pointer.
1756+
unsafe { NonNull::new_unchecked(self.as_mut_ptr()) }
1757+
}
1758+
16921759
/// Returns a reference to the underlying allocator.
16931760
#[unstable(feature = "allocator_api", issue = "32838")]
16941761
#[inline]

0 commit comments

Comments
 (0)