Skip to content

Commit 52f9d5d

Browse files
committed
liballoc: introduce String, Vec const-slicing
This change `const`-qualifies many methods on Vec and String, notably `as_slice`, `as_str`, `len`. These changes are made behind the unstable feature flag `const_vec_string_slice` with the following tracking issue: #129041
1 parent a32d4a0 commit 52f9d5d

8 files changed

+109
-149
lines changed

Diff for: library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
#![feature(const_pin)]
118118
#![feature(const_refs_to_cell)]
119119
#![feature(const_size_of_val)]
120+
#![feature(const_vec_string_slice)]
120121
#![feature(core_intrinsics)]
121122
#![feature(deprecated_suggestion)]
122123
#![feature(deref_pure_trait)]

Diff for: library/alloc/src/raw_vec.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ impl<T, A: Allocator> RawVec<T, A> {
293293
/// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
294294
/// be careful.
295295
#[inline]
296-
pub fn ptr(&self) -> *mut T {
296+
pub const fn ptr(&self) -> *mut T {
297297
self.inner.ptr()
298298
}
299299

@@ -306,7 +306,7 @@ impl<T, A: Allocator> RawVec<T, A> {
306306
///
307307
/// This will always be `usize::MAX` if `T` is zero-sized.
308308
#[inline]
309-
pub fn capacity(&self) -> usize {
309+
pub const fn capacity(&self) -> usize {
310310
self.inner.capacity(size_of::<T>())
311311
}
312312

@@ -501,8 +501,8 @@ impl<A: Allocator> RawVecInner<A> {
501501
}
502502

503503
#[inline]
504-
fn ptr<T>(&self) -> *mut T {
505-
self.non_null::<T>().as_ptr()
504+
const fn ptr<T>(&self) -> *mut T {
505+
self.ptr.as_ptr() as _
506506
}
507507

508508
#[inline]
@@ -511,7 +511,7 @@ impl<A: Allocator> RawVecInner<A> {
511511
}
512512

513513
#[inline]
514-
fn capacity(&self, elem_size: usize) -> usize {
514+
const fn capacity(&self, elem_size: usize) -> usize {
515515
if elem_size == 0 { usize::MAX } else { self.cap.0 }
516516
}
517517

Diff for: library/alloc/src/string.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,8 @@ impl String {
10061006
#[inline]
10071007
#[must_use = "`self` will be dropped if the result is not used"]
10081008
#[stable(feature = "rust1", since = "1.0.0")]
1009-
pub fn into_bytes(self) -> Vec<u8> {
1009+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1010+
pub const fn into_bytes(self) -> Vec<u8> {
10101011
self.vec
10111012
}
10121013

@@ -1022,8 +1023,9 @@ impl String {
10221023
#[inline]
10231024
#[must_use]
10241025
#[stable(feature = "string_as_str", since = "1.7.0")]
1025-
pub fn as_str(&self) -> &str {
1026-
self
1026+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1027+
pub const fn as_str(&self) -> &str {
1028+
unsafe { str::from_utf8_unchecked(self.vec.as_slice()) }
10271029
}
10281030

10291031
/// Converts a `String` into a mutable string slice.
@@ -1042,7 +1044,7 @@ impl String {
10421044
#[must_use]
10431045
#[stable(feature = "string_as_str", since = "1.7.0")]
10441046
pub fn as_mut_str(&mut self) -> &mut str {
1045-
self
1047+
unsafe { str::from_utf8_unchecked_mut(&mut self.vec) }
10461048
}
10471049

10481050
/// Appends a given string slice onto the end of this `String`.
@@ -1112,7 +1114,8 @@ impl String {
11121114
#[inline]
11131115
#[must_use]
11141116
#[stable(feature = "rust1", since = "1.0.0")]
1115-
pub fn capacity(&self) -> usize {
1117+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1118+
pub const fn capacity(&self) -> usize {
11161119
self.vec.capacity()
11171120
}
11181121

@@ -1375,8 +1378,9 @@ impl String {
13751378
#[inline]
13761379
#[must_use]
13771380
#[stable(feature = "rust1", since = "1.0.0")]
1378-
pub fn as_bytes(&self) -> &[u8] {
1379-
&self.vec
1381+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1382+
pub const fn as_bytes(&self) -> &[u8] {
1383+
self.vec.as_slice()
13801384
}
13811385

13821386
/// Shortens this `String` to the specified length.
@@ -1748,8 +1752,9 @@ impl String {
17481752
#[inline]
17491753
#[must_use]
17501754
#[stable(feature = "rust1", since = "1.0.0")]
1755+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
17511756
#[rustc_confusables("length", "size")]
1752-
pub fn len(&self) -> usize {
1757+
pub const fn len(&self) -> usize {
17531758
self.vec.len()
17541759
}
17551760

@@ -1767,7 +1772,8 @@ impl String {
17671772
#[inline]
17681773
#[must_use]
17691774
#[stable(feature = "rust1", since = "1.0.0")]
1770-
pub fn is_empty(&self) -> bool {
1775+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1776+
pub const fn is_empty(&self) -> bool {
17711777
self.len() == 0
17721778
}
17731779

@@ -2484,7 +2490,7 @@ impl ops::Deref for String {
24842490

24852491
#[inline]
24862492
fn deref(&self) -> &str {
2487-
unsafe { str::from_utf8_unchecked(&self.vec) }
2493+
self.as_str()
24882494
}
24892495
}
24902496

@@ -2495,7 +2501,7 @@ unsafe impl ops::DerefPure for String {}
24952501
impl ops::DerefMut for String {
24962502
#[inline]
24972503
fn deref_mut(&mut self) -> &mut str {
2498-
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
2504+
self.as_mut_str()
24992505
}
25002506
}
25012507

Diff for: library/alloc/src/vec/mod.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,8 @@ impl<T, A: Allocator> Vec<T, A> {
946946
/// ```
947947
#[inline]
948948
#[stable(feature = "rust1", since = "1.0.0")]
949-
pub fn capacity(&self) -> usize {
949+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
950+
pub const fn capacity(&self) -> usize {
950951
self.buf.capacity()
951952
}
952953

@@ -1253,8 +1254,9 @@ impl<T, A: Allocator> Vec<T, A> {
12531254
/// ```
12541255
#[inline]
12551256
#[stable(feature = "vec_as_slice", since = "1.7.0")]
1256-
pub fn as_slice(&self) -> &[T] {
1257-
self
1257+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1258+
pub const fn as_slice(&self) -> &[T] {
1259+
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
12581260
}
12591261

12601262
/// Extracts a mutable slice of the entire vector.
@@ -1271,7 +1273,7 @@ impl<T, A: Allocator> Vec<T, A> {
12711273
#[inline]
12721274
#[stable(feature = "vec_as_slice", since = "1.7.0")]
12731275
pub fn as_mut_slice(&mut self) -> &mut [T] {
1274-
self
1276+
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
12751277
}
12761278

12771279
/// Returns a raw pointer to the vector's buffer, or a dangling raw pointer
@@ -1326,9 +1328,10 @@ impl<T, A: Allocator> Vec<T, A> {
13261328
/// [`as_mut_ptr`]: Vec::as_mut_ptr
13271329
/// [`as_ptr`]: Vec::as_ptr
13281330
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
1331+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
13291332
#[rustc_never_returns_null_ptr]
13301333
#[inline]
1331-
pub fn as_ptr(&self) -> *const T {
1334+
pub const fn as_ptr(&self) -> *const T {
13321335
// We shadow the slice method of the same name to avoid going through
13331336
// `deref`, which creates an intermediate reference.
13341337
self.buf.ptr()
@@ -2262,8 +2265,9 @@ impl<T, A: Allocator> Vec<T, A> {
22622265
/// ```
22632266
#[inline]
22642267
#[stable(feature = "rust1", since = "1.0.0")]
2268+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
22652269
#[rustc_confusables("length", "size")]
2266-
pub fn len(&self) -> usize {
2270+
pub const fn len(&self) -> usize {
22672271
self.len
22682272
}
22692273

@@ -2279,7 +2283,8 @@ impl<T, A: Allocator> Vec<T, A> {
22792283
/// assert!(!v.is_empty());
22802284
/// ```
22812285
#[stable(feature = "rust1", since = "1.0.0")]
2282-
pub fn is_empty(&self) -> bool {
2286+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
2287+
pub const fn is_empty(&self) -> bool {
22832288
self.len() == 0
22842289
}
22852290

@@ -2828,15 +2833,15 @@ impl<T, A: Allocator> ops::Deref for Vec<T, A> {
28282833

28292834
#[inline]
28302835
fn deref(&self) -> &[T] {
2831-
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
2836+
self.as_slice()
28322837
}
28332838
}
28342839

28352840
#[stable(feature = "rust1", since = "1.0.0")]
28362841
impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
28372842
#[inline]
28382843
fn deref_mut(&mut self) -> &mut [T] {
2839-
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
2844+
self.as_mut_slice()
28402845
}
28412846
}
28422847

Diff for: tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir

+35-57
Original file line numberDiff line numberDiff line change
@@ -5,67 +5,48 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
55
let mut _0: &[u8];
66
scope 1 (inlined <Vec<u8> as Deref>::deref) {
77
debug self => _1;
8-
let mut _7: usize;
9-
scope 2 (inlined Vec::<u8>::as_ptr) {
8+
scope 2 (inlined Vec::<u8>::as_slice) {
109
debug self => _1;
11-
let mut _2: &alloc::raw_vec::RawVec<u8>;
12-
scope 3 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
13-
debug self => _2;
14-
let mut _3: &alloc::raw_vec::RawVecInner;
15-
scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
16-
debug self => _3;
17-
let mut _6: std::ptr::NonNull<u8>;
18-
scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
10+
let mut _6: usize;
11+
scope 3 (inlined Vec::<u8>::as_ptr) {
12+
debug self => _1;
13+
let mut _2: &alloc::raw_vec::RawVec<u8>;
14+
scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
15+
debug self => _2;
16+
let mut _3: &alloc::raw_vec::RawVecInner;
17+
scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
1918
debug self => _3;
2019
let mut _4: std::ptr::NonNull<u8>;
21-
scope 6 (inlined Unique::<u8>::cast::<u8>) {
20+
scope 6 (inlined Unique::<u8>::as_ptr) {
2221
debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
2322
debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
24-
scope 7 (inlined NonNull::<u8>::cast::<u8>) {
23+
scope 7 (inlined NonNull::<u8>::as_ptr) {
2524
debug self => _4;
26-
scope 8 (inlined NonNull::<u8>::as_ptr) {
27-
debug self => _4;
28-
let mut _5: *const u8;
29-
}
30-
}
31-
}
32-
scope 9 (inlined #[track_caller] <Unique<u8> as Into<NonNull<u8>>>::into) {
33-
debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
34-
debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
35-
scope 10 (inlined <NonNull<u8> as From<Unique<u8>>>::from) {
36-
debug ((unique: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
37-
debug ((unique: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
38-
scope 11 (inlined Unique::<u8>::as_non_null_ptr) {
39-
debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
40-
debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
41-
}
25+
let mut _5: *const u8;
4226
}
4327
}
4428
}
45-
scope 12 (inlined NonNull::<u8>::as_ptr) {
46-
debug self => _6;
47-
}
4829
}
4930
}
50-
}
51-
scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) {
52-
debug data => _5;
53-
debug len => _7;
54-
let _8: *const [u8];
55-
scope 14 (inlined core::ub_checks::check_language_ub) {
56-
scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
57-
}
58-
}
59-
scope 16 (inlined std::mem::size_of::<u8>) {
60-
}
61-
scope 17 (inlined align_of::<u8>) {
62-
}
63-
scope 18 (inlined slice_from_raw_parts::<u8>) {
31+
scope 8 (inlined std::slice::from_raw_parts::<'_, u8>) {
6432
debug data => _5;
65-
debug len => _7;
66-
scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
67-
debug data_pointer => _5;
68-
debug metadata => _7;
33+
debug len => _6;
34+
let _7: *const [u8];
35+
scope 9 (inlined core::ub_checks::check_language_ub) {
36+
scope 10 (inlined core::ub_checks::check_language_ub::runtime) {
37+
}
38+
}
39+
scope 11 (inlined std::mem::size_of::<u8>) {
40+
}
41+
scope 12 (inlined align_of::<u8>) {
42+
}
43+
scope 13 (inlined slice_from_raw_parts::<u8>) {
44+
debug data => _5;
45+
debug len => _6;
46+
scope 14 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
47+
debug data_pointer => _5;
48+
debug metadata => _6;
49+
}
6950
}
7051
}
7152
}
@@ -76,22 +57,19 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
7657
_2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
7758
StorageLive(_3);
7859
_3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
79-
StorageLive(_6);
8060
StorageLive(_4);
8161
_4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
8262
_5 = copy (_4.0: *const u8);
83-
_6 = NonNull::<u8> { pointer: copy _5 };
8463
StorageDead(_4);
85-
StorageDead(_6);
8664
StorageDead(_3);
8765
StorageDead(_2);
66+
StorageLive(_6);
67+
_6 = copy ((*_1).1: usize);
8868
StorageLive(_7);
89-
_7 = copy ((*_1).1: usize);
90-
StorageLive(_8);
91-
_8 = *const [u8] from (copy _5, copy _7);
92-
_0 = &(*_8);
93-
StorageDead(_8);
69+
_7 = *const [u8] from (copy _5, copy _6);
70+
_0 = &(*_7);
9471
StorageDead(_7);
72+
StorageDead(_6);
9573
return;
9674
}
9775
}

0 commit comments

Comments
 (0)