Skip to content

Commit 9ac23f5

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 b7b9453 commit 9ac23f5

File tree

5 files changed

+38
-34
lines changed

5 files changed

+38
-34
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
@@ -1057,7 +1057,8 @@ impl String {
10571057
#[inline]
10581058
#[must_use = "`self` will be dropped if the result is not used"]
10591059
#[stable(feature = "rust1", since = "1.0.0")]
1060-
pub fn into_bytes(self) -> Vec<u8> {
1060+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1061+
pub const fn into_bytes(self) -> Vec<u8> {
10611062
self.vec
10621063
}
10631064

@@ -1073,8 +1074,9 @@ impl String {
10731074
#[inline]
10741075
#[must_use]
10751076
#[stable(feature = "string_as_str", since = "1.7.0")]
1076-
pub fn as_str(&self) -> &str {
1077-
self
1077+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1078+
pub const fn as_str(&self) -> &str {
1079+
unsafe { str::from_utf8_unchecked(self.vec.as_slice()) }
10781080
}
10791081

10801082
/// Converts a `String` into a mutable string slice.
@@ -1093,7 +1095,7 @@ impl String {
10931095
#[must_use]
10941096
#[stable(feature = "string_as_str", since = "1.7.0")]
10951097
pub fn as_mut_str(&mut self) -> &mut str {
1096-
self
1098+
unsafe { str::from_utf8_unchecked_mut(&mut self.vec) }
10971099
}
10981100

10991101
/// Appends a given string slice onto the end of this `String`.
@@ -1163,7 +1165,8 @@ impl String {
11631165
#[inline]
11641166
#[must_use]
11651167
#[stable(feature = "rust1", since = "1.0.0")]
1166-
pub fn capacity(&self) -> usize {
1168+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1169+
pub const fn capacity(&self) -> usize {
11671170
self.vec.capacity()
11681171
}
11691172

@@ -1426,8 +1429,9 @@ impl String {
14261429
#[inline]
14271430
#[must_use]
14281431
#[stable(feature = "rust1", since = "1.0.0")]
1429-
pub fn as_bytes(&self) -> &[u8] {
1430-
&self.vec
1432+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1433+
pub const fn as_bytes(&self) -> &[u8] {
1434+
self.vec.as_slice()
14311435
}
14321436

14331437
/// Shortens this `String` to the specified length.
@@ -1799,8 +1803,9 @@ impl String {
17991803
#[inline]
18001804
#[must_use]
18011805
#[stable(feature = "rust1", since = "1.0.0")]
1806+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
18021807
#[rustc_confusables("length", "size")]
1803-
pub fn len(&self) -> usize {
1808+
pub const fn len(&self) -> usize {
18041809
self.vec.len()
18051810
}
18061811

@@ -1818,7 +1823,8 @@ impl String {
18181823
#[inline]
18191824
#[must_use]
18201825
#[stable(feature = "rust1", since = "1.0.0")]
1821-
pub fn is_empty(&self) -> bool {
1826+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1827+
pub const fn is_empty(&self) -> bool {
18221828
self.len() == 0
18231829
}
18241830

@@ -2559,7 +2565,7 @@ impl ops::Deref for String {
25592565

25602566
#[inline]
25612567
fn deref(&self) -> &str {
2562-
unsafe { str::from_utf8_unchecked(&self.vec) }
2568+
self.as_str()
25632569
}
25642570
}
25652571

@@ -2570,7 +2576,7 @@ unsafe impl ops::DerefPure for String {}
25702576
impl ops::DerefMut for String {
25712577
#[inline]
25722578
fn deref_mut(&mut self) -> &mut str {
2573-
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
2579+
self.as_mut_str()
25742580
}
25752581
}
25762582

library/alloc/src/vec/mod.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,8 @@ impl<T, A: Allocator> Vec<T, A> {
12381238
/// ```
12391239
#[inline]
12401240
#[stable(feature = "rust1", since = "1.0.0")]
1241-
pub fn capacity(&self) -> usize {
1241+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1242+
pub const fn capacity(&self) -> usize {
12421243
self.buf.capacity()
12431244
}
12441245

@@ -1545,8 +1546,9 @@ impl<T, A: Allocator> Vec<T, A> {
15451546
/// ```
15461547
#[inline]
15471548
#[stable(feature = "vec_as_slice", since = "1.7.0")]
1548-
pub fn as_slice(&self) -> &[T] {
1549-
self
1549+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
1550+
pub const fn as_slice(&self) -> &[T] {
1551+
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
15501552
}
15511553

15521554
/// Extracts a mutable slice of the entire vector.
@@ -1563,7 +1565,7 @@ impl<T, A: Allocator> Vec<T, A> {
15631565
#[inline]
15641566
#[stable(feature = "vec_as_slice", since = "1.7.0")]
15651567
pub fn as_mut_slice(&mut self) -> &mut [T] {
1566-
self
1568+
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
15671569
}
15681570

15691571
/// Returns a raw pointer to the vector's buffer, or a dangling raw pointer
@@ -1618,9 +1620,10 @@ impl<T, A: Allocator> Vec<T, A> {
16181620
/// [`as_mut_ptr`]: Vec::as_mut_ptr
16191621
/// [`as_ptr`]: Vec::as_ptr
16201622
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
1623+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
16211624
#[rustc_never_returns_null_ptr]
16221625
#[inline]
1623-
pub fn as_ptr(&self) -> *const T {
1626+
pub const fn as_ptr(&self) -> *const T {
16241627
// We shadow the slice method of the same name to avoid going through
16251628
// `deref`, which creates an intermediate reference.
16261629
self.buf.ptr()
@@ -2556,8 +2559,9 @@ impl<T, A: Allocator> Vec<T, A> {
25562559
/// ```
25572560
#[inline]
25582561
#[stable(feature = "rust1", since = "1.0.0")]
2562+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
25592563
#[rustc_confusables("length", "size")]
2560-
pub fn len(&self) -> usize {
2564+
pub const fn len(&self) -> usize {
25612565
self.len
25622566
}
25632567

@@ -2573,7 +2577,8 @@ impl<T, A: Allocator> Vec<T, A> {
25732577
/// assert!(!v.is_empty());
25742578
/// ```
25752579
#[stable(feature = "rust1", since = "1.0.0")]
2576-
pub fn is_empty(&self) -> bool {
2580+
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
2581+
pub const fn is_empty(&self) -> bool {
25772582
self.len() == 0
25782583
}
25792584

@@ -3123,15 +3128,15 @@ impl<T, A: Allocator> ops::Deref for Vec<T, A> {
31233128

31243129
#[inline]
31253130
fn deref(&self) -> &[T] {
3126-
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
3131+
self.as_slice()
31273132
}
31283133
}
31293134

31303135
#[stable(feature = "rust1", since = "1.0.0")]
31313136
impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
31323137
#[inline]
31333138
fn deref_mut(&mut self) -> &mut [T] {
3134-
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
3139+
self.as_mut_slice()
31353140
}
31363141
}
31373142

tests/ui/consts/issue-94675.stderr

+1-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
error[E0015]: cannot call non-const fn `Vec::<u32>::len` in constant functions
2-
--> $DIR/issue-94675.rs:11:27
3-
|
4-
LL | self.bar[0] = baz.len();
5-
| ^^^^^
6-
|
7-
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
8-
91
error[E0015]: cannot call non-const operator in constant functions
102
--> $DIR/issue-94675.rs:11:17
113
|
@@ -20,6 +12,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
2012
LL + #![feature(effects)]
2113
|
2214

23-
error: aborting due to 2 previous errors
15+
error: aborting due to 1 previous error
2416

2517
For more information about this error, try `rustc --explain E0015`.

0 commit comments

Comments
 (0)