Improve design of assert_len
This commit is contained in:
parent
3f5aee2d52
commit
9d29793614
@ -1063,7 +1063,7 @@ fn range_tail_head<R>(&self, range: R) -> (usize, usize)
|
|||||||
where
|
where
|
||||||
R: RangeBounds<usize>,
|
R: RangeBounds<usize>,
|
||||||
{
|
{
|
||||||
let Range { start, end } = range.assert_len(self.len());
|
let Range { start, end } = range.ensure_subset_of(..self.len());
|
||||||
let tail = self.wrap_add(self.tail, start);
|
let tail = self.wrap_add(self.tail, start);
|
||||||
let head = self.wrap_add(self.tail, end);
|
let head = self.wrap_add(self.tail, end);
|
||||||
(tail, head)
|
(tail, head)
|
||||||
|
@ -115,7 +115,7 @@
|
|||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
#![feature(pattern)]
|
#![feature(pattern)]
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
#![feature(range_bounds_assert_len)]
|
#![feature(range_bounds_ensure_subset_of)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(receiver_trait)]
|
#![feature(receiver_trait)]
|
||||||
#![cfg_attr(bootstrap, feature(min_const_generics))]
|
#![cfg_attr(bootstrap, feature(min_const_generics))]
|
||||||
|
@ -1510,14 +1510,14 @@ pub fn drain<R>(&mut self, range: R) -> Drain<'_>
|
|||||||
// of the vector version. The data is just plain bytes.
|
// of the vector version. The data is just plain bytes.
|
||||||
// Because the range removal happens in Drop, if the Drain iterator is leaked,
|
// Because the range removal happens in Drop, if the Drain iterator is leaked,
|
||||||
// the removal will not happen.
|
// the removal will not happen.
|
||||||
let Range { start, end } = range.assert_len(self.len());
|
let Range { start, end } = range.ensure_subset_of(..self.len());
|
||||||
assert!(self.is_char_boundary(start));
|
assert!(self.is_char_boundary(start));
|
||||||
assert!(self.is_char_boundary(end));
|
assert!(self.is_char_boundary(end));
|
||||||
|
|
||||||
// Take out two simultaneous borrows. The &mut String won't be accessed
|
// Take out two simultaneous borrows. The &mut String won't be accessed
|
||||||
// until iteration is over, in Drop.
|
// until iteration is over, in Drop.
|
||||||
let self_ptr = self as *mut _;
|
let self_ptr = self as *mut _;
|
||||||
// SAFETY: `assert_len` and `is_char_boundary` do the appropriate bounds checks.
|
// SAFETY: `ensure_subset_of` and `is_char_boundary` do the appropriate bounds checks.
|
||||||
let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
|
let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
|
||||||
|
|
||||||
Drain { start, end, iter: chars_iter, string: self_ptr }
|
Drain { start, end, iter: chars_iter, string: self_ptr }
|
||||||
|
@ -1650,7 +1650,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, A>
|
|||||||
// the hole, and the vector length is restored to the new length.
|
// the hole, and the vector length is restored to the new length.
|
||||||
//
|
//
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
let Range { start, end } = range.assert_len(len);
|
let Range { start, end } = range.ensure_subset_of(..len);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// set self.vec length's to start, to be safe in case Drain is leaked
|
// set self.vec length's to start, to be safe in case Drain is leaked
|
||||||
|
@ -766,8 +766,15 @@ pub trait RangeBounds<T: ?Sized> {
|
|||||||
|
|
||||||
/// Performs bounds-checking of this range.
|
/// Performs bounds-checking of this range.
|
||||||
///
|
///
|
||||||
|
/// This method is similar to [`Index::index`] for slices, but it returns a
|
||||||
|
/// [`Range`] equivalent to this range. You can use this method to turn any
|
||||||
|
/// range into `start` and `end` values.
|
||||||
|
///
|
||||||
|
/// The given range 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
|
/// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
|
||||||
/// [`slice::get_unchecked_mut`] for slices of the given length.
|
/// [`slice::get_unchecked_mut`] for slices with the given range.
|
||||||
///
|
///
|
||||||
/// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
|
/// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
|
||||||
/// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
|
/// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
|
||||||
@ -779,49 +786,51 @@ pub trait RangeBounds<T: ?Sized> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(range_bounds_assert_len)]
|
/// #![feature(range_bounds_ensure_subset_of)]
|
||||||
///
|
///
|
||||||
/// use std::ops::RangeBounds;
|
/// use std::ops::RangeBounds;
|
||||||
///
|
///
|
||||||
/// let v = [10, 40, 30];
|
/// let v = [10, 40, 30];
|
||||||
/// assert_eq!(1..2, (1..2).assert_len(v.len()));
|
/// assert_eq!(1..2, (1..2).ensure_subset_of(..v.len()));
|
||||||
/// assert_eq!(0..2, (..2).assert_len(v.len()));
|
/// assert_eq!(0..2, (..2).ensure_subset_of(..v.len()));
|
||||||
/// assert_eq!(1..3, (1..).assert_len(v.len()));
|
/// assert_eq!(1..3, (1..).ensure_subset_of(..v.len()));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Panics when [`Index::index`] would panic:
|
/// Panics when [`Index::index`] would panic:
|
||||||
///
|
///
|
||||||
/// ```should_panic
|
/// ```should_panic
|
||||||
/// #![feature(range_bounds_assert_len)]
|
/// #![feature(range_bounds_ensure_subset_of)]
|
||||||
///
|
///
|
||||||
/// use std::ops::RangeBounds;
|
/// use std::ops::RangeBounds;
|
||||||
///
|
///
|
||||||
/// (2..1).assert_len(3);
|
/// (2..1).ensure_subset_of(..3);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```should_panic
|
/// ```should_panic
|
||||||
/// #![feature(range_bounds_assert_len)]
|
/// #![feature(range_bounds_ensure_subset_of)]
|
||||||
///
|
///
|
||||||
/// use std::ops::RangeBounds;
|
/// use std::ops::RangeBounds;
|
||||||
///
|
///
|
||||||
/// (1..4).assert_len(3);
|
/// (1..4).ensure_subset_of(..3);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```should_panic
|
/// ```should_panic
|
||||||
/// #![feature(range_bounds_assert_len)]
|
/// #![feature(range_bounds_ensure_subset_of)]
|
||||||
///
|
///
|
||||||
/// use std::ops::RangeBounds;
|
/// use std::ops::RangeBounds;
|
||||||
///
|
///
|
||||||
/// (1..=usize::MAX).assert_len(3);
|
/// (1..=usize::MAX).ensure_subset_of(..3);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`Index::index`]: crate::ops::Index::index
|
/// [`Index::index`]: crate::ops::Index::index
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[unstable(feature = "range_bounds_assert_len", issue = "76393")]
|
#[unstable(feature = "range_bounds_ensure_subset_of", issue = "76393")]
|
||||||
fn assert_len(self, len: usize) -> Range<usize>
|
fn ensure_subset_of(self, range: RangeTo<usize>) -> Range<usize>
|
||||||
where
|
where
|
||||||
Self: RangeBounds<usize>,
|
Self: RangeBounds<usize>,
|
||||||
{
|
{
|
||||||
|
let len = range.end;
|
||||||
|
|
||||||
let start: Bound<&usize> = self.start_bound();
|
let start: Bound<&usize> = self.start_bound();
|
||||||
let start = match start {
|
let start = match start {
|
||||||
Bound::Included(&start) => start,
|
Bound::Included(&start) => start,
|
||||||
|
@ -3052,7 +3052,7 @@ pub fn copy_within<R: RangeBounds<usize>>(&mut self, src: R, dest: usize)
|
|||||||
where
|
where
|
||||||
T: Copy,
|
T: Copy,
|
||||||
{
|
{
|
||||||
let Range { start: src_start, end: src_end } = src.assert_len(self.len());
|
let Range { start: src_start, end: src_end } = src.ensure_subset_of(..self.len());
|
||||||
let count = src_end - src_start;
|
let count = src_end - src_start;
|
||||||
assert!(dest <= self.len() - count, "dest is out of bounds");
|
assert!(dest <= self.len() - count, "dest is out of bounds");
|
||||||
// SAFETY: the conditions for `ptr::copy` have all been checked above,
|
// SAFETY: the conditions for `ptr::copy` have all been checked above,
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
# `range_bounds_assert_len`
|
|
||||||
|
|
||||||
The tracking issue for this feature is: [#76393]
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
This adds [`RangeBounds::assert_len`].
|
|
||||||
|
|
||||||
[#76393]: https://github.com/rust-lang/rust/issues/76393
|
|
||||||
[`RangeBounds::assert_len`]: https://doc.rust-lang.org/nightly/std/ops/trait.RangeBounds.html#method.assert_len
|
|
@ -0,0 +1,10 @@
|
|||||||
|
# `range_bounds_ensure_subset_of`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#76393]
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
This adds [`RangeBounds::ensure_subset_of`].
|
||||||
|
|
||||||
|
[#76393]: https://github.com/rust-lang/rust/issues/76393
|
||||||
|
[`RangeBounds::ensure_subset_of`]: https://doc.rust-lang.org/nightly/std/ops/trait.RangeBounds.html#method.ensure_subset_of
|
Loading…
Reference in New Issue
Block a user