Skip to content

Commit a2eae7f

Browse files
committed
Optimize SliceIndex impl for RangeInclusive
The check for `self.end() == usize::MAX` can be combined with the `self.end() + 1 > slice.len()` check into `self.en() >= slice.len()`, since `self.end() < slice.len()` implies both `self.end() <= slice.len()` and `self.end() < usize::MAX`. The tradeoff is slightly worse error reporting: previously there would be a special panic message in the `range.end() == usize::MAX` case.
1 parent ca77504 commit a2eae7f

File tree

3 files changed

+12
-11
lines changed

3 files changed

+12
-11
lines changed

library/core/src/slice/index.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,6 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFull {
658658
}
659659

660660
/// The methods `index` and `index_mut` panic if:
661-
/// - the end of the range is `usize::MAX` or
662661
/// - the start of the range is greater than the end of the range or
663662
/// - the end of the range is out of bounds.
664663
#[stable(feature = "inclusive_range", since = "1.26.0")]
@@ -668,12 +667,14 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
668667

669668
#[inline]
670669
fn get(self, slice: &[T]) -> Option<&[T]> {
671-
if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
670+
// `self.into_slice_range()` cannot overflow, because `*self.end() <
671+
// slice.len()` implies `*self.end() < usize::MAX`.
672+
if *self.end() >= slice.len() { None } else { self.into_slice_range().get(slice) }
672673
}
673674

674675
#[inline]
675676
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
676-
if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
677+
if *self.end() >= slice.len() { None } else { self.into_slice_range().get_mut(slice) }
677678
}
678679

679680
#[inline]
@@ -690,16 +691,16 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
690691

691692
#[inline]
692693
fn index(self, slice: &[T]) -> &[T] {
693-
if *self.end() == usize::MAX {
694-
slice_end_index_overflow_fail();
694+
if *self.end() >= slice.len() {
695+
slice_end_index_len_fail(*self.end(), slice.len());
695696
}
696697
self.into_slice_range().index(slice)
697698
}
698699

699700
#[inline]
700701
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
701-
if *self.end() == usize::MAX {
702-
slice_end_index_overflow_fail();
702+
if *self.end() >= slice.len() {
703+
slice_end_index_len_fail(*self.end(), slice.len());
703704
}
704705
self.into_slice_range().index_mut(slice)
705706
}

library/coretests/tests/slice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,14 +1492,14 @@ mod slice_index {
14921492
// note: using 0 specifically ensures that the result of overflowing is 0..0,
14931493
// so that `get` doesn't simply return None for the wrong reason.
14941494
bad: data[0 ..= usize::MAX];
1495-
message: "maximum usize";
1495+
message: "out of range";
14961496
}
14971497

14981498
in mod rangetoinclusive_overflow {
14991499
data: [0, 1];
15001500

15011501
bad: data[..= usize::MAX];
1502-
message: "maximum usize";
1502+
message: "out of range";
15031503
}
15041504

15051505
in mod boundpair_overflow_end {
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
thread 'main' ($TID) panicked at tests/panic/oob_subslice.rs:LL:CC:
3-
range end index 5 out of range for slice of length 4
2+
thread 'main' panicked at tests/panic/oob_subslice.rs:LL:CC:
3+
range end index 4 out of range for slice of length 4
44
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
55
note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect

0 commit comments

Comments
 (0)