Skip to content

Commit c4af1ae

Browse files
committed
liballoc: introduce String, Vec const-slicing
1 parent a32d4a0 commit c4af1ae

File tree

3 files changed

+139
-8
lines changed

3 files changed

+139
-8
lines changed

library/alloc/src/raw_vec.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,14 @@ impl<T, A: Allocator> RawVec<T, A> {
297297
self.inner.ptr()
298298
}
299299

300+
/// Gets a const raw pointer to the start of the allocation. Note that this is
301+
/// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
302+
/// be careful.
303+
#[inline]
304+
pub const fn ptr_const(&self) -> *mut T {
305+
self.ptr.as_ptr()
306+
}
307+
300308
#[inline]
301309
pub fn non_null(&self) -> NonNull<T> {
302310
self.inner.non_null()

library/alloc/src/string.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,38 @@ impl String {
10231023
#[must_use]
10241024
#[stable(feature = "string_as_str", since = "1.7.0")]
10251025
pub fn as_str(&self) -> &str {
1026-
self
1026+
self.as_str_const()
1027+
}
1028+
1029+
/// Extracts a const string slice containing the entire `String`.
1030+
///
1031+
/// # Examples
1032+
///
1033+
/// ```
1034+
/// # use std::borrow::Cow;
1035+
/// // `Deref`, `AsRef`, and `as_str` are not available in `const` contexts, so this doesn't otherwise work.
1036+
/// const fn cow_str<'c, 's>(c: &Cow<'s, str>) -> &'c str
1037+
/// where 's: 'c {
1038+
/// match c {
1039+
/// Cow::Borrowed(s) => s,
1040+
/// Cow::Owned(s) => s.as_str_const(),
1041+
/// }
1042+
/// }
1043+
///
1044+
/// const STRING: Cow<'static, str> = Cow::Owned(String::new());
1045+
/// const STR: Cow<'static, str> = Cow::Borrowed("foo");
1046+
///
1047+
/// const SLICED_STRING: &'static str = cow_str(&STRING);
1048+
/// const SLICED_STR: &'static str = cow_str(&STR);
1049+
///
1050+
/// assert_eq!(SLICED_STRING, "");
1051+
/// assert_eq!(SLICED_STR, "foo");
1052+
/// ```
1053+
#[inline]
1054+
#[must_use]
1055+
#[unstable(feature = "const_vec_string_slice", issue = "none")]
1056+
pub const fn as_str_const(&self) -> &str {
1057+
unsafe { str::from_utf8_unchecked(self.vec.as_slice_const()) }
10271058
}
10281059

10291060
/// Converts a `String` into a mutable string slice.
@@ -1042,7 +1073,7 @@ impl String {
10421073
#[must_use]
10431074
#[stable(feature = "string_as_str", since = "1.7.0")]
10441075
pub fn as_mut_str(&mut self) -> &mut str {
1045-
self
1076+
unsafe { str::from_utf8_unchecked_mut(&mut self.vec) }
10461077
}
10471078

10481079
/// Appends a given string slice onto the end of this `String`.
@@ -2484,7 +2515,7 @@ impl ops::Deref for String {
24842515

24852516
#[inline]
24862517
fn deref(&self) -> &str {
2487-
unsafe { str::from_utf8_unchecked(&self.vec) }
2518+
self.as_str()
24882519
}
24892520
}
24902521

@@ -2495,7 +2526,7 @@ unsafe impl ops::DerefPure for String {}
24952526
impl ops::DerefMut for String {
24962527
#[inline]
24972528
fn deref_mut(&mut self) -> &mut str {
2498-
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
2529+
self.as_mut_str()
24992530
}
25002531
}
25012532

library/alloc/src/vec/mod.rs

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,37 @@ impl<T, A: Allocator> Vec<T, A> {
12541254
#[inline]
12551255
#[stable(feature = "vec_as_slice", since = "1.7.0")]
12561256
pub fn as_slice(&self) -> &[T] {
1257-
self
1257+
self.as_slice_const()
1258+
}
1259+
1260+
/// Extracts a slice containing the entire vector.
1261+
///
1262+
/// # Examples
1263+
///
1264+
/// ```
1265+
/// # use std::borrow::Cow;
1266+
/// // `Deref`, `AsRef`, and `as_slice` are not available in `const` contexts, so this doesn't otherwise work.
1267+
/// const fn cow_slice<'c, 's>(c: &Cow<'s, [u8]>) -> &'c [u8]
1268+
/// where 's: 'c {
1269+
/// match c {
1270+
/// Cow::Borrowed(s) => s,
1271+
/// Cow::Owned(s) => s.as_slice_const(),
1272+
/// }
1273+
/// }
1274+
///
1275+
/// const VEC: Cow<'static, [u8]> = Cow::Owned(Vec::new());
1276+
/// const SLICE: Cow<'static, [u8]> = Cow::Borrowed(b"foo");
1277+
///
1278+
/// const SLICED_VEC: &'static [u8] = cow_slice(&VEC);
1279+
/// const SLICED_SLICE: &'static [u8] = cow_slice(&SLICE);
1280+
///
1281+
/// assert_eq!(SLICED_VEC, b"");
1282+
/// assert_eq!(SLICED_SLICE, b"foo");
1283+
/// ```
1284+
#[inline]
1285+
#[unstable(feature = "const_vec_string_slice", issue = "none")]
1286+
pub const fn as_slice_const(&self) -> &[T] {
1287+
unsafe { slice::from_raw_parts(self.as_ptr_const(), self.len) }
12581288
}
12591289

12601290
/// Extracts a mutable slice of the entire vector.
@@ -1271,7 +1301,7 @@ impl<T, A: Allocator> Vec<T, A> {
12711301
#[inline]
12721302
#[stable(feature = "vec_as_slice", since = "1.7.0")]
12731303
pub fn as_mut_slice(&mut self) -> &mut [T] {
1274-
self
1304+
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
12751305
}
12761306

12771307
/// Returns a raw pointer to the vector's buffer, or a dangling raw pointer
@@ -1334,6 +1364,68 @@ impl<T, A: Allocator> Vec<T, A> {
13341364
self.buf.ptr()
13351365
}
13361366

1367+
/// Returns a raw pointer to the vector's buffer, or a dangling raw pointer
1368+
/// valid for zero sized reads if the vector didn't allocate.
1369+
///
1370+
/// This is a `const` version of [`as_ptr`].
1371+
///
1372+
/// The caller must ensure that the vector outlives the pointer this
1373+
/// function returns, or else it will end up pointing to garbage.
1374+
/// Modifying the vector may cause its buffer to be reallocated,
1375+
/// which would also make any pointers to it invalid.
1376+
///
1377+
/// The caller must also ensure that the memory the pointer (non-transitively) points to
1378+
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
1379+
/// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`].
1380+
///
1381+
/// This method guarantees that for the purpose of the aliasing model, this method
1382+
/// does not materialize a reference to the underlying slice, and thus the returned pointer
1383+
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
1384+
/// Note that calling other methods that materialize mutable references to the slice,
1385+
/// or mutable references to specific elements you are planning on accessing through this pointer,
1386+
/// as well as writing to those elements, may still invalidate this pointer.
1387+
/// See the second example below for how this guarantee can be used.
1388+
///
1389+
///
1390+
/// # Examples
1391+
///
1392+
/// ```
1393+
/// let x = vec![1, 2, 4];
1394+
/// let x_ptr = x.as_ptr_const();
1395+
///
1396+
/// unsafe {
1397+
/// for i in 0..x.len() {
1398+
/// assert_eq!(*x_ptr.add(i), 1 << i);
1399+
/// }
1400+
/// }
1401+
/// ```
1402+
///
1403+
/// Due to the aliasing guarantee, the following code is legal:
1404+
///
1405+
/// ```rust
1406+
/// unsafe {
1407+
/// let mut v = vec![0, 1, 2];
1408+
/// let ptr1 = v.as_ptr_const();
1409+
/// let _ = ptr1.read();
1410+
/// let ptr2 = v.as_mut_ptr().offset(2);
1411+
/// ptr2.write(2);
1412+
/// // Notably, the write to `ptr2` did *not* invalidate `ptr1`
1413+
/// // because it mutated a different element:
1414+
/// let _ = ptr1.read();
1415+
/// }
1416+
/// ```
1417+
///
1418+
/// [`as_mut_ptr`]: Vec::as_mut_ptr
1419+
/// [`as_ptr_const`]: Vec::as_ptr
1420+
#[rustc_never_returns_null_ptr]
1421+
#[unstable(feature = "const_vec_string_slice", issue = "none")]
1422+
#[inline]
1423+
pub const fn as_ptr_const(&self) -> *const T {
1424+
// We shadow the slice method of the same name to avoid going through
1425+
// `deref`, which creates an intermediate reference.
1426+
self.buf.ptr_const()
1427+
}
1428+
13371429
/// Returns an unsafe mutable pointer to the vector's buffer, or a dangling
13381430
/// raw pointer valid for zero sized reads if the vector didn't allocate.
13391431
///
@@ -2828,15 +2920,15 @@ impl<T, A: Allocator> ops::Deref for Vec<T, A> {
28282920

28292921
#[inline]
28302922
fn deref(&self) -> &[T] {
2831-
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
2923+
self.as_slice()
28322924
}
28332925
}
28342926

28352927
#[stable(feature = "rust1", since = "1.0.0")]
28362928
impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
28372929
#[inline]
28382930
fn deref_mut(&mut self) -> &mut [T] {
2839-
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
2931+
self.as_mut_slice()
28402932
}
28412933
}
28422934

0 commit comments

Comments
 (0)