Skip to content

Commit bd63d02

Browse files
committed
Optimize SliceIndex<str> for RangeInclusive
1 parent e1ac2f9 commit bd63d02

File tree

4 files changed

+15
-37
lines changed

4 files changed

+15
-37
lines changed

library/alloctests/tests/str.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -631,13 +631,13 @@ mod slice_index {
631631
// note: using 0 specifically ensures that the result of overflowing is 0..0,
632632
// so that `get` doesn't simply return None for the wrong reason.
633633
bad: data[0..=usize::MAX];
634-
message: "maximum usize";
634+
message: "out of bounds";
635635
}
636636

637637
in mod rangetoinclusive {
638638
data: "hello";
639639
bad: data[..=usize::MAX];
640-
message: "maximum usize";
640+
message: "out of bounds";
641641
}
642642
}
643643
}

library/core/src/range.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -333,15 +333,6 @@ impl<Idx: Step> RangeInclusive<Idx> {
333333
}
334334
}
335335

336-
impl RangeInclusive<usize> {
337-
/// Converts to an exclusive `Range` for `SliceIndex` implementations.
338-
/// The caller is responsible for dealing with `end == usize::MAX`.
339-
#[inline]
340-
pub(crate) const fn into_slice_range(self) -> Range<usize> {
341-
Range { start: self.start, end: self.end + 1 }
342-
}
343-
}
344-
345336
#[unstable(feature = "new_range_api", issue = "125687")]
346337
impl<T> RangeBounds<T> for RangeInclusive<T> {
347338
fn start_bound(&self) -> Bound<&T> {

library/core/src/str/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! {
8787
let ellipsis = if trunc_len < s.len() { "[...]" } else { "" };
8888

8989
// 1. out of bounds
90-
if begin > s.len() || end > s.len() {
90+
if begin > s.len() || end > s.len() || (end == s.len() && s.is_char_boundary(begin)) {
9191
let oob_index = if begin > s.len() { begin } else { end };
9292
panic!("byte index {oob_index} is out of bounds of `{s_trunc}`{ellipsis}");
9393
}

library/core/src/str/traits.rs

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,6 @@ where
7575
}
7676
}
7777

78-
#[inline(never)]
79-
#[cold]
80-
#[track_caller]
81-
const fn str_index_overflow_fail() -> ! {
82-
panic!("attempted to index str up to maximum usize");
83-
}
84-
8578
/// Implements substring slicing with syntax `&self[..]` or `&mut self[..]`.
8679
///
8780
/// Returns a slice of the whole string, i.e., returns `&self` or `&mut
@@ -639,11 +632,11 @@ unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> {
639632
type Output = str;
640633
#[inline]
641634
fn get(self, slice: &str) -> Option<&Self::Output> {
642-
if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
635+
if *self.end() >= slice.len() { None } else { self.into_slice_range().get(slice) }
643636
}
644637
#[inline]
645638
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
646-
if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
639+
if *self.end() >= slice.len() { None } else { self.into_slice_range().get_mut(slice) }
647640
}
648641
#[inline]
649642
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
@@ -657,15 +650,15 @@ unsafe impl const SliceIndex<str> for ops::RangeInclusive<usize> {
657650
}
658651
#[inline]
659652
fn index(self, slice: &str) -> &Self::Output {
660-
if *self.end() == usize::MAX {
661-
str_index_overflow_fail();
653+
if *self.end() >= slice.len() {
654+
super::slice_error_fail(slice, *self.start(), *self.end());
662655
}
663656
self.into_slice_range().index(slice)
664657
}
665658
#[inline]
666659
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
667-
if *self.end() == usize::MAX {
668-
str_index_overflow_fail();
660+
if *self.end() >= slice.len() {
661+
super::slice_error_fail(slice, *self.start(), *self.end());
669662
}
670663
self.into_slice_range().index_mut(slice)
671664
}
@@ -677,35 +670,29 @@ unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
677670
type Output = str;
678671
#[inline]
679672
fn get(self, slice: &str) -> Option<&Self::Output> {
680-
if self.end == usize::MAX { None } else { self.into_slice_range().get(slice) }
673+
ops::RangeInclusive::from(self).get(slice)
681674
}
682675
#[inline]
683676
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
684-
if self.end == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
677+
ops::RangeInclusive::from(self).get_mut(slice)
685678
}
686679
#[inline]
687680
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
688681
// SAFETY: the caller must uphold the safety contract for `get_unchecked`.
689-
unsafe { self.into_slice_range().get_unchecked(slice) }
682+
unsafe { ops::RangeInclusive::from(self).get_unchecked(slice) }
690683
}
691684
#[inline]
692685
unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
693686
// SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
694-
unsafe { self.into_slice_range().get_unchecked_mut(slice) }
687+
unsafe { ops::RangeInclusive::from(self).get_unchecked_mut(slice) }
695688
}
696689
#[inline]
697690
fn index(self, slice: &str) -> &Self::Output {
698-
if self.end == usize::MAX {
699-
str_index_overflow_fail();
700-
}
701-
self.into_slice_range().index(slice)
691+
ops::RangeInclusive::from(self).index(slice)
702692
}
703693
#[inline]
704694
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
705-
if self.end == usize::MAX {
706-
str_index_overflow_fail();
707-
}
708-
self.into_slice_range().index_mut(slice)
695+
ops::RangeInclusive::from(self).index_mut(slice)
709696
}
710697
}
711698

0 commit comments

Comments
 (0)