summaryrefslogtreecommitdiffstats
path: root/library/alloc/src/collections/vec_deque
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /library/alloc/src/collections/vec_deque
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/alloc/src/collections/vec_deque')
-rw-r--r--library/alloc/src/collections/vec_deque/drain.rs40
-rw-r--r--library/alloc/src/collections/vec_deque/into_iter.rs30
-rw-r--r--library/alloc/src/collections/vec_deque/iter.rs33
-rw-r--r--library/alloc/src/collections/vec_deque/iter_mut.rs32
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs49
5 files changed, 93 insertions, 91 deletions
diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs
index 89feb361d..0be274a38 100644
--- a/library/alloc/src/collections/vec_deque/drain.rs
+++ b/library/alloc/src/collections/vec_deque/drain.rs
@@ -52,36 +52,22 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
}
}
- // Only returns pointers to the slices, as that's
- // all we need to drop them. May only be called if `self.remaining != 0`.
+ // Only returns pointers to the slices, as that's all we need
+ // to drop them. May only be called if `self.remaining != 0`.
unsafe fn as_slices(&self) -> (*mut [T], *mut [T]) {
unsafe {
let deque = self.deque.as_ref();
- // FIXME: This is doing almost exactly the same thing as the else branch in `VecDeque::slice_ranges`.
- // Unfortunately, we can't just call `slice_ranges` here, as the deque's `len` is currently
- // just `drain_start`, so the range check would (almost) always panic. Between temporarily
- // adjusting the deques `len` to call `slice_ranges`, and just copy pasting the `slice_ranges`
- // implementation, this seemed like the less hacky solution, though it might be good to
- // find a better one in the future.
-
- // because `self.remaining != 0`, we know that `self.idx < deque.original_len`, so it's a valid
- // logical index.
- let wrapped_start = deque.to_physical_idx(self.idx);
-
- let head_len = deque.capacity() - wrapped_start;
-
- let (a_range, b_range) = if head_len >= self.remaining {
- (wrapped_start..wrapped_start + self.remaining, 0..0)
- } else {
- let tail_len = self.remaining - head_len;
- (wrapped_start..deque.capacity(), 0..tail_len)
- };
-
- // SAFETY: the range `self.idx..self.idx+self.remaining` lies strictly inside
- // the range `0..deque.original_len`. because of this, and because of the fact
- // that we acquire `a_range` and `b_range` exactly like `slice_ranges` would,
- // it's guaranteed that `a_range` and `b_range` represent valid ranges into
- // the deques buffer.
+
+ // We know that `self.idx + self.remaining <= deque.len <= usize::MAX`, so this won't overflow.
+ let logical_remaining_range = self.idx..self.idx + self.remaining;
+
+ // SAFETY: `logical_remaining_range` represents the
+ // range into the logical buffer of elements that
+ // haven't been drained yet, so they're all initialized,
+ // and `slice::range(start..end, end) == start..end`,
+ // so the preconditions for `slice_ranges` are met.
+ let (a_range, b_range) =
+ deque.slice_ranges(logical_remaining_range.clone(), logical_remaining_range.end);
(deque.buffer_range(a_range), deque.buffer_range(b_range))
}
}
diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs
index 34bc0ce91..d9e274df0 100644
--- a/library/alloc/src/collections/vec_deque/into_iter.rs
+++ b/library/alloc/src/collections/vec_deque/into_iter.rs
@@ -1,4 +1,5 @@
use core::iter::{FusedIterator, TrustedLen};
+use core::num::NonZeroUsize;
use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr};
use crate::alloc::{Allocator, Global};
@@ -11,7 +12,6 @@ use super::VecDeque;
/// (provided by the [`IntoIterator`] trait). See its documentation for more.
///
/// [`into_iter`]: VecDeque::into_iter
-/// [`IntoIterator`]: core::iter::IntoIterator
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<
@@ -54,15 +54,16 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
}
#[inline]
- fn advance_by(&mut self, n: usize) -> Result<(), usize> {
- if self.inner.len < n {
- let len = self.inner.len;
+ fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
+ let len = self.inner.len;
+ let rem = if len < n {
self.inner.clear();
- Err(len)
+ n - len
} else {
self.inner.drain(..n);
- Ok(())
- }
+ 0
+ };
+ NonZeroUsize::new(rem).map_or(Ok(()), Err)
}
#[inline]
@@ -182,15 +183,16 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
}
#[inline]
- fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
let len = self.inner.len;
- if len >= n {
- self.inner.truncate(len - n);
- Ok(())
- } else {
+ let rem = if len < n {
self.inner.clear();
- Err(len)
- }
+ n - len
+ } else {
+ self.inner.truncate(len - n);
+ 0
+ };
+ NonZeroUsize::new(rem).map_or(Ok(()), Err)
}
fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs
index d9f393714..646a2a991 100644
--- a/library/alloc/src/collections/vec_deque/iter.rs
+++ b/library/alloc/src/collections/vec_deque/iter.rs
@@ -1,4 +1,5 @@
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
+use core::num::NonZeroUsize;
use core::ops::Try;
use core::{fmt, mem, slice};
@@ -55,13 +56,15 @@ impl<'a, T> Iterator for Iter<'a, T> {
}
}
- fn advance_by(&mut self, n: usize) -> Result<(), usize> {
- let m = match self.i1.advance_by(n) {
- Ok(_) => return Ok(()),
- Err(m) => m,
- };
- mem::swap(&mut self.i1, &mut self.i2);
- self.i1.advance_by(n - m).map_err(|o| o + m)
+ fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
+ let remaining = self.i1.advance_by(n);
+ match remaining {
+ Ok(()) => return Ok(()),
+ Err(n) => {
+ mem::swap(&mut self.i1, &mut self.i2);
+ self.i1.advance_by(n.get())
+ }
+ }
}
#[inline]
@@ -125,14 +128,14 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
}
}
- fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
- let m = match self.i2.advance_back_by(n) {
- Ok(_) => return Ok(()),
- Err(m) => m,
- };
-
- mem::swap(&mut self.i1, &mut self.i2);
- self.i2.advance_back_by(n - m).map_err(|o| m + o)
+ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
+ match self.i2.advance_back_by(n) {
+ Ok(()) => return Ok(()),
+ Err(n) => {
+ mem::swap(&mut self.i1, &mut self.i2);
+ self.i2.advance_back_by(n.get())
+ }
+ }
}
fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs
index 2c59d95cd..7defbb109 100644
--- a/library/alloc/src/collections/vec_deque/iter_mut.rs
+++ b/library/alloc/src/collections/vec_deque/iter_mut.rs
@@ -1,4 +1,5 @@
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
+use core::num::NonZeroUsize;
use core::ops::Try;
use core::{fmt, mem, slice};
@@ -47,13 +48,14 @@ impl<'a, T> Iterator for IterMut<'a, T> {
}
}
- fn advance_by(&mut self, n: usize) -> Result<(), usize> {
- let m = match self.i1.advance_by(n) {
- Ok(_) => return Ok(()),
- Err(m) => m,
- };
- mem::swap(&mut self.i1, &mut self.i2);
- self.i1.advance_by(n - m).map_err(|o| o + m)
+ fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
+ match self.i1.advance_by(n) {
+ Ok(()) => return Ok(()),
+ Err(remaining) => {
+ mem::swap(&mut self.i1, &mut self.i2);
+ self.i1.advance_by(remaining.get())
+ }
+ }
}
#[inline]
@@ -117,14 +119,14 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
}
}
- fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
- let m = match self.i2.advance_back_by(n) {
- Ok(_) => return Ok(()),
- Err(m) => m,
- };
-
- mem::swap(&mut self.i1, &mut self.i2);
- self.i2.advance_back_by(n - m).map_err(|o| m + o)
+ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
+ match self.i2.advance_back_by(n) {
+ Ok(()) => return Ok(()),
+ Err(remaining) => {
+ mem::swap(&mut self.i1, &mut self.i2);
+ self.i2.advance_back_by(remaining.get())
+ }
+ }
}
fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 8317ac431..8916b42ed 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -10,7 +10,7 @@
use core::cmp::{self, Ordering};
use core::fmt;
use core::hash::{Hash, Hasher};
-use core::iter::{repeat_n, repeat_with, ByRefSized, FromIterator};
+use core::iter::{repeat_n, repeat_with, ByRefSized};
use core::mem::{ManuallyDrop, SizedTypeProperties};
use core::ops::{Index, IndexMut, Range, RangeBounds};
use core::ptr;
@@ -1156,7 +1156,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_slices(&self) -> (&[T], &[T]) {
- let (a_range, b_range) = self.slice_ranges(..);
+ let (a_range, b_range) = self.slice_ranges(.., self.len);
// SAFETY: `slice_ranges` always returns valid ranges into
// the physical buffer.
unsafe { (&*self.buffer_range(a_range), &*self.buffer_range(b_range)) }
@@ -1190,7 +1190,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
- let (a_range, b_range) = self.slice_ranges(..);
+ let (a_range, b_range) = self.slice_ranges(.., self.len);
// SAFETY: `slice_ranges` always returns valid ranges into
// the physical buffer.
unsafe { (&mut *self.buffer_range(a_range), &mut *self.buffer_range(b_range)) }
@@ -1232,19 +1232,28 @@ impl<T, A: Allocator> VecDeque<T, A> {
/// Given a range into the logical buffer of the deque, this function
/// return two ranges into the physical buffer that correspond to
- /// the given range.
- fn slice_ranges<R>(&self, range: R) -> (Range<usize>, Range<usize>)
+ /// the given range. The `len` parameter should usually just be `self.len`;
+ /// the reason it's passed explicitly is that if the deque is wrapped in
+ /// a `Drain`, then `self.len` is not actually the length of the deque.
+ ///
+ /// # Safety
+ ///
+ /// This function is always safe to call. For the resulting ranges to be valid
+ /// ranges into the physical buffer, the caller must ensure that the result of
+ /// calling `slice::range(range, ..len)` represents a valid range into the
+ /// logical buffer, and that all elements in that range are initialized.
+ fn slice_ranges<R>(&self, range: R, len: usize) -> (Range<usize>, Range<usize>)
where
R: RangeBounds<usize>,
{
- let Range { start, end } = slice::range(range, ..self.len);
+ let Range { start, end } = slice::range(range, ..len);
let len = end - start;
if len == 0 {
(0..0, 0..0)
} else {
- // `slice::range` guarantees that `start <= end <= self.len`.
- // because `len != 0`, we know that `start < end`, so `start < self.len`
+ // `slice::range` guarantees that `start <= end <= len`.
+ // because `len != 0`, we know that `start < end`, so `start < len`
// and the indexing is valid.
let wrapped_start = self.to_physical_idx(start);
@@ -1290,7 +1299,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
where
R: RangeBounds<usize>,
{
- let (a_range, b_range) = self.slice_ranges(range);
+ let (a_range, b_range) = self.slice_ranges(range, self.len);
// SAFETY: The ranges returned by `slice_ranges`
// are valid ranges into the physical buffer, so
// it's ok to pass them to `buffer_range` and
@@ -1330,7 +1339,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
where
R: RangeBounds<usize>,
{
- let (a_range, b_range) = self.slice_ranges(range);
+ let (a_range, b_range) = self.slice_ranges(range, self.len);
// SAFETY: The ranges returned by `slice_ranges`
// are valid ranges into the physical buffer, so
// it's ok to pass them to `buffer_range` and
@@ -2385,7 +2394,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
}
/// Binary searches this `VecDeque` for a given element.
- /// This behaves similarly to [`contains`] if this `VecDeque` is sorted.
+ /// If the `VecDeque` is not sorted, the returned result is unspecified and
+ /// meaningless.
///
/// If the value is found then [`Result::Ok`] is returned, containing the
/// index of the matching element. If there are multiple matches, then any
@@ -2395,7 +2405,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
///
/// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`].
///
- /// [`contains`]: VecDeque::contains
/// [`binary_search_by`]: VecDeque::binary_search_by
/// [`binary_search_by_key`]: VecDeque::binary_search_by_key
/// [`partition_point`]: VecDeque::partition_point
@@ -2441,12 +2450,13 @@ impl<T, A: Allocator> VecDeque<T, A> {
}
/// Binary searches this `VecDeque` with a comparator function.
- /// This behaves similarly to [`contains`] if this `VecDeque` is sorted.
///
- /// The comparator function should implement an order consistent
- /// with the sort order of the deque, returning an order code that
- /// indicates whether its argument is `Less`, `Equal` or `Greater`
- /// than the desired target.
+ /// The comparator function should return an order code that indicates
+ /// whether its argument is `Less`, `Equal` or `Greater` the desired
+ /// target.
+ /// If the `VecDeque` is not sorted or if the comparator function does not
+ /// implement an order consistent with the sort order of the underlying
+ /// `VecDeque`, the returned result is unspecified and meaningless.
///
/// If the value is found then [`Result::Ok`] is returned, containing the
/// index of the matching element. If there are multiple matches, then any
@@ -2456,7 +2466,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
///
/// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`].
///
- /// [`contains`]: VecDeque::contains
/// [`binary_search`]: VecDeque::binary_search
/// [`binary_search_by_key`]: VecDeque::binary_search_by_key
/// [`partition_point`]: VecDeque::partition_point
@@ -2496,10 +2505,11 @@ impl<T, A: Allocator> VecDeque<T, A> {
}
/// Binary searches this `VecDeque` with a key extraction function.
- /// This behaves similarly to [`contains`] if this `VecDeque` is sorted.
///
/// Assumes that the deque is sorted by the key, for instance with
/// [`make_contiguous().sort_by_key()`] using the same key extraction function.
+ /// If the deque is not sorted by the key, the returned result is
+ /// unspecified and meaningless.
///
/// If the value is found then [`Result::Ok`] is returned, containing the
/// index of the matching element. If there are multiple matches, then any
@@ -2509,7 +2519,6 @@ impl<T, A: Allocator> VecDeque<T, A> {
///
/// See also [`binary_search`], [`binary_search_by`], and [`partition_point`].
///
- /// [`contains`]: VecDeque::contains
/// [`make_contiguous().sort_by_key()`]: VecDeque::make_contiguous
/// [`binary_search`]: VecDeque::binary_search
/// [`binary_search_by`]: VecDeque::binary_search_by