Skip to content

Commit 89b814c

Browse files
authored
Rollup merge of #74510 - LukasKalbertodt:fix-range-from-index-panic, r=hanna-kruppe
Fix panic message when `RangeFrom` index is out of bounds Before, the `Range` method was called with `end = slice.len()`. Unfortunately, because `Range::index` first checks the order of the indices (start has to be smaller than end), an out of bounds index leads to `core::slice::slice_index_order_fail` being called. This prints the message 'slice index starts at 27 but ends at 10', which is worse than 'index 27 out of range for slice of length 10'. This is not only useful to normal users reading panic messages, but also for people inspecting assembly and being confused by `slice_index_order_fail` calls. You can see the produced assembly [here](https://rust.godbolt.org/z/GzMGWf) and try on Playground [here](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=aada5996b2f3848075a6d02cf4055743). (By the way. this is only about which panic function is called; I'm pretty sure it does not improve anything about performance).
2 parents 59617e4 + ea74e7d commit 89b814c

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

src/libcore/slice/mod.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -2974,8 +2974,15 @@ where
29742974
#[inline(never)]
29752975
#[cold]
29762976
#[track_caller]
2977-
fn slice_index_len_fail(index: usize, len: usize) -> ! {
2978-
panic!("index {} out of range for slice of length {}", index, len);
2977+
fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
2978+
panic!("range start index {} out of range for slice of length {}", index, len);
2979+
}
2980+
2981+
#[inline(never)]
2982+
#[cold]
2983+
#[track_caller]
2984+
fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
2985+
panic!("range end index {} out of range for slice of length {}", index, len);
29792986
}
29802987

29812988
#[inline(never)]
@@ -3160,7 +3167,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
31603167
if self.start > self.end {
31613168
slice_index_order_fail(self.start, self.end);
31623169
} else if self.end > slice.len() {
3163-
slice_index_len_fail(self.end, slice.len());
3170+
slice_end_index_len_fail(self.end, slice.len());
31643171
}
31653172
unsafe { &*self.get_unchecked(slice) }
31663173
}
@@ -3170,7 +3177,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
31703177
if self.start > self.end {
31713178
slice_index_order_fail(self.start, self.end);
31723179
} else if self.end > slice.len() {
3173-
slice_index_len_fail(self.end, slice.len());
3180+
slice_end_index_len_fail(self.end, slice.len());
31743181
}
31753182
unsafe { &mut *self.get_unchecked_mut(slice) }
31763183
}
@@ -3241,12 +3248,18 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
32413248

32423249
#[inline]
32433250
fn index(self, slice: &[T]) -> &[T] {
3244-
(self.start..slice.len()).index(slice)
3251+
if self.start > slice.len() {
3252+
slice_start_index_len_fail(self.start, slice.len());
3253+
}
3254+
unsafe { &*self.get_unchecked(slice) }
32453255
}
32463256

32473257
#[inline]
32483258
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
3249-
(self.start..slice.len()).index_mut(slice)
3259+
if self.start > slice.len() {
3260+
slice_start_index_len_fail(self.start, slice.len());
3261+
}
3262+
unsafe { &mut *self.get_unchecked_mut(slice) }
32503263
}
32513264
}
32523265

src/libcore/tests/slice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,7 @@ mod slice_index {
10881088

10891089
good: data[6..] == [];
10901090
bad: data[7..];
1091-
message: "but ends at"; // perhaps not ideal
1091+
message: "out of range";
10921092
}
10931093

10941094
in mod rangeto_len {

0 commit comments

Comments
 (0)