Skip to content

Commit

Permalink
Rollup merge of rust-lang#50863 - oli-obk:const_len, r=SimonSapin,Gankro
Browse files Browse the repository at this point in the history
Make `[T]::len` and `str::len` const fn

r? @gankro
  • Loading branch information
kennytm authored May 22, 2018
2 parents eb92280 + 2788f66 commit e7e3261
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 16 deletions.
3 changes: 3 additions & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(const_slice_len)]
#![feature(const_str_as_bytes)]
#![feature(const_str_len)]

#[prelude_import]
#[allow(unused)]
Expand Down
32 changes: 21 additions & 11 deletions src/libcore/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,16 @@ mod rotate;
mod sort;

#[repr(C)]
struct Repr<T> {
pub data: *const T,
pub len: usize,
union Repr<'a, T: 'a> {
rust: &'a [T],
rust_mut: &'a mut [T],
raw: FatPtr<T>,
}

#[repr(C)]
struct FatPtr<T> {
data: *const T,
len: usize,
}

//
Expand Down Expand Up @@ -119,9 +126,10 @@ impl<T> [T] {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn len(&self) -> usize {
#[rustc_const_unstable(feature = "const_slice_len")]
pub const fn len(&self) -> usize {
unsafe {
mem::transmute::<&[T], Repr<T>>(self).len
Repr { rust: self }.raw.len
}
}

Expand All @@ -135,7 +143,8 @@ impl<T> [T] {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_empty(&self) -> bool {
#[rustc_const_unstable(feature = "const_slice_len")]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}

Expand Down Expand Up @@ -418,7 +427,8 @@ impl<T> [T] {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn as_ptr(&self) -> *const T {
#[rustc_const_unstable(feature = "const_slice_as_ptr")]
pub const fn as_ptr(&self) -> *const T {
self as *const [T] as *const T
}

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

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

/// Converts a reference to T into a slice of length 1 (without copying).
Expand Down
20 changes: 15 additions & 5 deletions src/libcore/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2166,7 +2166,8 @@ impl str {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn len(&self) -> usize {
#[rustc_const_unstable(feature = "const_str_len")]
pub const fn len(&self) -> usize {
self.as_bytes().len()
}

Expand All @@ -2185,7 +2186,8 @@ impl str {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_empty(&self) -> bool {
#[rustc_const_unstable(feature = "const_str_len")]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}

Expand Down Expand Up @@ -2242,8 +2244,15 @@ impl str {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline(always)]
pub fn as_bytes(&self) -> &[u8] {
unsafe { &*(self as *const str as *const [u8]) }
#[rustc_const_unstable(feature="const_str_as_bytes")]
pub const fn as_bytes(&self) -> &[u8] {
unsafe {
union Slices<'a> {
str: &'a str,
slice: &'a [u8],
}
Slices { str: self }.slice
}
}

/// Converts a mutable string slice to a mutable byte slice. To convert the
Expand Down Expand Up @@ -2303,7 +2312,8 @@ impl str {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn as_ptr(&self) -> *const u8 {
#[rustc_const_unstable(feature = "const_str_as_ptr")]
pub const fn as_ptr(&self) -> *const u8 {
self as *const str as *const u8
}

Expand Down
33 changes: 33 additions & 0 deletions src/test/ui/const-eval/strlen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// run-pass

#![feature(const_str_len, const_str_as_bytes)]

const S: &str = "foo";
pub const B: &[u8] = S.as_bytes();

pub fn foo() -> [u8; S.len()] {
let mut buf = [0; S.len()];
for (i, &c) in S.as_bytes().iter().enumerate() {
buf[i] = c;
}
buf
}

fn main() {
assert_eq!(&foo()[..], b"foo");
assert_eq!(foo().len(), S.len());
const LEN: usize = S.len();
assert_eq!(LEN, S.len());
assert_eq!(B, foo());
assert_eq!(B, b"foo");
}

0 comments on commit e7e3261

Please sign in to comment.