about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/alloc/src/collections/vec_deque.rs6
-rw-r--r--library/alloc/src/slice.rs2
-rw-r--r--library/alloc/src/string.rs3
-rw-r--r--library/alloc/src/vec.rs2
-rw-r--r--library/alloc/tests/vec.rs2
-rw-r--r--library/core/src/slice/index.rs75
-rw-r--r--library/core/src/slice/mod.rs81
7 files changed, 85 insertions, 86 deletions
diff --git a/library/alloc/src/collections/vec_deque.rs b/library/alloc/src/collections/vec_deque.rs
index 253a3e9f2be..65cfe9a9b49 100644
--- a/library/alloc/src/collections/vec_deque.rs
+++ b/library/alloc/src/collections/vec_deque.rs
@@ -1089,11 +1089,7 @@ impl<T> VecDeque<T> {
     where
         R: RangeBounds<usize>,
     {
-        // SAFETY: This buffer is only used to check the range. It might be partially
-        // uninitialized, but `check_range` needs a contiguous slice.
-        // https://github.com/rust-lang/rust/pull/75207#discussion_r471193682
-        let buffer = unsafe { slice::from_raw_parts(self.ptr(), self.len()) };
-        let Range { start, end } = buffer.check_range(range);
+        let Range { start, end } = slice::check_range(self.len(), range);
         let tail = self.wrap_add(self.tail, start);
         let head = self.wrap_add(self.tail, end);
         (tail, head)
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 677bfdd2349..55afdd94f44 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -91,6 +91,8 @@ use crate::borrow::ToOwned;
 use crate::boxed::Box;
 use crate::vec::Vec;
 
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub use core::slice::check_range;
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use core::slice::ArrayChunks;
 #[unstable(feature = "array_chunks", issue = "74985")]
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index e1724bf3c9a..2b0ce5ede56 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -49,6 +49,7 @@ use core::iter::{FromIterator, FusedIterator};
 use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
 use core::ptr;
+use core::slice;
 use core::str::{lossy, pattern::Pattern};
 
 use crate::borrow::{Cow, ToOwned};
@@ -1506,7 +1507,7 @@ impl String {
         // of the vector version. The data is just plain bytes.
         // Because the range removal happens in Drop, if the Drain iterator is leaked,
         // the removal will not happen.
-        let Range { start, end } = self.as_bytes().check_range(range);
+        let Range { start, end } = slice::check_range(self.len(), range);
         assert!(self.is_char_boundary(start));
         assert!(self.is_char_boundary(end));
 
diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index f9ee2034f31..9dbea0dc9e6 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -1312,7 +1312,7 @@ impl<T> Vec<T> {
         // the hole, and the vector length is restored to the new length.
         //
         let len = self.len();
-        let Range { start, end } = self.check_range(range);
+        let Range { start, end } = slice::check_range(len, range);
 
         unsafe {
             // set self.vec length's to start, to be safe in case Drain is leaked
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 563dd7ab645..368ca4c5432 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -919,7 +919,7 @@ fn test_from_iter_partially_drained_in_place_specialization() {
 #[test]
 fn test_from_iter_specialization_with_iterator_adapters() {
     fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {};
-    let src: Vec<usize> = vec![0usize; 65535];
+    let src: Vec<usize> = vec![0usize; 256];
     let srcptr = src.as_ptr();
     let iter = src
         .into_iter()
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index d67e0ae536d..16fcb6231dc 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -1,6 +1,6 @@
 //! Indexing implementations for `[T]`.
 
-use crate::ops;
+use crate::ops::{self, Bound, Range, RangeBounds};
 use crate::ptr;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -62,6 +62,79 @@ pub(super) fn slice_end_index_overflow_fail() -> ! {
     panic!("attempted to index slice up to maximum usize");
 }
 
+/// Performs bounds-checking of the given range.
+/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]
+/// for slices of the given length.
+///
+/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
+/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
+///
+/// # Panics
+///
+/// Panics if the range is out of bounds.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(slice_check_range)]
+/// use std::slice;
+///
+/// let v = [10, 40, 30];
+/// assert_eq!(1..2, slice::check_range(v.len(), 1..2));
+/// assert_eq!(0..2, slice::check_range(v.len(), ..2));
+/// assert_eq!(1..3, slice::check_range(v.len(), 1..));
+/// ```
+///
+/// Panics when [`Index::index`] would panic:
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 2..1);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 1..4);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 1..=usize::MAX);
+/// ```
+///
+/// [`Index::index`]: ops::Index::index
+#[track_caller]
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> {
+    let start = match range.start_bound() {
+        Bound::Included(&start) => start,
+        Bound::Excluded(start) => {
+            start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
+        }
+        Bound::Unbounded => 0,
+    };
+
+    let end = match range.end_bound() {
+        Bound::Included(end) => {
+            end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
+        }
+        Bound::Excluded(&end) => end,
+        Bound::Unbounded => len,
+    };
+
+    if start > end {
+        slice_index_order_fail(start, end);
+    }
+    if end > len {
+        slice_end_index_len_fail(end, len);
+    }
+
+    Range { start, end }
+}
+
 mod private_slice_index {
     use super::ops;
     #[stable(feature = "slice_get_slice", since = "1.28.0")]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 64a707c39f0..ba3185433c8 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -12,7 +12,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::intrinsics::assume;
 use crate::marker::{self, Copy};
 use crate::mem;
-use crate::ops::{Bound, FnMut, Range, RangeBounds};
+use crate::ops::{FnMut, Range, RangeBounds};
 use crate::option::Option;
 use crate::option::Option::{None, Some};
 use crate::ptr::{self, NonNull};
@@ -72,8 +72,8 @@ pub use sort::heapsort;
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use index::SliceIndex;
 
-use index::{slice_end_index_len_fail, slice_index_order_fail};
-use index::{slice_end_index_overflow_fail, slice_start_index_overflow_fail};
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub use index::check_range;
 
 #[lang = "slice"]
 #[cfg(not(test))]
@@ -378,79 +378,6 @@ impl<T> [T] {
         unsafe { &mut *index.get_unchecked_mut(self) }
     }
 
-    /// Converts a range over this slice to [`Range`].
-    ///
-    /// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
-    ///
-    /// [`get_unchecked`]: #method.get_unchecked
-    /// [`get_unchecked_mut`]: #method.get_unchecked_mut
-    ///
-    /// # Panics
-    ///
-    /// Panics if the range is out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(slice_check_range)]
-    ///
-    /// let v = [10, 40, 30];
-    /// assert_eq!(1..2, v.check_range(1..2));
-    /// assert_eq!(0..2, v.check_range(..2));
-    /// assert_eq!(1..3, v.check_range(1..));
-    /// ```
-    ///
-    /// Panics when [`Index::index`] would panic:
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(2..1);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(1..4);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(1..=usize::MAX);
-    /// ```
-    ///
-    /// [`Index::index`]: crate::ops::Index::index
-    #[track_caller]
-    #[unstable(feature = "slice_check_range", issue = "76393")]
-    pub fn check_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
-        let start = match range.start_bound() {
-            Bound::Included(&start) => start,
-            Bound::Excluded(start) => {
-                start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
-            }
-            Bound::Unbounded => 0,
-        };
-
-        let len = self.len();
-        let end = match range.end_bound() {
-            Bound::Included(end) => {
-                end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
-            }
-            Bound::Excluded(&end) => end,
-            Bound::Unbounded => len,
-        };
-
-        if start > end {
-            slice_index_order_fail(start, end);
-        }
-        if end > len {
-            slice_end_index_len_fail(end, len);
-        }
-
-        Range { start, end }
-    }
-
     /// Returns a raw pointer to the slice's buffer.
     ///
     /// The caller must ensure that the slice outlives the pointer this
@@ -2794,7 +2721,7 @@ impl<T> [T] {
     where
         T: Copy,
     {
-        let Range { start: src_start, end: src_end } = self.check_range(src);
+        let Range { start: src_start, end: src_end } = check_range(self.len(), src);
         let count = src_end - src_start;
         assert!(dest <= self.len() - count, "dest is out of bounds");
         // SAFETY: the conditions for `ptr::copy` have all been checked above,