From 5d519eaa6e9a583257b2f9e28a743ab85d1cabc5 Mon Sep 17 00:00:00 2001 From: dylni <46035563+dylni@users.noreply.github.com> Date: Mon, 1 Feb 2021 21:20:44 -0500 Subject: [PATCH] Rename `Range::ensure_subset_of` to `slice::range` --- .../alloc/src/collections/vec_deque/mod.rs | 2 +- library/alloc/src/lib.rs | 2 +- library/alloc/src/slice.rs | 2 + library/alloc/src/string.rs | 5 +- library/alloc/src/vec/mod.rs | 2 +- library/core/src/ops/range.rs | 101 ----------------- library/core/src/slice/index.rs | 105 +++++++++++++++++- library/core/src/slice/mod.rs | 8 +- 8 files changed, 115 insertions(+), 112 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 319ca666fc6..f7cefdce278 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1063,7 +1063,7 @@ impl<T> VecDeque<T> { where R: RangeBounds<usize>, { - let Range { start, end } = Range::ensure_subset_of(range, ..self.len()); + let Range { start, end } = slice::range(range, ..self.len()); let tail = self.wrap_add(self.tail, start); let head = self.wrap_add(self.tail, end); (tail, head) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index ade2e3fed2c..c020a969f1f 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -115,7 +115,6 @@ #![feature(or_patterns)] #![feature(pattern)] #![feature(ptr_internals)] -#![feature(range_ensure_subset_of)] #![feature(rustc_attrs)] #![feature(receiver_trait)] #![cfg_attr(bootstrap, feature(min_const_generics))] @@ -123,6 +122,7 @@ #![feature(set_ptr_value)] #![feature(slice_ptr_get)] #![feature(slice_ptr_len)] +#![feature(slice_range)] #![feature(staged_api)] #![feature(str_internals)] #![feature(trusted_len)] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index cb015b94930..c5ffade1261 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -92,6 +92,8 @@ use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; +#[unstable(feature = "slice_range", issue = "76393")] +pub use core::slice::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 ef2f264ec7e..b4deedc5263 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}; @@ -1510,14 +1511,14 @@ 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 } = Range::ensure_subset_of(range, ..self.len()); + let Range { start, end } = slice::range(range, ..self.len()); assert!(self.is_char_boundary(start)); assert!(self.is_char_boundary(end)); // Take out two simultaneous borrows. The &mut String won't be accessed // until iteration is over, in Drop. let self_ptr = self as *mut _; - // SAFETY: `ensure_subset_of` and `is_char_boundary` do the appropriate bounds checks. + // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks. let chars_iter = unsafe { self.get_unchecked(start..end) }.chars(); Drain { start, end, iter: chars_iter, string: self_ptr } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 1a7b846bd85..a8474f8ca59 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1650,7 +1650,7 @@ impl<T, A: Allocator> Vec<T, A> { // the hole, and the vector length is restored to the new length. // let len = self.len(); - let Range { start, end } = Range::ensure_subset_of(range, ..len); + let Range { start, end } = slice::range(range, ..len); unsafe { // set self.vec length's to start, to be safe in case Drain is leaked diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index b30ff9450ff..dbeb3912130 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -1,9 +1,5 @@ use crate::fmt; use crate::hash::Hash; -use crate::slice::index::{ - slice_end_index_len_fail, slice_end_index_overflow_fail, slice_index_order_fail, - slice_start_index_overflow_fail, -}; /// An unbounded range (`..`). /// @@ -151,103 +147,6 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> { } } -impl Range<usize> { - /// Performs bounds-checking of a range. - /// - /// This method is similar to [`Index::index`] for slices, but it returns a - /// `Range` equivalent to `range`. You can use this method to turn any range - /// into `start` and `end` values. - /// - /// `bounds` is the range of the slice to use for bounds-checking. It should - /// be a [`RangeTo`] range that ends at the length of the slice. - /// - /// The returned `Range` is safe to pass to [`slice::get_unchecked`] and - /// [`slice::get_unchecked_mut`] for slices with the given range. - /// - /// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked - /// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut - /// - /// # Panics - /// - /// Panics if `range` would be out of bounds. - /// - /// # Examples - /// - /// ``` - /// #![feature(range_ensure_subset_of)] - /// - /// use std::ops::Range; - /// - /// let v = [10, 40, 30]; - /// assert_eq!(1..2, Range::ensure_subset_of(1..2, ..v.len())); - /// assert_eq!(0..2, Range::ensure_subset_of(..2, ..v.len())); - /// assert_eq!(1..3, Range::ensure_subset_of(1.., ..v.len())); - /// ``` - /// - /// Panics when [`Index::index`] would panic: - /// - /// ```should_panic - /// #![feature(range_ensure_subset_of)] - /// - /// use std::ops::Range; - /// - /// Range::ensure_subset_of(2..1, ..3); - /// ``` - /// - /// ```should_panic - /// #![feature(range_ensure_subset_of)] - /// - /// use std::ops::Range; - /// - /// Range::ensure_subset_of(1..4, ..3); - /// ``` - /// - /// ```should_panic - /// #![feature(range_ensure_subset_of)] - /// - /// use std::ops::Range; - /// - /// Range::ensure_subset_of(1..=usize::MAX, ..3); - /// ``` - /// - /// [`Index::index`]: crate::ops::Index::index - #[track_caller] - #[unstable(feature = "range_ensure_subset_of", issue = "76393")] - pub fn ensure_subset_of<R>(range: R, bounds: RangeTo<usize>) -> Self - where - R: RangeBounds<usize>, - { - let len = bounds.end; - - let start: Bound<&usize> = range.start_bound(); - let start = match start { - Bound::Included(&start) => start, - Bound::Excluded(start) => { - start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) - } - Bound::Unbounded => 0, - }; - - let end: Bound<&usize> = range.end_bound(); - let end = match end { - 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); - } - - Self { start, end } - } -} - /// A range only bounded inclusively below (`start..`). /// /// The `RangeFrom` `start..` contains all values with `x >= start`. diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 660c8a2da5d..d20986bb724 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -37,28 +37,28 @@ fn slice_start_index_len_fail(index: usize, len: usize) -> ! { #[inline(never)] #[cold] #[track_caller] -pub(crate) fn slice_end_index_len_fail(index: usize, len: usize) -> ! { +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)] #[cold] #[track_caller] -pub(crate) fn slice_index_order_fail(index: usize, end: usize) -> ! { +fn slice_index_order_fail(index: usize, end: usize) -> ! { panic!("slice index starts at {} but ends at {}", index, end); } #[inline(never)] #[cold] #[track_caller] -pub(crate) fn slice_start_index_overflow_fail() -> ! { +fn slice_start_index_overflow_fail() -> ! { panic!("attempted to index slice from after maximum usize"); } #[inline(never)] #[cold] #[track_caller] -pub(crate) fn slice_end_index_overflow_fail() -> ! { +fn slice_end_index_overflow_fail() -> ! { panic!("attempted to index slice up to maximum usize"); } @@ -449,3 +449,100 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { (0..=self.end).index_mut(slice) } } + +/// Performs bounds-checking of a range. +/// +/// This method is similar to [`Index::index`] for slices, but it returns a +/// [`Range`] equivalent to `range`. You can use this method to turn any range +/// into `start` and `end` values. +/// +/// `bounds` is the range of the slice to use for bounds-checking. It should +/// be a [`RangeTo`] range that ends at the length of the slice. +/// +/// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and +/// [`slice::get_unchecked_mut`] for slices with the given range. +/// +/// [`Range`]: ops::Range +/// [`RangeTo`]: ops::RangeTo +/// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked +/// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut +/// +/// # Panics +/// +/// Panics if `range` would be out of bounds. +/// +/// # Examples +/// +/// ``` +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// let v = [10, 40, 30]; +/// assert_eq!(1..2, slice::range(1..2, ..v.len())); +/// assert_eq!(0..2, slice::range(..2, ..v.len())); +/// assert_eq!(1..3, slice::range(1.., ..v.len())); +/// ``` +/// +/// Panics when [`Index::index`] would panic: +/// +/// ```should_panic +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// slice::range(2..1, ..3); +/// ``` +/// +/// ```should_panic +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// slice::range(1..4, ..3); +/// ``` +/// +/// ```should_panic +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// slice::range(1..=usize::MAX, ..3); +/// ``` +/// +/// [`Index::index`]: ops::Index::index +#[track_caller] +#[unstable(feature = "slice_range", issue = "76393")] +pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize> +where + R: ops::RangeBounds<usize>, +{ + let len = bounds.end; + + let start: ops::Bound<&usize> = range.start_bound(); + let start = match start { + ops::Bound::Included(&start) => start, + ops::Bound::Excluded(start) => { + start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) + } + ops::Bound::Unbounded => 0, + }; + + let end: ops::Bound<&usize> = range.end_bound(); + let end = match end { + ops::Bound::Included(end) => { + end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) + } + ops::Bound::Excluded(&end) => end, + ops::Bound::Unbounded => len, + }; + + if start > end { + slice_index_order_fail(start, end); + } + if end > len { + slice_end_index_len_fail(end, len); + } + + ops::Range { start, end } +} diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e78b6476511..8256d2cc607 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -18,6 +18,7 @@ use crate::option::Option::{None, Some}; use crate::ptr; use crate::result::Result; use crate::result::Result::{Err, Ok}; +use crate::slice; #[unstable( feature = "slice_internals", @@ -29,7 +30,7 @@ pub mod memchr; mod ascii; mod cmp; -pub(crate) mod index; +mod index; mod iter; mod raw; mod rotate; @@ -76,6 +77,9 @@ pub use sort::heapsort; #[stable(feature = "slice_get_slice", since = "1.28.0")] pub use index::SliceIndex; +#[unstable(feature = "slice_range", issue = "76393")] +pub use index::range; + #[lang = "slice"] #[cfg(not(test))] impl<T> [T] { @@ -3052,7 +3056,7 @@ impl<T> [T] { where T: Copy, { - let Range { start: src_start, end: src_end } = Range::ensure_subset_of(src, ..self.len()); + let Range { start: src_start, end: src_end } = slice::range(src, ..self.len()); 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,