Skip to content

Commit

Permalink
Rollup merge of rust-lang#94657 - fee1-dead:const_slice_index, r=oli-obk
Browse files Browse the repository at this point in the history
Constify `Index{,Mut}` for `[T]`, `str`, and `[T; N]`

Several panic functions were rewired (via `const_eval_select`) to simpler implementations that do not require formatting for compile-time usage.

r? ``@oli-obk``
  • Loading branch information
Dylan-DPC authored Mar 9, 2022
2 parents e3c33bb + 4654a91 commit 30bb973
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 61 deletions.
10 changes: 6 additions & 4 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,10 @@ impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] {
}

#[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
impl<T, I, const N: usize> Index<I> for [T; N]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
impl<T, I, const N: usize> const Index<I> for [T; N]
where
[T]: Index<I>,
[T]: ~const Index<I>,
{
type Output = <[T] as Index<I>>::Output;

Expand All @@ -289,9 +290,10 @@ where
}

#[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
impl<T, I, const N: usize> IndexMut<I> for [T; N]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
impl<T, I, const N: usize> const IndexMut<I> for [T; N]
where
[T]: IndexMut<I>,
[T]: ~const IndexMut<I>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
Expand Down
2 changes: 2 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@
#![feature(variant_count)]
#![feature(const_array_from_ref)]
#![feature(const_slice_from_ref)]
#![feature(const_slice_index)]
#![feature(const_is_char_boundary)]
//
// Language features:
#![feature(abi_unadjusted)]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ impl u8 {
ascii::escape_default(self)
}

pub(crate) fn is_utf8_char_boundary(self) -> bool {
pub(crate) const fn is_utf8_char_boundary(self) -> bool {
// This is bit magic equivalent to: b < 128 || b >= 192
(self as i8) >= -0x40
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/ops/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ impl RangeInclusive<usize> {
/// Converts to an exclusive `Range` for `SliceIndex` implementations.
/// The caller is responsible for dealing with `end == usize::MAX`.
#[inline]
pub(crate) fn into_slice_range(self) -> Range<usize> {
pub(crate) const fn into_slice_range(self) -> Range<usize> {
// If we're not exhausted, we want to simply slice `start..end + 1`.
// If we are exhausted, then slicing with `end + 1..end + 1` gives us an
// empty range that is still subject to bounds-checks for that endpoint.
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1032,10 +1032,11 @@ impl<T> *const [T] {
/// }
/// ```
#[unstable(feature = "slice_ptr_get", issue = "74265")]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
#[inline]
pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
pub const unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
// SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds.
unsafe { index.get_unchecked(self) }
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1302,10 +1302,11 @@ impl<T> *mut [T] {
/// }
/// ```
#[unstable(feature = "slice_ptr_get", issue = "74265")]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
#[inline(always)]
pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
pub const unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
// SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds.
unsafe { index.get_unchecked_mut(self) }
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,10 +630,11 @@ impl<T> NonNull<[T]> {
/// }
/// ```
#[unstable(feature = "slice_ptr_get", issue = "74265")]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
#[inline]
pub unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output>
pub const unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output>
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
// SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds.
// As a consequence, the resulting pointer cannot be null.
Expand Down
83 changes: 67 additions & 16 deletions library/core/src/slice/index.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
//! Indexing implementations for `[T]`.

use crate::intrinsics::const_eval_select;
use crate::ops;
use crate::ptr;

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, I> ops::Index<I> for [T]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
impl<T, I> const ops::Index<I> for [T]
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
type Output = I::Output;

Expand All @@ -17,9 +19,10 @@ where
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, I> ops::IndexMut<I> for [T]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
impl<T, I> const ops::IndexMut<I> for [T]
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut I::Output {
Expand All @@ -31,39 +34,80 @@ where
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[cold]
#[track_caller]
fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
const fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
// SAFETY: we are just panicking here
unsafe {
const_eval_select(
(index, len),
slice_start_index_len_fail_ct,
slice_start_index_len_fail_rt,
)
}
}

// FIXME const-hack
fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! {
panic!("range start index {} out of range for slice of length {}", index, len);
}

const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! {
panic!("slice start index is out of range for slice");
}

#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[cold]
#[track_caller]
fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
const fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
// SAFETY: we are just panicking here
unsafe {
const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt)
}
}

// FIXME const-hack
fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! {
panic!("range end index {} out of range for slice of length {}", index, len);
}

const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! {
panic!("slice end index is out of range for slice");
}

#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[cold]
#[track_caller]
fn slice_index_order_fail(index: usize, end: usize) -> ! {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
const fn slice_index_order_fail(index: usize, end: usize) -> ! {
// SAFETY: we are just panicking here
unsafe { const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) }
}

// FIXME const-hack
fn slice_index_order_fail_rt(index: usize, end: usize) -> ! {
panic!("slice index starts at {} but ends at {}", index, end);
}

const fn slice_index_order_fail_ct(_: usize, _: usize) -> ! {
panic!("slice index start is larger than end");
}

#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[cold]
#[track_caller]
fn slice_start_index_overflow_fail() -> ! {
const fn slice_start_index_overflow_fail() -> ! {
panic!("attempted to index slice from after maximum usize");
}

#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[cold]
#[track_caller]
fn slice_end_index_overflow_fail() -> ! {
const fn slice_end_index_overflow_fail() -> ! {
panic!("attempted to index slice up to maximum usize");
}

Expand Down Expand Up @@ -153,7 +197,8 @@ pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
}

#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for usize {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
unsafe impl<T> const SliceIndex<[T]> for usize {
type Output = T;

#[inline]
Expand Down Expand Up @@ -197,7 +242,8 @@ unsafe impl<T> SliceIndex<[T]> for usize {
}

#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -261,7 +307,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
}

#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeTo<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -298,7 +345,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
}

#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -343,7 +391,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
}

#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeFull {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -378,7 +427,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
}

#[stable(feature = "inclusive_range", since = "1.26.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -421,7 +471,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
}

#[stable(feature = "inclusive_range", since = "1.26.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
type Output = [T];

#[inline]
Expand Down
20 changes: 12 additions & 8 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,11 @@ impl<T> [T] {
/// assert_eq!(None, v.get(0..4));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
#[inline]
pub fn get<I>(&self, index: I) -> Option<&I::Output>
pub const fn get<I>(&self, index: I) -> Option<&I::Output>
where
I: SliceIndex<Self>,
I: ~const SliceIndex<Self>,
{
index.get(self)
}
Expand All @@ -348,10 +349,11 @@ impl<T> [T] {
/// assert_eq!(x, &[0, 42, 2]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
#[inline]
pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
pub const fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
where
I: SliceIndex<Self>,
I: ~const SliceIndex<Self>,
{
index.get_mut(self)
}
Expand Down Expand Up @@ -379,10 +381,11 @@ impl<T> [T] {
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
#[inline]
pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
pub const unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
where
I: SliceIndex<Self>,
I: ~const SliceIndex<Self>,
{
// SAFETY: the caller must uphold most of the safety requirements for `get_unchecked`;
// the slice is dereferenceable because `self` is a safe reference.
Expand Down Expand Up @@ -415,10 +418,11 @@ impl<T> [T] {
/// assert_eq!(x, &[1, 13, 4]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
#[inline]
pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
pub const unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
where
I: SliceIndex<Self>,
I: ~const SliceIndex<Self>,
{
// SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`;
// the slice is dereferenceable because `self` is a safe reference.
Expand Down
Loading

0 comments on commit 30bb973

Please sign in to comment.