about summary refs log tree commit diff
path: root/src/libcore/slice
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2018-05-10 11:35:17 -0500
committerGitHub <noreply@github.com>2018-05-10 11:35:17 -0500
commitcff1a263c9e7744df286d2518e0c6ca3191dc681 (patch)
tree2d39f779a1fba6ca894db351eac6242edae37f92 /src/libcore/slice
parentecd9898b60b601f69113c64b77650a09d7678edf (diff)
parentf1d7b453fed6acefc68f90752922b37c6e3ac7a4 (diff)
downloadrust-cff1a263c9e7744df286d2518e0c6ca3191dc681.tar.gz
rust-cff1a263c9e7744df286d2518e0c6ca3191dc681.zip
Rollup merge of #50010 - ExpHP:slice-bounds, r=alexcrichton
Give SliceIndex impls a test suite of girth befitting the implementation (and fix a UTF8 boundary check)

So one day I was writing something in my codebase that basically amounted to `impl SliceIndex for (Bound<usize>, Bound<usize>)`, and I said to myself:

*Boy, gee, golly!  I never realized bounds checking was so tricky!*

At some point when I had around 60 lines of tests for it, I decided to go see how the standard library does it to see if I missed any edge cases. ...That's when I discovered that libcore only had about 40 lines of tests for slicing altogether, and none of them even used `..=`.

---

This PR includes:

* **Literally the first appearance of the word `get_unchecked_mut` in any directory named `test` or `tests`.**
* Likewise the first appearance of `get_mut` used with _any type of range argument_ in these directories.
* Tests for the panics on overflow with `..=`.
    * I wanted to test on `[(); usize::MAX]` as well but that takes linear time in debug mode </3
* A horrible and ugly test-generating macro for the `should_panic` tests that increases the DRYness by a single order of magnitude (which IMO wasn't enough, but I didn't want to go any further and risk making the tests inaccessible to next guy).
* Same stuff for str!
    * Actually, the existing `str` tests were pretty good. I just helped filled in the holes.
* [A fix for the bug it caught](https://github.com/rust-lang/rust/issues/50002).  (only one ~~sadly~~)
Diffstat (limited to 'src/libcore/slice')
-rw-r--r--src/libcore/slice/mod.rs12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 83e8a6e4b68..93ebc23ac0b 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -2262,6 +2262,12 @@ fn slice_index_order_fail(index: usize, end: usize) -> ! {
     panic!("slice index starts at {} but ends at {}", index, end);
 }
 
+#[inline(never)]
+#[cold]
+fn slice_index_overflow_fail() -> ! {
+    panic!("attempted to index slice up to maximum usize");
+}
+
 /// A helper trait used for indexing operations.
 #[unstable(feature = "slice_get_slice", issue = "35729")]
 #[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
@@ -2538,15 +2544,13 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
 
     #[inline]
     fn index(self, slice: &[T]) -> &[T] {
-        assert!(self.end != usize::max_value(),
-            "attempted to index slice up to maximum usize");
+        if self.end == usize::max_value() { slice_index_overflow_fail(); }
         (self.start..self.end + 1).index(slice)
     }
 
     #[inline]
     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        assert!(self.end != usize::max_value(),
-            "attempted to index slice up to maximum usize");
+        if self.end == usize::max_value() { slice_index_overflow_fail(); }
         (self.start..self.end + 1).index_mut(slice)
     }
 }