Skip to content

Commit 187b877

Browse files
committed
Auto merge of rust-lang#76885 - dylni:move-slice-check-range-to-range-bounds, r=KodrAus
Move `slice::check_range` to `RangeBounds` Since this method doesn't take a slice anymore (rust-lang#76662), it makes more sense to define it on `RangeBounds`. Questions: - Should the new method be `assert_len` or `assert_length`?
2 parents 4d247ad + f055b0b commit 187b877

File tree

10 files changed

+112
-101
lines changed

10 files changed

+112
-101
lines changed

library/alloc/src/collections/vec_deque.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ impl<T> VecDeque<T> {
11021102
where
11031103
R: RangeBounds<usize>,
11041104
{
1105-
let Range { start, end } = slice::check_range(self.len(), range);
1105+
let Range { start, end } = range.assert_len(self.len());
11061106
let tail = self.wrap_add(self.tail, start);
11071107
let head = self.wrap_add(self.tail, end);
11081108
(tail, head)

library/alloc/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@
114114
#![feature(or_patterns)]
115115
#![feature(pattern)]
116116
#![feature(ptr_internals)]
117+
#![feature(range_bounds_assert_len)]
117118
#![feature(raw_ref_op)]
118119
#![feature(rustc_attrs)]
119120
#![feature(receiver_trait)]
120121
#![feature(min_specialization)]
121-
#![feature(slice_check_range)]
122122
#![feature(slice_ptr_get)]
123123
#![feature(slice_ptr_len)]
124124
#![feature(staged_api)]

library/alloc/src/slice.rs

-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ use crate::borrow::ToOwned;
9191
use crate::boxed::Box;
9292
use crate::vec::Vec;
9393

94-
#[unstable(feature = "slice_check_range", issue = "76393")]
95-
pub use core::slice::check_range;
9694
#[unstable(feature = "array_chunks", issue = "74985")]
9795
pub use core::slice::ArrayChunks;
9896
#[unstable(feature = "array_chunks", issue = "74985")]

library/alloc/src/string.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ use core::iter::{FromIterator, FusedIterator};
4949
use core::ops::Bound::{Excluded, Included, Unbounded};
5050
use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
5151
use core::ptr;
52-
use core::slice;
5352
use core::str::{lossy, pattern::Pattern};
5453

5554
use crate::borrow::{Cow, ToOwned};
@@ -1507,14 +1506,14 @@ impl String {
15071506
// of the vector version. The data is just plain bytes.
15081507
// Because the range removal happens in Drop, if the Drain iterator is leaked,
15091508
// the removal will not happen.
1510-
let Range { start, end } = slice::check_range(self.len(), range);
1509+
let Range { start, end } = range.assert_len(self.len());
15111510
assert!(self.is_char_boundary(start));
15121511
assert!(self.is_char_boundary(end));
15131512

15141513
// Take out two simultaneous borrows. The &mut String won't be accessed
15151514
// until iteration is over, in Drop.
15161515
let self_ptr = self as *mut _;
1517-
// SAFETY: `check_range` and `is_char_boundary` do the appropriate bounds checks.
1516+
// SAFETY: `assert_len` and `is_char_boundary` do the appropriate bounds checks.
15181517
let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
15191518

15201519
Drain { start, end, iter: chars_iter, string: self_ptr }

library/alloc/src/vec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1314,7 +1314,7 @@ impl<T> Vec<T> {
13141314
// the hole, and the vector length is restored to the new length.
13151315
//
13161316
let len = self.len();
1317-
let Range { start, end } = slice::check_range(len, range);
1317+
let Range { start, end } = range.assert_len(len);
13181318

13191319
unsafe {
13201320
// set self.vec length's to start, to be safe in case Drain is leaked

library/core/src/ops/range.rs

+90
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use crate::fmt;
22
use crate::hash::Hash;
3+
use crate::slice::index::{
4+
slice_end_index_len_fail, slice_end_index_overflow_fail, slice_index_order_fail,
5+
slice_start_index_overflow_fail,
6+
};
37

48
/// An unbounded range (`..`).
59
///
@@ -701,6 +705,92 @@ pub trait RangeBounds<T: ?Sized> {
701705
#[stable(feature = "collections_range", since = "1.28.0")]
702706
fn end_bound(&self) -> Bound<&T>;
703707

708+
/// Performs bounds-checking of this range.
709+
///
710+
/// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
711+
/// [`slice::get_unchecked_mut`] for slices of the given length.
712+
///
713+
/// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
714+
/// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
715+
///
716+
/// # Panics
717+
///
718+
/// Panics if the range would be out of bounds.
719+
///
720+
/// # Examples
721+
///
722+
/// ```
723+
/// #![feature(range_bounds_assert_len)]
724+
///
725+
/// use std::ops::RangeBounds;
726+
///
727+
/// let v = [10, 40, 30];
728+
/// assert_eq!(1..2, (1..2).assert_len(v.len()));
729+
/// assert_eq!(0..2, (..2).assert_len(v.len()));
730+
/// assert_eq!(1..3, (1..).assert_len(v.len()));
731+
/// ```
732+
///
733+
/// Panics when [`Index::index`] would panic:
734+
///
735+
/// ```should_panic
736+
/// #![feature(range_bounds_assert_len)]
737+
///
738+
/// use std::ops::RangeBounds;
739+
///
740+
/// (2..1).assert_len(3);
741+
/// ```
742+
///
743+
/// ```should_panic
744+
/// #![feature(range_bounds_assert_len)]
745+
///
746+
/// use std::ops::RangeBounds;
747+
///
748+
/// (1..4).assert_len(3);
749+
/// ```
750+
///
751+
/// ```should_panic
752+
/// #![feature(range_bounds_assert_len)]
753+
///
754+
/// use std::ops::RangeBounds;
755+
///
756+
/// (1..=usize::MAX).assert_len(3);
757+
/// ```
758+
///
759+
/// [`Index::index`]: crate::ops::Index::index
760+
#[track_caller]
761+
#[unstable(feature = "range_bounds_assert_len", issue = "76393")]
762+
fn assert_len(self, len: usize) -> Range<usize>
763+
where
764+
Self: RangeBounds<usize>,
765+
{
766+
let start: Bound<&usize> = self.start_bound();
767+
let start = match start {
768+
Bound::Included(&start) => start,
769+
Bound::Excluded(start) => {
770+
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
771+
}
772+
Bound::Unbounded => 0,
773+
};
774+
775+
let end: Bound<&usize> = self.end_bound();
776+
let end = match end {
777+
Bound::Included(end) => {
778+
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
779+
}
780+
Bound::Excluded(&end) => end,
781+
Bound::Unbounded => len,
782+
};
783+
784+
if start > end {
785+
slice_index_order_fail(start, end);
786+
}
787+
if end > len {
788+
slice_end_index_len_fail(end, len);
789+
}
790+
791+
Range { start, end }
792+
}
793+
704794
/// Returns `true` if `item` is contained in the range.
705795
///
706796
/// # Examples

library/core/src/slice/index.rs

+5-78
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Indexing implementations for `[T]`.
22
3-
use crate::ops::{self, Bound, Range, RangeBounds};
3+
use crate::ops;
44
use crate::ptr;
55

66
#[stable(feature = "rust1", since = "1.0.0")]
@@ -37,104 +37,31 @@ fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
3737
#[inline(never)]
3838
#[cold]
3939
#[track_caller]
40-
pub(super) fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
40+
pub(crate) fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
4141
panic!("range end index {} out of range for slice of length {}", index, len);
4242
}
4343

4444
#[inline(never)]
4545
#[cold]
4646
#[track_caller]
47-
pub(super) fn slice_index_order_fail(index: usize, end: usize) -> ! {
47+
pub(crate) fn slice_index_order_fail(index: usize, end: usize) -> ! {
4848
panic!("slice index starts at {} but ends at {}", index, end);
4949
}
5050

5151
#[inline(never)]
5252
#[cold]
5353
#[track_caller]
54-
pub(super) fn slice_start_index_overflow_fail() -> ! {
54+
pub(crate) fn slice_start_index_overflow_fail() -> ! {
5555
panic!("attempted to index slice from after maximum usize");
5656
}
5757

5858
#[inline(never)]
5959
#[cold]
6060
#[track_caller]
61-
pub(super) fn slice_end_index_overflow_fail() -> ! {
61+
pub(crate) fn slice_end_index_overflow_fail() -> ! {
6262
panic!("attempted to index slice up to maximum usize");
6363
}
6464

65-
/// Performs bounds-checking of the given range.
66-
/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]
67-
/// for slices of the given length.
68-
///
69-
/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
70-
/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
71-
///
72-
/// # Panics
73-
///
74-
/// Panics if the range is out of bounds.
75-
///
76-
/// # Examples
77-
///
78-
/// ```
79-
/// #![feature(slice_check_range)]
80-
/// use std::slice;
81-
///
82-
/// let v = [10, 40, 30];
83-
/// assert_eq!(1..2, slice::check_range(v.len(), 1..2));
84-
/// assert_eq!(0..2, slice::check_range(v.len(), ..2));
85-
/// assert_eq!(1..3, slice::check_range(v.len(), 1..));
86-
/// ```
87-
///
88-
/// Panics when [`Index::index`] would panic:
89-
///
90-
/// ```should_panic
91-
/// #![feature(slice_check_range)]
92-
///
93-
/// std::slice::check_range(3, 2..1);
94-
/// ```
95-
///
96-
/// ```should_panic
97-
/// #![feature(slice_check_range)]
98-
///
99-
/// std::slice::check_range(3, 1..4);
100-
/// ```
101-
///
102-
/// ```should_panic
103-
/// #![feature(slice_check_range)]
104-
///
105-
/// std::slice::check_range(3, 1..=usize::MAX);
106-
/// ```
107-
///
108-
/// [`Index::index`]: ops::Index::index
109-
#[track_caller]
110-
#[unstable(feature = "slice_check_range", issue = "76393")]
111-
pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> {
112-
let start = match range.start_bound() {
113-
Bound::Included(&start) => start,
114-
Bound::Excluded(start) => {
115-
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
116-
}
117-
Bound::Unbounded => 0,
118-
};
119-
120-
let end = match range.end_bound() {
121-
Bound::Included(end) => {
122-
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
123-
}
124-
Bound::Excluded(&end) => end,
125-
Bound::Unbounded => len,
126-
};
127-
128-
if start > end {
129-
slice_index_order_fail(start, end);
130-
}
131-
if end > len {
132-
slice_end_index_len_fail(end, len);
133-
}
134-
135-
Range { start, end }
136-
}
137-
13865
mod private_slice_index {
13966
use super::ops;
14067
#[stable(feature = "slice_get_slice", since = "1.28.0")]

library/core/src/slice/mod.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub mod memchr;
2929

3030
mod ascii;
3131
mod cmp;
32-
mod index;
32+
pub(crate) mod index;
3333
mod iter;
3434
mod raw;
3535
mod rotate;
@@ -73,9 +73,6 @@ pub use sort::heapsort;
7373
#[stable(feature = "slice_get_slice", since = "1.28.0")]
7474
pub use index::SliceIndex;
7575

76-
#[unstable(feature = "slice_check_range", issue = "76393")]
77-
pub use index::check_range;
78-
7976
#[lang = "slice"]
8077
#[cfg(not(test))]
8178
impl<T> [T] {
@@ -2714,7 +2711,7 @@ impl<T> [T] {
27142711
where
27152712
T: Copy,
27162713
{
2717-
let Range { start: src_start, end: src_end } = check_range(self.len(), src);
2714+
let Range { start: src_start, end: src_end } = src.assert_len(self.len());
27182715
let count = src_end - src_start;
27192716
assert!(dest <= self.len() - count, "dest is out of bounds");
27202717
// SAFETY: the conditions for `ptr::copy` have all been checked above,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# `range_bounds_assert_len`
2+
3+
The tracking issue for this feature is: [#76393]
4+
5+
------------------------
6+
7+
This adds [`RangeBounds::assert_len`].
8+
9+
[#76393]: https://github.com/rust-lang/rust/issues/76393
10+
[`RangeBounds::assert_len`]: https://doc.rust-lang.org/nightly/std/ops/trait.RangeBounds.html#method.assert_len

src/doc/unstable-book/src/library-features/slice-check-range.md

-10
This file was deleted.

0 commit comments

Comments
 (0)