Changes according to code review

This commit is contained in:
Markus Everling 2022-11-25 03:36:11 +01:00
parent a1bf25e2bd
commit ecca8c5328
6 changed files with 180 additions and 143 deletions

View File

@ -53,27 +53,36 @@ pub(super) unsafe fn new(
}
// Only returns pointers to the slices, as that's
// all we need to drop them
fn as_slices(&self) -> (*mut [T], *mut [T]) {
// 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();
let wrapped_start = deque.wrap_idx(self.idx);
// 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.
if self.remaining <= deque.capacity() - wrapped_start {
// there's only one contigous slice
(
ptr::slice_from_raw_parts_mut(deque.ptr().add(wrapped_start), self.remaining),
&mut [] as *mut [T],
)
// 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 head_len = deque.capacity() - wrapped_start;
// this will never overflow due to the if condition
let tail_len = self.remaining - head_len;
(
ptr::slice_from_raw_parts_mut(deque.ptr().add(wrapped_start), head_len),
ptr::slice_from_raw_parts_mut(deque.ptr(), tail_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.
(deque.buffer_range(a_range), deque.buffer_range(b_range))
}
}
}
@ -103,8 +112,9 @@ fn drop(&mut self) {
impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> {
fn drop(&mut self) {
if self.0.remaining != 0 {
let (front, back) = self.0.as_slices();
unsafe {
// SAFETY: We just checked that `self.remaining != 0`.
let (front, back) = self.0.as_slices();
ptr::drop_in_place(front);
ptr::drop_in_place(back);
}
@ -133,7 +143,7 @@ fn drop(&mut self) {
source_deque.len = 0;
}
(0, _) => {
source_deque.head = source_deque.wrap_idx(drain_len);
source_deque.head = source_deque.to_physical_idx(drain_len);
source_deque.len = orig_len - drain_len;
}
(_, 0) => {
@ -143,15 +153,15 @@ fn drop(&mut self) {
if head_len <= tail_len {
source_deque.wrap_copy(
source_deque.head,
source_deque.wrap_idx(drain_len),
source_deque.to_physical_idx(drain_len),
head_len,
);
source_deque.head = source_deque.wrap_idx(drain_len);
source_deque.head = source_deque.to_physical_idx(drain_len);
source_deque.len = orig_len - drain_len;
} else {
source_deque.wrap_copy(
source_deque.wrap_idx(head_len + drain_len),
source_deque.wrap_idx(head_len),
source_deque.to_physical_idx(head_len + drain_len),
source_deque.to_physical_idx(head_len),
tail_len,
);
source_deque.len = orig_len - drain_len;
@ -162,14 +172,17 @@ fn drop(&mut self) {
}
let guard = DropGuard(self);
let (front, back) = guard.0.as_slices();
unsafe {
// since idx is a logical index, we don't need to worry about wrapping.
guard.0.idx += front.len();
guard.0.remaining -= front.len();
ptr::drop_in_place(front);
guard.0.remaining = 0;
ptr::drop_in_place(back);
if guard.0.remaining != 0 {
unsafe {
// SAFETY: We just checked that `self.remaining != 0`.
let (front, back) = guard.0.as_slices();
// since idx is a logical index, we don't need to worry about wrapping.
guard.0.idx += front.len();
guard.0.remaining -= front.len();
ptr::drop_in_place(front);
guard.0.remaining = 0;
ptr::drop_in_place(back);
}
}
// Dropping `guard` handles moving the remaining elements into place.
@ -185,7 +198,7 @@ fn next(&mut self) -> Option<T> {
if self.remaining == 0 {
return None;
}
let wrapped_idx = unsafe { self.deque.as_ref().wrap_idx(self.idx) };
let wrapped_idx = unsafe { self.deque.as_ref().to_physical_idx(self.idx) };
self.idx += 1;
self.remaining -= 1;
Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) })
@ -206,7 +219,7 @@ fn next_back(&mut self) -> Option<T> {
return None;
}
self.remaining -= 1;
let wrapped_idx = unsafe { self.deque.as_ref().wrap_idx(self.idx + self.remaining) };
let wrapped_idx = unsafe { self.deque.as_ref().to_physical_idx(self.idx + self.remaining) };
Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) })
}
}

View File

@ -39,15 +39,6 @@ fn clone(&self) -> Self {
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'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)
}
#[inline]
fn next(&mut self) -> Option<&'a T> {
match self.i1.next() {
@ -64,6 +55,15 @@ fn next(&mut self) -> Option<&'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)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
@ -75,17 +75,16 @@ fn fold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
F: FnMut(Acc, Self::Item) -> Acc,
{
let accum = self.i1.fold(accum, &mut f);
self.i2.fold(accum, f)
self.i2.fold(accum, &mut f)
}
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
let acc = self.i1.try_fold(init, &mut f)?;
self.i2.try_fold(acc, f)
self.i2.try_fold(acc, &mut f)
}
#[inline]
@ -117,7 +116,7 @@ fn next_back(&mut self) -> Option<&'a T> {
None => {
// most of the time, the iterator will either always
// call next(), or always call next_back(). By swapping
// the iterators once the first one is empty, we ensure
// the iterators once the second one is empty, we ensure
// that the first branch is taken as often as possible,
// without sacrificing correctness, as i2 is empty anyways
mem::swap(&mut self.i1, &mut self.i2);
@ -141,17 +140,16 @@ fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
F: FnMut(Acc, Self::Item) -> Acc,
{
let accum = self.i2.rfold(accum, &mut f);
self.i1.rfold(accum, f)
self.i1.rfold(accum, &mut f)
}
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
let acc = self.i2.try_rfold(init, &mut f)?;
self.i1.try_rfold(acc, f)
self.i1.try_rfold(acc, &mut f)
}
}

View File

@ -67,17 +67,16 @@ fn fold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
F: FnMut(Acc, Self::Item) -> Acc,
{
let accum = self.i1.fold(accum, &mut f);
self.i2.fold(accum, f)
self.i2.fold(accum, &mut f)
}
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
let acc = self.i1.try_fold(init, &mut f)?;
self.i2.try_fold(acc, f)
self.i2.try_fold(acc, &mut f)
}
#[inline]
@ -133,17 +132,16 @@ fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
F: FnMut(Acc, Self::Item) -> Acc,
{
let accum = self.i2.rfold(accum, &mut f);
self.i1.rfold(accum, f)
self.i1.rfold(accum, &mut f)
}
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
let acc = self.i2.try_rfold(init, &mut f)?;
self.i1.try_rfold(acc, f)
self.i1.try_rfold(acc, &mut f)
}
}

View File

@ -91,7 +91,12 @@ pub struct VecDeque<
T,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
// `self[0]`, if it exists, is `buf[head]`.
// `head < buf.capacity()`, unless `buf.capacity() == 0` when `head == 0`.
head: usize,
// the number of initialized elements, starting from the one at `head` and potentially wrapping around.
// if `len == 0`, the exact value of `head` is unimportant.
// if `T` is zero-Sized, then `self.len <= usize::MAX`, otherwise `self.len <= isize::MAX as usize`.
len: usize,
buf: RawVec<T, A>,
}
@ -106,15 +111,7 @@ fn clone(&self) -> Self {
fn clone_from(&mut self, other: &Self) {
self.clear();
self.head = 0;
self.reserve(other.len);
let (a, b) = other.as_slices();
unsafe {
self.write_iter(0, a.iter().cloned(), &mut 0);
self.write_iter(a.len(), b.iter().cloned(), &mut 0);
}
self.len = other.len;
self.extend(other.iter().cloned());
}
}
@ -133,13 +130,11 @@ fn drop(&mut self) {
}
}
if mem::needs_drop::<T>() {
let (front, back) = self.as_mut_slices();
unsafe {
let _back_dropper = Dropper(back);
// use drop for [T]
ptr::drop_in_place(front);
}
let (front, back) = self.as_mut_slices();
unsafe {
let _back_dropper = Dropper(back);
// use drop for [T]
ptr::drop_in_place(front);
}
// RawVec handles deallocation
}
@ -175,6 +170,15 @@ unsafe fn buffer_write(&mut self, off: usize, value: T) {
}
}
/// Returns a slice pointer into the buffer.
/// `range` must lie inside `0..self.capacity()`.
#[inline]
unsafe fn buffer_range(&self, range: Range<usize>) -> *mut [T] {
unsafe {
ptr::slice_from_raw_parts_mut(self.ptr().add(range.start), range.end - range.start)
}
}
/// Returns `true` if the buffer is at full capacity.
#[inline]
fn is_full(&self) -> bool {
@ -189,7 +193,7 @@ fn wrap_add(&self, idx: usize, addend: usize) -> usize {
}
#[inline]
fn wrap_idx(&self, idx: usize) -> usize {
fn to_physical_idx(&self, idx: usize) -> usize {
self.wrap_add(self.head, idx)
}
@ -473,6 +477,10 @@ unsafe fn handle_capacity_increase(&mut self, old_capacity: usize) {
debug_assert!(new_capacity >= old_capacity);
// Move the shortest contiguous section of the ring buffer
//
// H := head
// L := last element (`self.to_physical_idx(self.len - 1)`)
//
// H L
// [o o o o o o o . ]
// H L
@ -597,7 +605,7 @@ pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque<T, A> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.len {
let idx = self.wrap_idx(index);
let idx = self.to_physical_idx(index);
unsafe { Some(&*self.ptr().add(idx)) }
} else {
None
@ -626,7 +634,7 @@ pub fn get(&self, index: usize) -> Option<&T> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.len {
let idx = self.wrap_idx(index);
let idx = self.to_physical_idx(index);
unsafe { Some(&mut *self.ptr().add(idx)) }
} else {
None
@ -660,8 +668,8 @@ pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
pub fn swap(&mut self, i: usize, j: usize) {
assert!(i < self.len());
assert!(j < self.len());
let ri = self.wrap_idx(i);
let rj = self.wrap_idx(j);
let ri = self.to_physical_idx(i);
let rj = self.to_physical_idx(j);
unsafe { ptr::swap(self.ptr().add(ri), self.ptr().add(rj)) }
}
@ -913,6 +921,8 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
if self.len == 0 {
self.head = 0;
} else if self.head >= target_cap && tail_outside {
// H := head
// L := last element
// H L
// [. . . . . . . . o o o o o o o . ]
// H L
@ -923,6 +933,8 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
}
self.head = 0;
} else if self.head < target_cap && tail_outside {
// H := head
// L := last element
// H L
// [. . . o o o o o o o . . . . . . ]
// L H
@ -932,6 +944,8 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
self.copy_nonoverlapping(target_cap, 0, len);
}
} else if self.head >= target_cap {
// H := head
// L := last element
// L H
// [o o o o o . . . . . . . . . o o ]
// L H
@ -998,11 +1012,6 @@ fn drop(&mut self) {
return;
}
if !mem::needs_drop::<T>() {
self.len = len;
return;
}
let (front, back) = self.as_mut_slices();
if len > front.len() {
let begin = len - front.len();
@ -1102,18 +1111,10 @@ pub fn iter_mut(&mut self) -> IterMut<'_, T> {
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_slices(&self) -> (&[T], &[T]) {
if self.is_contiguous() {
(unsafe { slice::from_raw_parts(self.ptr().add(self.head), self.len) }, &[])
} else {
let head_len = self.capacity() - self.head;
let tail_len = self.len - head_len;
unsafe {
(
slice::from_raw_parts(self.ptr().add(self.head), head_len),
slice::from_raw_parts(self.ptr(), tail_len),
)
}
}
let (a_range, b_range) = self.slice_ranges(..);
// SAFETY: `slice_ranges` always returns valid ranges into
// the physical buffer.
unsafe { (&*self.buffer_range(a_range), &*self.buffer_range(b_range)) }
}
/// Returns a pair of slices which contain, in order, the contents of the
@ -1144,18 +1145,10 @@ pub fn as_slices(&self) -> (&[T], &[T]) {
#[inline]
#[stable(feature = "deque_extras_15", since = "1.5.0")]
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
if self.is_contiguous() {
(unsafe { slice::from_raw_parts_mut(self.ptr().add(self.head), self.len) }, &mut [])
} else {
let head_len = self.capacity() - self.head;
let tail_len = self.len - head_len;
unsafe {
(
slice::from_raw_parts_mut(self.ptr().add(self.head), head_len),
slice::from_raw_parts_mut(self.ptr(), tail_len),
)
}
}
let (a_range, b_range) = self.slice_ranges(..);
// SAFETY: `slice_ranges` always returns valid ranges into
// the physical buffer.
unsafe { (&mut *self.buffer_range(a_range), &mut *self.buffer_range(b_range)) }
}
/// Returns the number of elements in the deque.
@ -1192,18 +1185,37 @@ pub fn is_empty(&self) -> bool {
self.len == 0
}
/// 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>)
where
R: RangeBounds<usize>,
{
let Range { start, end } = slice::range(range, ..self.len);
let a_len = self.len.min(self.capacity() - self.head);
if end <= a_len {
(start..end, 0..0)
} else if start >= a_len {
(0..0, start - a_len..end - a_len)
let len = end - start;
if len == 0 {
(0..0, 0..0)
} else {
(start..a_len, 0..end - a_len)
// `slice::range` guarantees that `start <= end <= self.len`.
// because `len != 0`, we know that `start < end`, so `start < self.len`
// and the indexing is valid.
let wrapped_start = self.to_physical_idx(start);
// this subtraction can never overflow because `wrapped_start` is
// at most `self.capacity()` (and if `self.capacity != 0`, then `wrapped_start` is strictly less
// than `self.capacity`).
let head_len = self.capacity() - wrapped_start;
if head_len >= len {
// we know that `len + wrapped_start <= self.capacity <= usize::MAX`, so this addition can't overflow
(wrapped_start..wrapped_start + len, 0..0)
} else {
// can't overflow because of the if condition
let tail_len = len - head_len;
(wrapped_start..self.capacity(), 0..tail_len)
}
}
}
@ -1233,9 +1245,14 @@ pub fn range<R>(&self, range: R) -> Iter<'_, T>
where
R: RangeBounds<usize>,
{
let (a, b) = self.as_slices();
let (a_range, b_range) = self.slice_ranges(range);
Iter::new(a[a_range].iter(), b[b_range].iter())
// 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
// dereference the result.
let a = unsafe { &*self.buffer_range(a_range) };
let b = unsafe { &*self.buffer_range(b_range) };
Iter::new(a.iter(), b.iter())
}
/// Creates an iterator that covers the specified mutable range in the deque.
@ -1269,8 +1286,13 @@ pub fn range_mut<R>(&mut self, range: R) -> IterMut<'_, T>
R: RangeBounds<usize>,
{
let (a_range, b_range) = self.slice_ranges(range);
let (a, b) = self.as_mut_slices();
IterMut::new(a[a_range].iter_mut(), b[b_range].iter_mut())
// 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
// dereference the result.
let a = unsafe { &mut *self.buffer_range(a_range) };
let b = unsafe { &mut *self.buffer_range(b_range) };
IterMut::new(a.iter_mut(), b.iter_mut())
}
/// Removes the specified range from the deque in bulk, returning all
@ -1509,7 +1531,7 @@ pub fn pop_front(&mut self) -> Option<T> {
None
} else {
let old_head = self.head;
self.head = self.wrap_idx(1);
self.head = self.to_physical_idx(1);
self.len -= 1;
Some(unsafe { self.buffer_read(old_head) })
}
@ -1535,7 +1557,7 @@ pub fn pop_back(&mut self) -> Option<T> {
None
} else {
self.len -= 1;
Some(unsafe { self.buffer_read(self.wrap_idx(self.len)) })
Some(unsafe { self.buffer_read(self.to_physical_idx(self.len)) })
}
}
@ -1583,7 +1605,7 @@ pub fn push_back(&mut self, value: T) {
self.grow();
}
unsafe { self.buffer_write(self.wrap_idx(self.len), value) }
unsafe { self.buffer_write(self.to_physical_idx(self.len), value) }
self.len += 1;
}
@ -1700,8 +1722,8 @@ pub fn insert(&mut self, index: usize, value: T) {
// and panicked.
unsafe {
// see `remove()` for explanation why this wrap_copy() call is safe.
self.wrap_copy(self.wrap_idx(index), self.wrap_idx(index + 1), k);
self.buffer_write(self.wrap_idx(index), value);
self.wrap_copy(self.to_physical_idx(index), self.to_physical_idx(index + 1), k);
self.buffer_write(self.to_physical_idx(index), value);
self.len += 1;
}
} else {
@ -1709,7 +1731,7 @@ pub fn insert(&mut self, index: usize, value: T) {
self.head = self.wrap_sub(self.head, 1);
unsafe {
self.wrap_copy(old_head, self.head, index);
self.buffer_write(self.wrap_idx(index), value);
self.buffer_write(self.to_physical_idx(index), value);
self.len += 1;
}
}
@ -1742,7 +1764,7 @@ pub fn remove(&mut self, index: usize) -> Option<T> {
return None;
}
let wrapped_idx = self.wrap_idx(index);
let wrapped_idx = self.to_physical_idx(index);
let elem = unsafe { Some(self.buffer_read(wrapped_idx)) };
@ -1755,7 +1777,7 @@ pub fn remove(&mut self, index: usize) -> Option<T> {
self.len -= 1;
} else {
let old_head = self.head;
self.head = self.wrap_idx(1);
self.head = self.to_physical_idx(1);
unsafe { self.wrap_copy(old_head, self.head, index) };
self.len -= 1;
}
@ -1866,14 +1888,14 @@ pub fn append(&mut self, other: &mut Self) {
self.reserve(other.len);
unsafe {
let (left, right) = other.as_slices();
self.copy_slice(self.wrap_idx(self.len), left);
self.copy_slice(self.to_physical_idx(self.len), left);
// no overflow, because self.capacity() >= old_cap + left.len() >= self.len + left.len()
self.copy_slice(self.wrap_idx(self.len + left.len()), right);
self.copy_slice(self.to_physical_idx(self.len + left.len()), right);
}
// SAFETY: Update pointers after copying to avoid leaving doppelganger
// in case of panics.
self.len += other.len;
// Silently drop values in `other`.
// Now that we own its values, forget everything in `other`.
other.len = 0;
other.head = 0;
}
@ -1982,8 +2004,7 @@ fn grow(&mut self) {
// buffer without it being full emerge
debug_assert!(self.is_full());
let old_cap = self.capacity();
// if the cap was 0, we need to reserve at least 1.
self.buf.reserve(old_cap, old_cap.max(1));
self.buf.reserve_for_push(old_cap);
unsafe {
self.handle_capacity_increase(old_cap);
}
@ -2265,16 +2286,16 @@ pub fn rotate_right(&mut self, k: usize) {
unsafe fn rotate_left_inner(&mut self, mid: usize) {
debug_assert!(mid * 2 <= self.len());
unsafe {
self.wrap_copy(self.head, self.wrap_idx(self.len), mid);
self.wrap_copy(self.head, self.to_physical_idx(self.len), mid);
}
self.head = self.wrap_idx(mid);
self.head = self.to_physical_idx(mid);
}
unsafe fn rotate_right_inner(&mut self, k: usize) {
debug_assert!(k * 2 <= self.len());
self.head = self.wrap_sub(self.head, k);
unsafe {
self.wrap_copy(self.wrap_idx(self.len), self.head, k);
self.wrap_copy(self.to_physical_idx(self.len), self.head, k);
}
}
@ -2532,8 +2553,13 @@ pub fn resize(&mut self, new_len: usize, value: T) {
/// Returns the index in the underlying buffer for a given logical element index.
#[inline]
fn wrap_index(index: usize, size: usize) -> usize {
if index >= size { index - size } else { index }
fn wrap_index(logical_index: usize, capacity: usize) -> usize {
debug_assert!(
(logical_index == 0 && capacity == 0)
|| logical_index < capacity
|| (logical_index - capacity) < capacity
);
if logical_index >= capacity { logical_index - capacity } else { logical_index }
}
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -38,7 +38,7 @@ impl<T, I, A: Allocator> SpecExtend<T, I> for VecDeque<T, A>
// and `room == self.capacity() - self.len`
// => `self.len + room <= self.capacity()`
self.write_iter_wrapping(
self.wrap_idx(self.len),
self.to_physical_idx(self.len),
ByRefSized(&mut iter).take(room),
room,
);
@ -63,8 +63,9 @@ impl<T, I, A: Allocator> SpecExtend<T, I> for VecDeque<T, A>
);
self.reserve(additional);
let written =
unsafe { self.write_iter_wrapping(self.wrap_idx(self.len), iter, additional) };
let written = unsafe {
self.write_iter_wrapping(self.to_physical_idx(self.len), iter, additional)
};
debug_assert_eq!(
additional, written,
@ -87,7 +88,7 @@ fn spec_extend(&mut self, mut iterator: vec::IntoIter<T>) {
self.reserve(slice.len());
unsafe {
self.copy_slice(self.wrap_idx(self.len), slice);
self.copy_slice(self.to_physical_idx(self.len), slice);
self.len += slice.len();
}
iterator.forget_remaining_elements();
@ -113,7 +114,7 @@ fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) {
self.reserve(slice.len());
unsafe {
self.copy_slice(self.wrap_idx(self.len), slice);
self.copy_slice(self.to_physical_idx(self.len), slice);
self.len += slice.len();
}
}

View File

@ -257,13 +257,14 @@ fn test_swap_panic() {
#[test]
fn test_reserve_exact() {
let mut tester: VecDeque<i32> = VecDeque::with_capacity(1);
assert!(tester.capacity() == 1);
assert_eq!(tester.capacity(), 1);
tester.reserve_exact(50);
assert!(tester.capacity() >= 50);
assert_eq!(tester.capacity(), 50);
tester.reserve_exact(40);
assert!(tester.capacity() >= 40);
// reserving won't shrink the buffer
assert_eq!(tester.capacity(), 50);
tester.reserve_exact(200);
assert!(tester.capacity() >= 200);
assert_eq!(tester.capacity(), 200);
}
#[test]
@ -479,7 +480,7 @@ fn make_contiguous_big_tail() {
assert_eq!(tester.capacity(), 15);
assert_eq!((&[9, 8, 7, 6, 5, 4, 3] as &[_], &[0, 1, 2] as &[_]), tester.as_slices());
let expected_start = tester.wrap_idx(tester.len);
let expected_start = tester.to_physical_idx(tester.len);
tester.make_contiguous();
assert_eq!(tester.head, expected_start);
assert_eq!((&[9, 8, 7, 6, 5, 4, 3, 0, 1, 2] as &[_], &[] as &[_]), tester.as_slices());
@ -679,7 +680,7 @@ fn test_drain() {
let cap = tester.capacity();
for len in 0..=cap {
for head in 0..=cap {
for head in 0..cap {
for drain_start in 0..=len {
for drain_end in drain_start..=len {
tester.head = head;