about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-25 16:27:24 +0000
committerbors <bors@rust-lang.org>2020-07-25 16:27:24 +0000
commitfe08fb7b1e7cc5ef45e107f05b3cd30d48313d2b (patch)
treefadcb1a2aa10c1150749d9dfe12975b031158b95 /src/libcore
parent037d8e747de5056f0202f29aa2b0353bdbbf5cfe (diff)
parent0d64b016398f9c0116330089f038b11e2a3c4e1d (diff)
downloadrust-fe08fb7b1e7cc5ef45e107f05b3cd30d48313d2b.tar.gz
rust-fe08fb7b1e7cc5ef45e107f05b3cd30d48313d2b.zip
Auto 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).
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/slice/mod.rs25
-rw-r--r--src/libcore/tests/slice.rs2
2 files changed, 20 insertions, 7 deletions
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 210ac078b4f..9ed5a1f9622 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -2974,8 +2974,15 @@ where
 #[inline(never)]
 #[cold]
 #[track_caller]
-fn slice_index_len_fail(index: usize, len: usize) -> ! {
-    panic!("index {} out of range for slice of length {}", index, len);
+fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
+    panic!("range start index {} out of range for slice of length {}", index, len);
+}
+
+#[inline(never)]
+#[cold]
+#[track_caller]
+fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
+    panic!("range end index {} out of range for slice of length {}", index, len);
 }
 
 #[inline(never)]
@@ -3160,7 +3167,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
         if self.start > self.end {
             slice_index_order_fail(self.start, self.end);
         } else if self.end > slice.len() {
-            slice_index_len_fail(self.end, slice.len());
+            slice_end_index_len_fail(self.end, slice.len());
         }
         unsafe { &*self.get_unchecked(slice) }
     }
@@ -3170,7 +3177,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
         if self.start > self.end {
             slice_index_order_fail(self.start, self.end);
         } else if self.end > slice.len() {
-            slice_index_len_fail(self.end, slice.len());
+            slice_end_index_len_fail(self.end, slice.len());
         }
         unsafe { &mut *self.get_unchecked_mut(slice) }
     }
@@ -3241,12 +3248,18 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
 
     #[inline]
     fn index(self, slice: &[T]) -> &[T] {
-        (self.start..slice.len()).index(slice)
+        if self.start > slice.len() {
+            slice_start_index_len_fail(self.start, slice.len());
+        }
+        unsafe { &*self.get_unchecked(slice) }
     }
 
     #[inline]
     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        (self.start..slice.len()).index_mut(slice)
+        if self.start > slice.len() {
+            slice_start_index_len_fail(self.start, slice.len());
+        }
+        unsafe { &mut *self.get_unchecked_mut(slice) }
     }
 }
 
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index fba73be92be..8e240832c13 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -1088,7 +1088,7 @@ mod slice_index {
 
             good: data[6..] == [];
             bad: data[7..];
-            message: "but ends at"; // perhaps not ideal
+            message: "out of range";
         }
 
         in mod rangeto_len {