From 5941fef2920a631b22e870627c67a2cd9c30dafe Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 22 Feb 2022 12:39:36 +1100 Subject: [PATCH 1/2] Constify slice indexing --- library/core/src/lib.rs | 1 + library/core/src/ops/range.rs | 2 +- library/core/src/slice/index.rs | 80 ++++++++++++++++++++++++++------- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index aa1ad9362a90e..bad3fb0765c7b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -148,6 +148,7 @@ #![feature(variant_count)] #![feature(const_array_from_ref)] #![feature(const_slice_from_ref)] +#![feature(const_slice_index_impls)] // // Language features: #![feature(abi_unadjusted)] diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 1136722067874..5029e0560b892 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -446,7 +446,7 @@ impl RangeInclusive { /// 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 { + pub(crate) const fn into_slice_range(self) -> Range { // 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. diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 0298bba8d329e..3931c123352ce 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -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 ops::Index for [T] +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +impl const ops::Index for [T] where - I: SliceIndex<[T]>, + I: ~const SliceIndex<[T]>, { type Output = I::Output; @@ -17,9 +19,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut for [T] +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +impl const ops::IndexMut for [T] where - I: SliceIndex<[T]>, + I: ~const SliceIndex<[T]>, { #[inline] fn index_mut(&mut self, index: I) -> &mut I::Output { @@ -27,35 +30,73 @@ where } } + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[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_impls", 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_impls", 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_impls", 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"); } @@ -63,7 +104,7 @@ fn slice_start_index_overflow_fail() -> ! { #[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"); } @@ -153,7 +194,8 @@ pub unsafe trait SliceIndex: private_slice_index::Sealed { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for usize { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for usize { type Output = T; #[inline] @@ -197,7 +239,8 @@ unsafe impl SliceIndex<[T]> for usize { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for ops::Range { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::Range { type Output = [T]; #[inline] @@ -261,7 +304,8 @@ unsafe impl SliceIndex<[T]> for ops::Range { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for ops::RangeTo { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeTo { type Output = [T]; #[inline] @@ -298,7 +342,8 @@ unsafe impl SliceIndex<[T]> for ops::RangeTo { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for ops::RangeFrom { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; #[inline] @@ -343,7 +388,8 @@ unsafe impl SliceIndex<[T]> for ops::RangeFrom { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -unsafe impl SliceIndex<[T]> for ops::RangeFull { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeFull { type Output = [T]; #[inline] @@ -378,7 +424,8 @@ unsafe impl SliceIndex<[T]> for ops::RangeFull { } #[stable(feature = "inclusive_range", since = "1.26.0")] -unsafe impl SliceIndex<[T]> for ops::RangeInclusive { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; #[inline] @@ -421,7 +468,8 @@ unsafe impl SliceIndex<[T]> for ops::RangeInclusive { } #[stable(feature = "inclusive_range", since = "1.26.0")] -unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { +#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +unsafe impl const SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; #[inline] From 4654a910018cf0447db1edb2a46a0cae5f7dff8e Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 6 Mar 2022 14:00:12 +1100 Subject: [PATCH 2/2] Constify slice index for strings --- library/core/src/array/mod.rs | 10 +++++---- library/core/src/lib.rs | 3 ++- library/core/src/num/mod.rs | 2 +- library/core/src/ptr/const_ptr.rs | 5 +++-- library/core/src/ptr/mut_ptr.rs | 5 +++-- library/core/src/ptr/non_null.rs | 5 +++-- library/core/src/slice/index.rs | 31 +++++++++++++------------ library/core/src/slice/mod.rs | 20 ++++++++++------- library/core/src/str/mod.rs | 36 +++++++++++++++++++++++++----- library/core/src/str/traits.rs | 30 ++++++++++++++++--------- src/test/ui/str/str-idx.stderr | 8 +++---- src/test/ui/str/str-mut-idx.stderr | 8 +++---- 12 files changed, 104 insertions(+), 59 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index ee79021ed536e..20dfbc6347c4f 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -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 Index for [T; N] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +impl const Index for [T; N] where - [T]: Index, + [T]: ~const Index, { type Output = <[T] as Index>::Output; @@ -289,9 +290,10 @@ where } #[stable(feature = "index_trait_on_arrays", since = "1.50.0")] -impl IndexMut for [T; N] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +impl const IndexMut for [T; N] where - [T]: IndexMut, + [T]: ~const IndexMut, { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index bad3fb0765c7b..674e165455916 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -148,7 +148,8 @@ #![feature(variant_count)] #![feature(const_array_from_ref)] #![feature(const_slice_from_ref)] -#![feature(const_slice_index_impls)] +#![feature(const_slice_index)] +#![feature(const_is_char_boundary)] // // Language features: #![feature(abi_unadjusted)] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 72105888f9447..07fd317e07486 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -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 } diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 485a5965f4cf7..ee544b4842e86 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1032,10 +1032,11 @@ impl *const [T] { /// } /// ``` #[unstable(feature = "slice_ptr_get", issue = "74265")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked(self, index: I) -> *const I::Output + pub const unsafe fn get_unchecked(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) } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 1412e836ebfc2..3374b48c88c6b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1302,10 +1302,11 @@ impl *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(self, index: I) -> *mut I::Output + pub const unsafe fn get_unchecked_mut(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) } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 0aa8e9960a8dd..897609410dac4 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -630,10 +630,11 @@ impl 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(self, index: I) -> NonNull + pub const unsafe fn get_unchecked_mut(self, index: I) -> NonNull 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. diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 3931c123352ce..7e6fbbe353889 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -5,7 +5,7 @@ use crate::ops; use crate::ptr; #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] impl const ops::Index for [T] where I: ~const SliceIndex<[T]>, @@ -19,7 +19,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] impl const ops::IndexMut for [T] where I: ~const SliceIndex<[T]>, @@ -30,16 +30,19 @@ where } } - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[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) + const_eval_select( + (index, len), + slice_start_index_len_fail_ct, + slice_start_index_len_fail_rt, + ) } } @@ -56,7 +59,7 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[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 { @@ -77,7 +80,7 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[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) } @@ -194,7 +197,7 @@ pub unsafe trait SliceIndex: private_slice_index::Sealed { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for usize { type Output = T; @@ -239,7 +242,7 @@ unsafe impl const SliceIndex<[T]> for usize { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::Range { type Output = [T]; @@ -304,7 +307,7 @@ unsafe impl const SliceIndex<[T]> for ops::Range { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeTo { type Output = [T]; @@ -342,7 +345,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeTo { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; @@ -388,7 +391,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeFrom { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeFull { type Output = [T]; @@ -424,7 +427,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeFull { } #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; @@ -468,7 +471,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { } #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index_impls", issue = "none")] +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl const SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index cd38c3a75473d..ea03dc9de9ec3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -321,10 +321,11 @@ impl [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(&self, index: I) -> Option<&I::Output> + pub const fn get(&self, index: I) -> Option<&I::Output> where - I: SliceIndex, + I: ~const SliceIndex, { index.get(self) } @@ -345,10 +346,11 @@ impl [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(&mut self, index: I) -> Option<&mut I::Output> + pub const fn get_mut(&mut self, index: I) -> Option<&mut I::Output> where - I: SliceIndex, + I: ~const SliceIndex, { index.get_mut(self) } @@ -376,10 +378,11 @@ impl [T] { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked(&self, index: I) -> &I::Output + pub const unsafe fn get_unchecked(&self, index: I) -> &I::Output where - I: SliceIndex, + I: ~const SliceIndex, { // SAFETY: the caller must uphold most of the safety requirements for `get_unchecked`; // the slice is dereferenceable because `self` is a safe reference. @@ -412,10 +415,11 @@ impl [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(&mut self, index: I) -> &mut I::Output + pub const unsafe fn get_unchecked_mut(&mut self, index: I) -> &mut I::Output where - I: SliceIndex, + I: ~const SliceIndex, { // SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`; // the slice is dereferenceable because `self` is a safe reference. diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 09709dc3cf6df..f66bab999a98a 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -79,7 +79,23 @@ use iter::{MatchesInternal, SplitNInternal}; #[inline(never)] #[cold] #[track_caller] -fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { +#[rustc_allow_const_fn_unstable(const_eval_select)] +const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { + // SAFETY: panics for both branches + unsafe { + crate::intrinsics::const_eval_select( + (s, begin, end), + slice_error_fail_ct, + slice_error_fail_rt, + ) + } +} + +const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! { + panic!("failed to slice string"); +} + +fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { const MAX_DISPLAY_LENGTH: usize = 256; let trunc_len = s.floor_char_boundary(MAX_DISPLAY_LENGTH); let s_trunc = &s[..trunc_len]; @@ -189,8 +205,9 @@ impl str { /// ``` #[must_use] #[stable(feature = "is_char_boundary", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_is_char_boundary", issue = "none")] #[inline] - pub fn is_char_boundary(&self, index: usize) -> bool { + pub const fn is_char_boundary(&self, index: usize) -> bool { // 0 is always ok. // Test for 0 explicitly so that it can optimize out the check // easily and skip reading string data for that case. @@ -418,8 +435,9 @@ impl str { /// assert!(v.get(..42).is_none()); /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub fn get>(&self, i: I) -> Option<&I::Output> { + pub const fn get>(&self, i: I) -> Option<&I::Output> { i.get(self) } @@ -450,8 +468,9 @@ impl str { /// assert_eq!("HEllo", v); /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { + pub const fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { i.get_mut(self) } @@ -482,8 +501,9 @@ impl str { /// } /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { + pub const unsafe fn get_unchecked>(&self, i: I) -> &I::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked`; // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. @@ -517,8 +537,12 @@ impl str { /// } /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] #[inline] - pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { + pub const unsafe fn get_unchecked_mut>( + &mut self, + i: I, + ) -> &mut I::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`; // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 952676247489f..8b6b4fa02f833 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -53,9 +53,10 @@ impl PartialOrd for str { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for str +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +impl const ops::Index for str where - I: SliceIndex, + I: ~const SliceIndex, { type Output = I::Output; @@ -66,9 +67,10 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut for str +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +impl const ops::IndexMut for str where - I: SliceIndex, + I: ~const SliceIndex, { #[inline] fn index_mut(&mut self, index: I) -> &mut I::Output { @@ -79,7 +81,7 @@ where #[inline(never)] #[cold] #[track_caller] -fn str_index_overflow_fail() -> ! { +const fn str_index_overflow_fail() -> ! { panic!("attempted to index str up to maximum usize"); } @@ -96,7 +98,8 @@ fn str_index_overflow_fail() -> ! { /// /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -unsafe impl SliceIndex for ops::RangeFull { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeFull { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -160,7 +163,8 @@ unsafe impl SliceIndex for ops::RangeFull { /// // &s[3 .. 100]; /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] -unsafe impl SliceIndex for ops::Range { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::Range { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -247,7 +251,8 @@ unsafe impl SliceIndex for ops::Range { /// Panics if `end` does not point to the starting byte offset of a /// character (as defined by `is_char_boundary`), or if `end > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -unsafe impl SliceIndex for ops::RangeTo { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeTo { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -317,7 +322,8 @@ unsafe impl SliceIndex for ops::RangeTo { /// Panics if `begin` does not point to the starting byte offset of /// a character (as defined by `is_char_boundary`), or if `begin > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -unsafe impl SliceIndex for ops::RangeFrom { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeFrom { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -393,7 +399,8 @@ unsafe impl SliceIndex for ops::RangeFrom { /// to the ending byte offset of a character (`end + 1` is either a starting /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -unsafe impl SliceIndex for ops::RangeInclusive { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { @@ -444,7 +451,8 @@ unsafe impl SliceIndex for ops::RangeInclusive { /// (`end + 1` is either a starting byte offset as defined by /// `is_char_boundary`, or equal to `len`), or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -unsafe impl SliceIndex for ops::RangeToInclusive { +#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] +unsafe impl const SliceIndex for ops::RangeToInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 9c3c3646139dc..9ab409bbdcdf8 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -23,8 +23,8 @@ LL | let _ = s.get(4); note: required by a bound in `core::str::::get` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | -LL | pub fn get>(&self, i: I) -> Option<&I::Output> { - | ^^^^^^^^^^^^^^^ required by this bound in `core::str::::get` +LL | pub const fn get>(&self, i: I) -> Option<&I::Output> { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get` error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-idx.rs:5:29 @@ -40,8 +40,8 @@ LL | let _ = s.get_unchecked(4); note: required by a bound in `core::str::::get_unchecked` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | -LL | pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { - | ^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked` +LL | pub const unsafe fn get_unchecked>(&self, i: I) -> &I::Output { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked` error[E0277]: the type `str` cannot be indexed by `char` --> $DIR/str-idx.rs:6:17 diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index 2559ee9eb49b2..5956e363b0c09 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -47,8 +47,8 @@ LL | s.get_mut(1); note: required by a bound in `core::str::::get_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | -LL | pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { - | ^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_mut` +LL | pub const fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_mut` error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-mut-idx.rs:11:25 @@ -64,8 +64,8 @@ LL | s.get_unchecked_mut(1); note: required by a bound in `core::str::::get_unchecked_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL | -LL | pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { - | ^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked_mut` +LL | pub const unsafe fn get_unchecked_mut>( + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::::get_unchecked_mut` error[E0277]: the type `str` cannot be indexed by `char` --> $DIR/str-mut-idx.rs:13:5