Skip to content

Commit e7e3261

Browse files
authored
Rollup merge of rust-lang#50863 - oli-obk:const_len, r=SimonSapin,Gankro
Make `[T]::len` and `str::len` const fn r? @gankro
2 parents eb92280 + 2788f66 commit e7e3261

File tree

4 files changed

+72
-16
lines changed

4 files changed

+72
-16
lines changed

src/libcore/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@
119119
#![feature(powerpc_target_feature)]
120120
#![feature(mips_target_feature)]
121121
#![feature(aarch64_target_feature)]
122+
#![feature(const_slice_len)]
123+
#![feature(const_str_as_bytes)]
124+
#![feature(const_str_len)]
122125

123126
#[prelude_import]
124127
#[allow(unused)]

src/libcore/slice/mod.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,16 @@ mod rotate;
5959
mod sort;
6060

6161
#[repr(C)]
62-
struct Repr<T> {
63-
pub data: *const T,
64-
pub len: usize,
62+
union Repr<'a, T: 'a> {
63+
rust: &'a [T],
64+
rust_mut: &'a mut [T],
65+
raw: FatPtr<T>,
66+
}
67+
68+
#[repr(C)]
69+
struct FatPtr<T> {
70+
data: *const T,
71+
len: usize,
6572
}
6673

6774
//
@@ -119,9 +126,10 @@ impl<T> [T] {
119126
/// ```
120127
#[stable(feature = "rust1", since = "1.0.0")]
121128
#[inline]
122-
pub fn len(&self) -> usize {
129+
#[rustc_const_unstable(feature = "const_slice_len")]
130+
pub const fn len(&self) -> usize {
123131
unsafe {
124-
mem::transmute::<&[T], Repr<T>>(self).len
132+
Repr { rust: self }.raw.len
125133
}
126134
}
127135

@@ -135,7 +143,8 @@ impl<T> [T] {
135143
/// ```
136144
#[stable(feature = "rust1", since = "1.0.0")]
137145
#[inline]
138-
pub fn is_empty(&self) -> bool {
146+
#[rustc_const_unstable(feature = "const_slice_len")]
147+
pub const fn is_empty(&self) -> bool {
139148
self.len() == 0
140149
}
141150

@@ -418,7 +427,8 @@ impl<T> [T] {
418427
/// ```
419428
#[stable(feature = "rust1", since = "1.0.0")]
420429
#[inline]
421-
pub fn as_ptr(&self) -> *const T {
430+
#[rustc_const_unstable(feature = "const_slice_as_ptr")]
431+
pub const fn as_ptr(&self) -> *const T {
422432
self as *const [T] as *const T
423433
}
424434

@@ -3856,8 +3866,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> {
38563866
/// ```
38573867
#[inline]
38583868
#[stable(feature = "rust1", since = "1.0.0")]
3859-
pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] {
3860-
mem::transmute(Repr { data: p, len: len })
3869+
pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
3870+
Repr { raw: FatPtr { data, len } }.rust
38613871
}
38623872

38633873
/// Performs the same functionality as `from_raw_parts`, except that a mutable
@@ -3869,8 +3879,8 @@ pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] {
38693879
/// `from_raw_parts`.
38703880
#[inline]
38713881
#[stable(feature = "rust1", since = "1.0.0")]
3872-
pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
3873-
mem::transmute(Repr { data: p, len: len })
3882+
pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
3883+
Repr { raw: FatPtr { data, len} }.rust_mut
38743884
}
38753885

38763886
/// Converts a reference to T into a slice of length 1 (without copying).

src/libcore/str/mod.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,7 +2166,8 @@ impl str {
21662166
/// ```
21672167
#[stable(feature = "rust1", since = "1.0.0")]
21682168
#[inline]
2169-
pub fn len(&self) -> usize {
2169+
#[rustc_const_unstable(feature = "const_str_len")]
2170+
pub const fn len(&self) -> usize {
21702171
self.as_bytes().len()
21712172
}
21722173

@@ -2185,7 +2186,8 @@ impl str {
21852186
/// ```
21862187
#[inline]
21872188
#[stable(feature = "rust1", since = "1.0.0")]
2188-
pub fn is_empty(&self) -> bool {
2189+
#[rustc_const_unstable(feature = "const_str_len")]
2190+
pub const fn is_empty(&self) -> bool {
21892191
self.len() == 0
21902192
}
21912193

@@ -2242,8 +2244,15 @@ impl str {
22422244
/// ```
22432245
#[stable(feature = "rust1", since = "1.0.0")]
22442246
#[inline(always)]
2245-
pub fn as_bytes(&self) -> &[u8] {
2246-
unsafe { &*(self as *const str as *const [u8]) }
2247+
#[rustc_const_unstable(feature="const_str_as_bytes")]
2248+
pub const fn as_bytes(&self) -> &[u8] {
2249+
unsafe {
2250+
union Slices<'a> {
2251+
str: &'a str,
2252+
slice: &'a [u8],
2253+
}
2254+
Slices { str: self }.slice
2255+
}
22472256
}
22482257

22492258
/// Converts a mutable string slice to a mutable byte slice. To convert the
@@ -2303,7 +2312,8 @@ impl str {
23032312
/// ```
23042313
#[stable(feature = "rust1", since = "1.0.0")]
23052314
#[inline]
2306-
pub fn as_ptr(&self) -> *const u8 {
2315+
#[rustc_const_unstable(feature = "const_str_as_ptr")]
2316+
pub const fn as_ptr(&self) -> *const u8 {
23072317
self as *const str as *const u8
23082318
}
23092319

src/test/ui/const-eval/strlen.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// run-pass
12+
13+
#![feature(const_str_len, const_str_as_bytes)]
14+
15+
const S: &str = "foo";
16+
pub const B: &[u8] = S.as_bytes();
17+
18+
pub fn foo() -> [u8; S.len()] {
19+
let mut buf = [0; S.len()];
20+
for (i, &c) in S.as_bytes().iter().enumerate() {
21+
buf[i] = c;
22+
}
23+
buf
24+
}
25+
26+
fn main() {
27+
assert_eq!(&foo()[..], b"foo");
28+
assert_eq!(foo().len(), S.len());
29+
const LEN: usize = S.len();
30+
assert_eq!(LEN, S.len());
31+
assert_eq!(B, foo());
32+
assert_eq!(B, b"foo");
33+
}

0 commit comments

Comments
 (0)