Skip to content

Commit bcc8544

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 506f22b commit bcc8544

8 files changed

+101
-129
lines changed

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
#![feature(const_option)]
115115
#![feature(const_pin)]
116116
#![feature(const_size_of_val)]
117+
#![feature(const_vec_string_slice)]
117118
#![feature(core_intrinsics)]
118119
#![feature(deprecated_suggestion)]
119120
#![feature(deref_pure_trait)]

library/alloc/src/raw_vec.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ impl<T, A: Allocator> RawVec<T, A> {
280280
/// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
281281
/// be careful.
282282
#[inline]
283-
pub fn ptr(&self) -> *mut T {
283+
pub const fn ptr(&self) -> *mut T {
284284
self.inner.ptr()
285285
}
286286

@@ -293,7 +293,7 @@ impl<T, A: Allocator> RawVec<T, A> {
293293
///
294294
/// This will always be `usize::MAX` if `T` is zero-sized.
295295
#[inline]
296-
pub fn capacity(&self) -> usize {
296+
pub const fn capacity(&self) -> usize {
297297
self.inner.capacity(size_of::<T>())
298298
}
299299

@@ -488,8 +488,8 @@ impl<A: Allocator> RawVecInner<A> {
488488
}
489489

490490
#[inline]
491-
fn ptr<T>(&self) -> *mut T {
492-
self.non_null::<T>().as_ptr()
491+
const fn ptr<T>(&self) -> *mut T {
492+
self.ptr.as_ptr() as _
493493
}
494494

495495
#[inline]
@@ -498,7 +498,7 @@ impl<A: Allocator> RawVecInner<A> {
498498
}
499499

500500
#[inline]
501-
fn capacity(&self, elem_size: usize) -> usize {
501+
const fn capacity(&self, elem_size: usize) -> usize {
502502
if elem_size == 0 { usize::MAX } else { self.cap.0 }
503503
}
504504

library/alloc/src/string.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,8 @@ impl String {
10591059
#[inline]
10601060
#[must_use = "`self` will be dropped if the result is not used"]
10611061
#[stable(feature = "rust1", since = "1.0.0")]
1062-
pub fn into_bytes(self) -> Vec<u8> {
1062+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1063+
pub const fn into_bytes(self) -> Vec<u8> {
10631064
self.vec
10641065
}
10651066

@@ -1076,8 +1077,9 @@ impl String {
10761077
#[must_use]
10771078
#[stable(feature = "string_as_str", since = "1.7.0")]
10781079
#[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")]
1079-
pub fn as_str(&self) -> &str {
1080-
self
1080+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1081+
pub const fn as_str(&self) -> &str {
1082+
unsafe { str::from_utf8_unchecked(self.vec.as_slice()) }
10811083
}
10821084

10831085
/// Converts a `String` into a mutable string slice.
@@ -1097,7 +1099,7 @@ impl String {
10971099
#[stable(feature = "string_as_str", since = "1.7.0")]
10981100
#[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")]
10991101
pub fn as_mut_str(&mut self) -> &mut str {
1100-
self
1102+
unsafe { str::from_utf8_unchecked_mut(&mut self.vec) }
11011103
}
11021104

11031105
/// Appends a given string slice onto the end of this `String`.
@@ -1168,7 +1170,8 @@ impl String {
11681170
#[inline]
11691171
#[must_use]
11701172
#[stable(feature = "rust1", since = "1.0.0")]
1171-
pub fn capacity(&self) -> usize {
1173+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1174+
pub const fn capacity(&self) -> usize {
11721175
self.vec.capacity()
11731176
}
11741177

@@ -1431,8 +1434,9 @@ impl String {
14311434
#[inline]
14321435
#[must_use]
14331436
#[stable(feature = "rust1", since = "1.0.0")]
1434-
pub fn as_bytes(&self) -> &[u8] {
1435-
&self.vec
1437+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1438+
pub const fn as_bytes(&self) -> &[u8] {
1439+
self.vec.as_slice()
14361440
}
14371441

14381442
/// Shortens this `String` to the specified length.
@@ -1805,8 +1809,9 @@ impl String {
18051809
#[inline]
18061810
#[must_use]
18071811
#[stable(feature = "rust1", since = "1.0.0")]
1812+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
18081813
#[rustc_confusables("length", "size")]
1809-
pub fn len(&self) -> usize {
1814+
pub const fn len(&self) -> usize {
18101815
self.vec.len()
18111816
}
18121817

@@ -1824,7 +1829,8 @@ impl String {
18241829
#[inline]
18251830
#[must_use]
18261831
#[stable(feature = "rust1", since = "1.0.0")]
1827-
pub fn is_empty(&self) -> bool {
1832+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1833+
pub const fn is_empty(&self) -> bool {
18281834
self.len() == 0
18291835
}
18301836

@@ -2565,7 +2571,7 @@ impl ops::Deref for String {
25652571

25662572
#[inline]
25672573
fn deref(&self) -> &str {
2568-
unsafe { str::from_utf8_unchecked(&self.vec) }
2574+
self.as_str()
25692575
}
25702576
}
25712577

@@ -2576,7 +2582,7 @@ unsafe impl ops::DerefPure for String {}
25762582
impl ops::DerefMut for String {
25772583
#[inline]
25782584
fn deref_mut(&mut self) -> &mut str {
2579-
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
2585+
self.as_mut_str()
25802586
}
25812587
}
25822588

library/alloc/src/vec/mod.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -1240,7 +1240,8 @@ impl<T, A: Allocator> Vec<T, A> {
12401240
/// ```
12411241
#[inline]
12421242
#[stable(feature = "rust1", since = "1.0.0")]
1243-
pub fn capacity(&self) -> usize {
1243+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1244+
pub const fn capacity(&self) -> usize {
12441245
self.buf.capacity()
12451246
}
12461247

@@ -1548,8 +1549,9 @@ impl<T, A: Allocator> Vec<T, A> {
15481549
#[inline]
15491550
#[stable(feature = "vec_as_slice", since = "1.7.0")]
15501551
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_slice")]
1551-
pub fn as_slice(&self) -> &[T] {
1552-
self
1552+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1553+
pub const fn as_slice(&self) -> &[T] {
1554+
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
15531555
}
15541556

15551557
/// Extracts a mutable slice of the entire vector.
@@ -1567,7 +1569,7 @@ impl<T, A: Allocator> Vec<T, A> {
15671569
#[stable(feature = "vec_as_slice", since = "1.7.0")]
15681570
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_mut_slice")]
15691571
pub fn as_mut_slice(&mut self) -> &mut [T] {
1570-
self
1572+
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
15711573
}
15721574

15731575
/// Returns a raw pointer to the vector's buffer, or a dangling raw pointer
@@ -1622,9 +1624,10 @@ impl<T, A: Allocator> Vec<T, A> {
16221624
/// [`as_mut_ptr`]: Vec::as_mut_ptr
16231625
/// [`as_ptr`]: Vec::as_ptr
16241626
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
1627+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
16251628
#[rustc_never_returns_null_ptr]
16261629
#[inline]
1627-
pub fn as_ptr(&self) -> *const T {
1630+
pub const fn as_ptr(&self) -> *const T {
16281631
// We shadow the slice method of the same name to avoid going through
16291632
// `deref`, which creates an intermediate reference.
16301633
self.buf.ptr()
@@ -2561,8 +2564,9 @@ impl<T, A: Allocator> Vec<T, A> {
25612564
/// ```
25622565
#[inline]
25632566
#[stable(feature = "rust1", since = "1.0.0")]
2567+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
25642568
#[rustc_confusables("length", "size")]
2565-
pub fn len(&self) -> usize {
2569+
pub const fn len(&self) -> usize {
25662570
self.len
25672571
}
25682572

@@ -2579,7 +2583,8 @@ impl<T, A: Allocator> Vec<T, A> {
25792583
/// ```
25802584
#[stable(feature = "rust1", since = "1.0.0")]
25812585
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_is_empty")]
2582-
pub fn is_empty(&self) -> bool {
2586+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
2587+
pub const fn is_empty(&self) -> bool {
25832588
self.len() == 0
25842589
}
25852590

@@ -3130,15 +3135,15 @@ impl<T, A: Allocator> ops::Deref for Vec<T, A> {
31303135

31313136
#[inline]
31323137
fn deref(&self) -> &[T] {
3133-
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
3138+
self.as_slice()
31343139
}
31353140
}
31363141

31373142
#[stable(feature = "rust1", since = "1.0.0")]
31383143
impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
31393144
#[inline]
31403145
fn deref_mut(&mut self) -> &mut [T] {
3141-
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
3146+
self.as_mut_slice()
31423147
}
31433148
}
31443149

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

+31-47
Original file line numberDiff line numberDiff line change
@@ -5,66 +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 _6: 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-
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>) {
1818
debug self => _3;
1919
let mut _4: std::ptr::NonNull<u8>;
20-
scope 6 (inlined Unique::<u8>::cast::<u8>) {
20+
scope 6 (inlined Unique::<u8>::as_ptr) {
2121
debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
2222
debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
23-
scope 7 (inlined NonNull::<u8>::cast::<u8>) {
23+
scope 7 (inlined NonNull::<u8>::as_ptr) {
2424
debug self => _4;
25-
scope 8 (inlined NonNull::<u8>::as_ptr) {
26-
debug self => _4;
27-
let mut _5: *const u8;
28-
}
29-
}
30-
}
31-
scope 9 (inlined #[track_caller] <Unique<u8> as Into<NonNull<u8>>>::into) {
32-
debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
33-
debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
34-
scope 10 (inlined <NonNull<u8> as From<Unique<u8>>>::from) {
35-
debug ((unique: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
36-
debug ((unique: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
37-
scope 11 (inlined Unique::<u8>::as_non_null_ptr) {
38-
debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
39-
debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
40-
}
25+
let mut _5: *const u8;
4126
}
4227
}
4328
}
44-
scope 12 (inlined NonNull::<u8>::as_ptr) {
45-
debug self => _4;
46-
}
47-
}
48-
}
49-
}
50-
scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) {
51-
debug data => _5;
52-
debug len => _6;
53-
let _7: *const [u8];
54-
scope 14 (inlined core::ub_checks::check_language_ub) {
55-
scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
5629
}
5730
}
58-
scope 16 (inlined std::mem::size_of::<u8>) {
59-
}
60-
scope 17 (inlined align_of::<u8>) {
61-
}
62-
scope 18 (inlined slice_from_raw_parts::<u8>) {
31+
scope 8 (inlined std::slice::from_raw_parts::<'_, u8>) {
6332
debug data => _5;
6433
debug len => _6;
65-
scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
66-
debug data_pointer => _5;
67-
debug metadata => _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+
}
6850
}
6951
}
7052
}
@@ -75,8 +57,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
7557
_2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
7658
StorageLive(_3);
7759
_3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
60+
StorageLive(_4);
7861
_4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
7962
_5 = copy (_4.0: *const u8);
63+
StorageDead(_4);
8064
StorageDead(_3);
8165
StorageDead(_2);
8266
StorageLive(_6);

0 commit comments

Comments
 (0)