diff options
Diffstat (limited to 'library/alloc/src')
| -rw-r--r-- | library/alloc/src/borrow.rs | 6 | ||||
| -rw-r--r-- | library/alloc/src/collections/binary_heap.rs | 3 | ||||
| -rw-r--r-- | library/alloc/src/collections/binary_heap/tests.rs | 489 | ||||
| -rw-r--r-- | library/alloc/src/collections/linked_list.rs | 10 | ||||
| -rw-r--r-- | library/alloc/src/collections/linked_list/tests.rs | 695 | ||||
| -rw-r--r-- | library/alloc/src/collections/vec_deque/mod.rs | 43 | ||||
| -rw-r--r-- | library/alloc/src/collections/vec_deque/spec_extend.rs | 73 | ||||
| -rw-r--r-- | library/alloc/src/collections/vec_deque/tests.rs | 294 | ||||
| -rw-r--r-- | library/alloc/src/rc.rs | 19 | ||||
| -rw-r--r-- | library/alloc/src/sync.rs | 19 | ||||
| -rw-r--r-- | library/alloc/src/vec/into_iter.rs | 5 | ||||
| -rw-r--r-- | library/alloc/src/vec/is_zero.rs | 9 | ||||
| -rw-r--r-- | library/alloc/src/vec/mod.rs | 42 | ||||
| -rw-r--r-- | library/alloc/src/vec/spec_extend.rs | 2 |
14 files changed, 1627 insertions, 82 deletions
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 8b13e36c4b3..cb4e438f8be 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -292,8 +292,7 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> { /// /// # Examples /// - /// Calling `into_owned` on a `Cow::Borrowed` clones the underlying data - /// and becomes a `Cow::Owned`: + /// Calling `into_owned` on a `Cow::Borrowed` returns a clone of the borrowed data: /// /// ``` /// use std::borrow::Cow; @@ -307,7 +306,8 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> { /// ); /// ``` /// - /// Calling `into_owned` on a `Cow::Owned` is a no-op: + /// Calling `into_owned` on a `Cow::Owned` returns the owned data. The data is moved out of the + /// `Cow` without being cloned. /// /// ``` /// use std::borrow::Cow; diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index ef5bef0253a..c3c1d0c92a8 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -155,6 +155,9 @@ use crate::vec::{self, AsVecIntoIter, Vec}; use super::SpecExtend; +#[cfg(test)] +mod tests; + /// A priority queue implemented with a binary heap. /// /// This will be a max-heap. diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs new file mode 100644 index 00000000000..7c758dbb3ab --- /dev/null +++ b/library/alloc/src/collections/binary_heap/tests.rs @@ -0,0 +1,489 @@ +use super::*; +use crate::boxed::Box; +use std::iter::TrustedLen; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::sync::atomic::{AtomicU32, Ordering}; + +#[test] +fn test_iterator() { + let data = vec![5, 9, 3]; + let iterout = [9, 5, 3]; + let heap = BinaryHeap::from(data); + let mut i = 0; + for el in &heap { + assert_eq!(*el, iterout[i]); + i += 1; + } +} + +#[test] +fn test_iter_rev_cloned_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.iter().rev().cloned().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![9, 5, 3]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.into_iter().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_size_hint() { + let data = vec![5, 9]; + let pq = BinaryHeap::from(data); + + let mut it = pq.into_iter(); + + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next(), Some(9)); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next(), Some(5)); + + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_into_iter_rev_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.into_iter().rev().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_sorted_collect() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + let it = heap.into_iter_sorted(); + let sorted = it.collect::<Vec<_>>(); + assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]); +} + +#[test] +fn test_drain_sorted_collect() { + let mut heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + let it = heap.drain_sorted(); + let sorted = it.collect::<Vec<_>>(); + assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]); +} + +fn check_exact_size_iterator<I: ExactSizeIterator>(len: usize, it: I) { + let mut it = it; + + for i in 0..it.len() { + let (lower, upper) = it.size_hint(); + assert_eq!(Some(lower), upper); + assert_eq!(lower, len - i); + assert_eq!(it.len(), len - i); + it.next(); + } + assert_eq!(it.len(), 0); + assert!(it.is_empty()); +} + +#[test] +fn test_exact_size_iterator() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_exact_size_iterator(heap.len(), heap.iter()); + check_exact_size_iterator(heap.len(), heap.clone().into_iter()); + check_exact_size_iterator(heap.len(), heap.clone().into_iter_sorted()); + check_exact_size_iterator(heap.len(), heap.clone().drain()); + check_exact_size_iterator(heap.len(), heap.clone().drain_sorted()); +} + +fn check_trusted_len<I: TrustedLen>(len: usize, it: I) { + let mut it = it; + for i in 0..len { + let (lower, upper) = it.size_hint(); + if upper.is_some() { + assert_eq!(Some(lower), upper); + assert_eq!(lower, len - i); + } + it.next(); + } +} + +#[test] +fn test_trusted_len() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_trusted_len(heap.len(), heap.clone().into_iter_sorted()); + check_trusted_len(heap.len(), heap.clone().drain_sorted()); +} + +#[test] +fn test_peek_and_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut sorted = data.clone(); + sorted.sort(); + let mut heap = BinaryHeap::from(data); + while !heap.is_empty() { + assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); + assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); + } +} + +#[test] +fn test_peek_mut() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut heap = BinaryHeap::from(data); + assert_eq!(heap.peek(), Some(&10)); + { + let mut top = heap.peek_mut().unwrap(); + *top -= 2; + } + assert_eq!(heap.peek(), Some(&9)); +} + +#[test] +fn test_peek_mut_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut heap = BinaryHeap::from(data); + assert_eq!(heap.peek(), Some(&10)); + { + let mut top = heap.peek_mut().unwrap(); + *top -= 2; + assert_eq!(PeekMut::pop(top), 8); + } + assert_eq!(heap.peek(), Some(&9)); +} + +#[test] +fn test_push() { + let mut heap = BinaryHeap::from(vec![2, 4, 9]); + assert_eq!(heap.len(), 3); + assert!(*heap.peek().unwrap() == 9); + heap.push(11); + assert_eq!(heap.len(), 4); + assert!(*heap.peek().unwrap() == 11); + heap.push(5); + assert_eq!(heap.len(), 5); + assert!(*heap.peek().unwrap() == 11); + heap.push(27); + assert_eq!(heap.len(), 6); + assert!(*heap.peek().unwrap() == 27); + heap.push(3); + assert_eq!(heap.len(), 7); + assert!(*heap.peek().unwrap() == 27); + heap.push(103); + assert_eq!(heap.len(), 8); + assert!(*heap.peek().unwrap() == 103); +} + +#[test] +fn test_push_unique() { + let mut heap = BinaryHeap::<Box<_>>::from(vec![box 2, box 4, box 9]); + assert_eq!(heap.len(), 3); + assert!(**heap.peek().unwrap() == 9); + heap.push(box 11); + assert_eq!(heap.len(), 4); + assert!(**heap.peek().unwrap() == 11); + heap.push(box 5); + assert_eq!(heap.len(), 5); + assert!(**heap.peek().unwrap() == 11); + heap.push(box 27); + assert_eq!(heap.len(), 6); + assert!(**heap.peek().unwrap() == 27); + heap.push(box 3); + assert_eq!(heap.len(), 7); + assert!(**heap.peek().unwrap() == 27); + heap.push(box 103); + assert_eq!(heap.len(), 8); + assert!(**heap.peek().unwrap() == 103); +} + +fn check_to_vec(mut data: Vec<i32>) { + let heap = BinaryHeap::from(data.clone()); + let mut v = heap.clone().into_vec(); + v.sort(); + data.sort(); + + assert_eq!(v, data); + assert_eq!(heap.into_sorted_vec(), data); +} + +#[test] +fn test_to_vec() { + check_to_vec(vec![]); + check_to_vec(vec![5]); + check_to_vec(vec![3, 2]); + check_to_vec(vec![2, 3]); + check_to_vec(vec![5, 1, 2]); + check_to_vec(vec![1, 100, 2, 3]); + check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); + check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); + check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); +} + +#[test] +fn test_in_place_iterator_specialization() { + let src: Vec<usize> = vec![1, 2, 3]; + let src_ptr = src.as_ptr(); + let heap: BinaryHeap<_> = src.into_iter().map(std::convert::identity).collect(); + let heap_ptr = heap.iter().next().unwrap() as *const usize; + assert_eq!(src_ptr, heap_ptr); + let sink: Vec<_> = heap.into_iter().map(std::convert::identity).collect(); + let sink_ptr = sink.as_ptr(); + assert_eq!(heap_ptr, sink_ptr); +} + +#[test] +fn test_empty_pop() { + let mut heap = BinaryHeap::<i32>::new(); + assert!(heap.pop().is_none()); +} + +#[test] +fn test_empty_peek() { + let empty = BinaryHeap::<i32>::new(); + assert!(empty.peek().is_none()); +} + +#[test] +fn test_empty_peek_mut() { + let mut empty = BinaryHeap::<i32>::new(); + assert!(empty.peek_mut().is_none()); +} + +#[test] +fn test_from_iter() { + let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); + + for &x in &xs { + assert_eq!(q.pop().unwrap(), x); + } +} + +#[test] +fn test_drain() { + let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); + + assert_eq!(q.drain().take(5).count(), 5); + + assert!(q.is_empty()); +} + +#[test] +fn test_drain_sorted() { + let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); + + assert_eq!(q.drain_sorted().take(5).collect::<Vec<_>>(), vec![9, 8, 7, 6, 5]); + + assert!(q.is_empty()); +} + +#[test] +fn test_drain_sorted_leak() { + static DROPS: AtomicU32 = AtomicU32::new(0); + + #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] + struct D(u32, bool); + + impl Drop for D { + fn drop(&mut self) { + DROPS.fetch_add(1, Ordering::SeqCst); + + if self.1 { + panic!("panic in `drop`"); + } + } + } + + let mut q = BinaryHeap::from(vec![ + D(0, false), + D(1, false), + D(2, false), + D(3, true), + D(4, false), + D(5, false), + ]); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).ok(); + + assert_eq!(DROPS.load(Ordering::SeqCst), 6); +} + +#[test] +fn test_extend_ref() { + let mut a = BinaryHeap::new(); + a.push(1); + a.push(2); + + a.extend(&[3, 4, 5]); + + assert_eq!(a.len(), 5); + assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); + + let mut a = BinaryHeap::new(); + a.push(1); + a.push(2); + let mut b = BinaryHeap::new(); + b.push(3); + b.push(4); + b.push(5); + + a.extend(&b); + + assert_eq!(a.len(), 5); + assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); +} + +#[test] +fn test_append() { + let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); + let mut b = BinaryHeap::from(vec![-20, 5, 43]); + + a.append(&mut b); + + assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); + assert!(b.is_empty()); +} + +#[test] +fn test_append_to_empty() { + let mut a = BinaryHeap::new(); + let mut b = BinaryHeap::from(vec![-20, 5, 43]); + + a.append(&mut b); + + assert_eq!(a.into_sorted_vec(), [-20, 5, 43]); + assert!(b.is_empty()); +} + +#[test] +fn test_extend_specialization() { + let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); + let b = BinaryHeap::from(vec![-20, 5, 43]); + + a.extend(b); + + assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); +} + +#[allow(dead_code)] +fn assert_covariance() { + fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { + d + } +} + +#[test] +fn test_retain() { + let mut a = BinaryHeap::from(vec![100, 10, 50, 1, 2, 20, 30]); + a.retain(|&x| x != 2); + + // Check that 20 moved into 10's place. + assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); + + a.retain(|_| true); + + assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); + + a.retain(|&x| x < 50); + + assert_eq!(a.clone().into_vec(), [30, 20, 10, 1]); + + a.retain(|_| false); + + assert!(a.is_empty()); +} + +// old binaryheap failed this test +// +// Integrity means that all elements are present after a comparison panics, +// even if the order might not be correct. +// +// Destructors must be called exactly once per element. +// FIXME: re-enable emscripten once it can unwind again +#[test] +#[cfg(not(target_os = "emscripten"))] +fn panic_safe() { + use rand::{seq::SliceRandom, thread_rng}; + use std::cmp; + use std::panic::{self, AssertUnwindSafe}; + use std::sync::atomic::{AtomicUsize, Ordering}; + + static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); + + #[derive(Eq, PartialEq, Ord, Clone, Debug)] + struct PanicOrd<T>(T, bool); + + impl<T> Drop for PanicOrd<T> { + fn drop(&mut self) { + // update global drop count + DROP_COUNTER.fetch_add(1, Ordering::SeqCst); + } + } + + impl<T: PartialOrd> PartialOrd for PanicOrd<T> { + fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { + if self.1 || other.1 { + panic!("Panicking comparison"); + } + self.0.partial_cmp(&other.0) + } + } + let mut rng = thread_rng(); + const DATASZ: usize = 32; + // Miri is too slow + let ntest = if cfg!(miri) { 1 } else { 10 }; + + // don't use 0 in the data -- we want to catch the zeroed-out case. + let data = (1..=DATASZ).collect::<Vec<_>>(); + + // since it's a fuzzy test, run several tries. + for _ in 0..ntest { + for i in 1..=DATASZ { + DROP_COUNTER.store(0, Ordering::SeqCst); + + let mut panic_ords: Vec<_> = + data.iter().filter(|&&x| x != i).map(|&x| PanicOrd(x, false)).collect(); + let panic_item = PanicOrd(i, true); + + // heapify the sane items + panic_ords.shuffle(&mut rng); + let mut heap = BinaryHeap::from(panic_ords); + let inner_data; + + { + // push the panicking item to the heap and catch the panic + let thread_result = { + let mut heap_ref = AssertUnwindSafe(&mut heap); + panic::catch_unwind(move || { + heap_ref.push(panic_item); + }) + }; + assert!(thread_result.is_err()); + + // Assert no elements were dropped + let drops = DROP_COUNTER.load(Ordering::SeqCst); + assert!(drops == 0, "Must not drop items. drops={}", drops); + inner_data = heap.clone().into_vec(); + drop(heap); + } + let drops = DROP_COUNTER.load(Ordering::SeqCst); + assert_eq!(drops, DATASZ); + + let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::<Vec<_>>(); + data_sorted.sort(); + assert_eq!(data_sorted, data); + } + } +} diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index d81f24e7202..736b38370ab 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -645,7 +645,7 @@ impl<T> LinkedList<T> { /// Returns `true` if the `LinkedList` contains an element equal to the /// given value. /// - /// This operation should compute in *O*(*n*) time. + /// This operation should compute linearly in *O*(*n*) time. /// /// # Examples /// @@ -1569,7 +1569,7 @@ impl<'a, T> CursorMut<'a, T> { /// Appends an element to the front of the cursor's parent list. The node /// that the cursor points to is unchanged, even if it is the "ghost" node. /// - /// This operation should compute in O(1) time. + /// This operation should compute in *O*(1) time. // `push_front` continues to point to "ghost" when it addes a node to mimic // the behavior of `insert_before` on an empty list. #[unstable(feature = "linked_list_cursors", issue = "58533")] @@ -1584,7 +1584,7 @@ impl<'a, T> CursorMut<'a, T> { /// Appends an element to the back of the cursor's parent list. The node /// that the cursor points to is unchanged, even if it is the "ghost" node. /// - /// This operation should compute in O(1) time. + /// This operation should compute in *O*(1) time. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn push_back(&mut self, elt: T) { // Safety: We know that `push_back` does not change the position in @@ -1603,7 +1603,7 @@ impl<'a, T> CursorMut<'a, T> { /// unchanged, unless it was pointing to the front element. In that case, it /// points to the new front element. /// - /// This operation should compute in O(1) time. + /// This operation should compute in *O*(1) time. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn pop_front(&mut self) -> Option<T> { // We can't check if current is empty, we must check the list directly. @@ -1630,7 +1630,7 @@ impl<'a, T> CursorMut<'a, T> { /// unchanged, unless it was pointing to the back element. In that case, it /// points to the "ghost" element. /// - /// This operation should compute in O(1) time. + /// This operation should compute in *O*(1) time. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn pop_back(&mut self) -> Option<T> { if self.list.is_empty() { diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs index 5a65ed7a962..38c702aa387 100644 --- a/library/alloc/src/collections/linked_list/tests.rs +++ b/library/alloc/src/collections/linked_list/tests.rs @@ -1,10 +1,55 @@ use super::*; +use crate::vec::Vec; +use std::panic::{catch_unwind, AssertUnwindSafe}; use std::thread; -use std::vec::Vec; use rand::{thread_rng, RngCore}; +#[test] +fn test_basic() { + let mut m = LinkedList::<Box<_>>::new(); + assert_eq!(m.pop_front(), None); + assert_eq!(m.pop_back(), None); + assert_eq!(m.pop_front(), None); + m.push_front(box 1); + assert_eq!(m.pop_front(), Some(box 1)); + m.push_back(box 2); + m.push_back(box 3); + assert_eq!(m.len(), 2); + assert_eq!(m.pop_front(), Some(box 2)); + assert_eq!(m.pop_front(), Some(box 3)); + assert_eq!(m.len(), 0); + assert_eq!(m.pop_front(), None); + m.push_back(box 1); + m.push_back(box 3); + m.push_back(box 5); + m.push_back(box 7); + assert_eq!(m.pop_front(), Some(box 1)); + + let mut n = LinkedList::new(); + n.push_front(2); + n.push_front(3); + { + assert_eq!(n.front().unwrap(), &3); + let x = n.front_mut().unwrap(); + assert_eq!(*x, 3); + *x = 0; + } + { + assert_eq!(n.back().unwrap(), &2); + let y = n.back_mut().unwrap(); + assert_eq!(*y, 2); + *y = 1; + } + assert_eq!(n.pop_front(), Some(0)); + assert_eq!(n.pop_front(), Some(1)); +} + +fn generate_test() -> LinkedList<i32> { + list_from(&[0, 1, 2, 3, 4, 5, 6]) +} + fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> { v.iter().cloned().collect() } @@ -111,6 +156,123 @@ fn test_append() { } #[test] +fn test_iterator() { + let m = generate_test(); + for (i, elt) in m.iter().enumerate() { + assert_eq!(i as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iterator_clone() { + let mut n = LinkedList::new(); + n.push_back(2); + n.push_back(3); + n.push_back(4); + let mut it = n.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next_back(), jt.next_back()); + assert_eq!(it.next(), jt.next()); +} + +#[test] +fn test_iterator_double_end() { + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(it.next().unwrap(), &6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next_back().unwrap(), &5); + assert_eq!(it.next_back(), None); + assert_eq!(it.next(), None); +} + +#[test] +fn test_rev_iter() { + let m = generate_test(); + for (i, elt) in m.iter().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().rev().next(), None); + n.push_front(4); + let mut it = n.iter().rev(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_mut_iter() { + let mut m = generate_test(); + let mut len = m.len(); + for (i, elt) in m.iter_mut().enumerate() { + assert_eq!(i as i32, *elt); + len -= 1; + } + assert_eq!(len, 0); + let mut n = LinkedList::new(); + assert!(n.iter_mut().next().is_none()); + n.push_front(4); + n.push_back(5); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (2, Some(2))); + assert!(it.next().is_some()); + assert!(it.next().is_some()); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_mut_double_end() { + let mut n = LinkedList::new(); + assert!(n.iter_mut().next_back().is_none()); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(*it.next().unwrap(), 6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(*it.next_back().unwrap(), 4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(*it.next_back().unwrap(), 5); + assert!(it.next_back().is_none()); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_rev_iter() { + let mut m = generate_test(); + for (i, elt) in m.iter_mut().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert!(n.iter_mut().rev().next().is_none()); + n.push_front(4); + let mut it = n.iter_mut().rev(); + assert!(it.next().is_some()); + assert!(it.next().is_none()); +} + +#[test] fn test_clone_from() { // Short cloned from long { @@ -168,13 +330,60 @@ fn test_send() { } #[test] -fn test_fuzz() { - for _ in 0..25 { - fuzz_test(3); - fuzz_test(16); - #[cfg(not(miri))] // Miri is too slow - fuzz_test(189); - } +fn test_eq() { + let mut n = list_from(&[]); + let mut m = list_from(&[]); + assert!(n == m); + n.push_front(1); + assert!(n != m); + m.push_back(1); + assert!(n == m); + + let n = list_from(&[2, 3, 4]); + let m = list_from(&[1, 2, 3]); + assert!(n != m); +} + +#[test] +fn test_ord() { + let n = list_from(&[]); + let m = list_from(&[1, 2, 3]); + assert!(n < m); + assert!(m > n); + assert!(n <= n); + assert!(n >= n); +} + +#[test] +fn test_ord_nan() { + let nan = 0.0f64 / 0.0; + let n = list_from(&[nan]); + let m = list_from(&[nan]); + assert!(!(n < m)); + assert!(!(n > m)); + assert!(!(n <= m)); + assert!(!(n >= m)); + + let n = list_from(&[nan]); + let one = list_from(&[1.0f64]); + assert!(!(n < one)); + assert!(!(n > one)); + assert!(!(n <= one)); + assert!(!(n >= one)); + + let u = list_from(&[1.0f64, 2.0, nan]); + let v = list_from(&[1.0f64, 2.0, 3.0]); + assert!(!(u < v)); + assert!(!(u > v)); + assert!(!(u <= v)); + assert!(!(u >= v)); + + let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]); + let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]); + assert!(!(s < t)); + assert!(s > one); + assert!(!(s <= one)); + assert!(s >= one); } #[test] @@ -215,6 +424,62 @@ fn test_split_off() { } } +#[test] +fn test_split_off_2() { + // singleton + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(0); + assert_eq!(m.len(), 0); + assert_eq!(p.len(), 1); + assert_eq!(p.back(), Some(&1)); + assert_eq!(p.front(), Some(&1)); + } + + // not singleton, forwards + { + let u = vec![1, 2, 3, 4, 5]; + let mut m = list_from(&u); + let mut n = m.split_off(2); + assert_eq!(m.len(), 2); + assert_eq!(n.len(), 3); + for elt in 1..3 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 3..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + // not singleton, backwards + { + let u = vec![1, 2, 3, 4, 5]; + let mut m = list_from(&u); + let mut n = m.split_off(4); + assert_eq!(m.len(), 4); + assert_eq!(n.len(), 1); + for elt in 1..5 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 5..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + + // no-op on the last index + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(1); + assert_eq!(m.len(), 1); + assert_eq!(p.len(), 0); + assert_eq!(m.back(), Some(&1)); + assert_eq!(m.front(), Some(&1)); + } +} + fn fuzz_test(sz: i32) { let mut m: LinkedList<_> = LinkedList::new(); let mut v = vec![]; @@ -254,6 +519,25 @@ fn fuzz_test(sz: i32) { } #[test] +fn test_fuzz() { + for _ in 0..25 { + fuzz_test(3); + fuzz_test(16); + #[cfg(not(miri))] // Miri is too slow + fuzz_test(189); + } +} + +#[test] +fn test_show() { + let list: LinkedList<_> = (0..10).collect(); + assert_eq!(format!("{list:?}"), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let list: LinkedList<_> = ["just", "one", "test", "more"].into_iter().collect(); + assert_eq!(format!("{list:?}"), "[\"just\", \"one\", \"test\", \"more\"]"); +} + +#[test] fn drain_filter_test() { let mut m: LinkedList<u32> = LinkedList::new(); m.extend(&[1, 2, 3, 4, 5, 6]); @@ -475,3 +759,398 @@ fn test_cursor_pop_front_back() { assert_eq!(c.current(), None); assert_eq!(c.index, 2); } + +#[test] +fn test_extend_ref() { + let mut a = LinkedList::new(); + a.push_back(1); + + a.extend(&[2, 3, 4]); + + assert_eq!(a.len(), 4); + assert_eq!(a, list_from(&[1, 2, 3, 4])); + + let mut b = LinkedList::new(); + b.push_back(5); + b.push_back(6); + a.extend(&b); + + assert_eq!(a.len(), 6); + assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6])); +} + +#[test] +fn test_extend() { + let mut a = LinkedList::new(); + a.push_back(1); + a.extend(vec![2, 3, 4]); // uses iterator + + assert_eq!(a.len(), 4); + assert!(a.iter().eq(&[1, 2, 3, 4])); + + let b: LinkedList<_> = [5, 6, 7].into_iter().collect(); + a.extend(b); // specializes to `append` + + assert_eq!(a.len(), 7); + assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7])); +} + +#[test] +fn test_contains() { + let mut l = LinkedList::new(); + l.extend(&[2, 3, 4]); + + assert!(l.contains(&3)); + assert!(!l.contains(&1)); + + l.clear(); + + assert!(!l.contains(&3)); +} + +#[test] +fn drain_filter_empty() { + let mut list: LinkedList<i32> = LinkedList::new(); + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); +} + +#[test] +fn drain_filter_zst() { + let mut list: LinkedList<_> = [(), (), (), (), ()].into_iter().collect(); + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); +} + +#[test] +fn drain_filter_false() { + let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| false); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + for _ in iter.by_ref() { + count += 1; + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, 0); + assert_eq!(list.len(), initial_len); + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +} + +#[test] +fn drain_filter_true() { + let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); +} + +#[test] +fn drain_filter_complex() { + { + // [+xxx++++++xxxxx++++x+x++] + let mut list = [ + 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, + 39, + ] + .into_iter() + .collect::<LinkedList<_>>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 14); + assert_eq!( + list.into_iter().collect::<Vec<_>>(), + vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] + ); + } + + { + // [xxx++++++xxxxx++++x+x++] + let mut list = + [2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39] + .into_iter() + .collect::<LinkedList<_>>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 13); + assert_eq!( + list.into_iter().collect::<Vec<_>>(), + vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] + ); + } + + { + // [xxx++++++xxxxx++++x+x] + let mut list = + [2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36] + .into_iter() + .collect::<LinkedList<_>>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 11); + assert_eq!( + list.into_iter().collect::<Vec<_>>(), + vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35] + ); + } + + { + // [xxxxxxxxxx+++++++++++] + let mut list = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19] + .into_iter() + .collect::<LinkedList<_>>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(list.len(), 10); + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } + + { + // [+++++++++++xxxxxxxxxx] + let mut list = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + .into_iter() + .collect::<LinkedList<_>>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(list.len(), 10); + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } +} + +#[test] +fn drain_filter_drop_panic_leak() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + q.push_front(D(false)); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok(); + + assert_eq!(unsafe { DROPS }, 8); + assert!(q.is_empty()); +} + +#[test] +fn drain_filter_pred_panic_leak() { + static mut DROPS: i32 = 0; + + #[derive(Debug)] + struct D(u32); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(3)); + q.push_back(D(4)); + q.push_back(D(5)); + q.push_back(D(6)); + q.push_back(D(7)); + q.push_front(D(2)); + q.push_front(D(1)); + q.push_front(D(0)); + + catch_unwind(AssertUnwindSafe(|| { + drop(q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true })) + })) + .ok(); + + assert_eq!(unsafe { DROPS }, 2); // 0 and 1 + assert_eq!(q.len(), 6); +} + +#[test] +fn test_drop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + drop(ring); + + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_with_pop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + + drop(ring.pop_back()); + drop(ring.pop_front()); + assert_eq!(unsafe { DROPS }, 2); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_clear() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + ring.clear(); + assert_eq!(unsafe { DROPS }, 4); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_panic() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + + catch_unwind(move || drop(q)).ok(); + + assert_eq!(unsafe { DROPS }, 8); +} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 488671d8d8d..5f1a6848ae6 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -54,6 +54,10 @@ use self::ring_slices::RingSlices; mod ring_slices; +use self::spec_extend::SpecExtend; + +mod spec_extend; + #[cfg(test)] mod tests; @@ -1342,6 +1346,12 @@ impl<T, A: Allocator> VecDeque<T, A> { /// Returns `true` if the deque contains an element equal to the /// given value. /// + /// This operation is *O*(*n*). + /// + /// Note that if you have a sorted `VecDeque`, [`binary_search`] may be faster. + /// + /// [`binary_search`]: VecDeque::binary_search + /// /// # Examples /// /// ``` @@ -2560,7 +2570,8 @@ impl<T, A: Allocator> VecDeque<T, A> { } } - /// Binary searches the sorted deque for a given element. + /// Binary searches this `VecDeque` for a given element. + /// This behaves similarly to [`contains`] if this `VecDeque` is sorted. /// /// If the value is found then [`Result::Ok`] is returned, containing the /// index of the matching element. If there are multiple matches, then any @@ -2570,6 +2581,7 @@ 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 @@ -2614,7 +2626,8 @@ impl<T, A: Allocator> VecDeque<T, A> { self.binary_search_by(|e| e.cmp(x)) } - /// Binary searches the sorted deque with a comparator function. + /// 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 @@ -2629,6 +2642,7 @@ 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 @@ -2667,7 +2681,8 @@ impl<T, A: Allocator> VecDeque<T, A> { } } - /// Binary searches the sorted deque with a key extraction function. + /// 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. @@ -2680,6 +2695,7 @@ 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 @@ -2958,24 +2974,7 @@ impl<'a, T, A: Allocator> IntoIterator for &'a mut VecDeque<T, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<T, A: Allocator> Extend<T> for VecDeque<T, A> { fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { - // This function should be the moral equivalent of: - // - // for item in iter.into_iter() { - // self.push_back(item); - // } - let mut iter = iter.into_iter(); - while let Some(element) = iter.next() { - if self.len() == self.capacity() { - let (lower, _) = iter.size_hint(); - self.reserve(lower.saturating_add(1)); - } - - let head = self.head; - self.head = self.wrap_add(self.head, 1); - unsafe { - self.buffer_write(head, element); - } - } + <Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter()); } #[inline] @@ -2992,7 +2991,7 @@ impl<T, A: Allocator> Extend<T> for VecDeque<T, A> { #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque<T, A> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { - self.extend(iter.into_iter().cloned()); + self.spec_extend(iter.into_iter()); } #[inline] diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs new file mode 100644 index 00000000000..172f2e9068f --- /dev/null +++ b/library/alloc/src/collections/vec_deque/spec_extend.rs @@ -0,0 +1,73 @@ +use crate::alloc::Allocator; +use crate::vec; +use core::slice; + +use super::VecDeque; + +// Specialization trait used for VecDeque::extend +pub(super) trait SpecExtend<T, I> { + fn spec_extend(&mut self, iter: I); +} + +impl<T, I, A: Allocator> SpecExtend<T, I> for VecDeque<T, A> +where + I: Iterator<Item = T>, +{ + default fn spec_extend(&mut self, mut iter: I) { + // This function should be the moral equivalent of: + // + // for item in iter { + // self.push_back(item); + // } + while let Some(element) = iter.next() { + if self.len() == self.capacity() { + let (lower, _) = iter.size_hint(); + self.reserve(lower.saturating_add(1)); + } + + let head = self.head; + self.head = self.wrap_add(self.head, 1); + unsafe { + self.buffer_write(head, element); + } + } + } +} + +impl<T, A: Allocator> SpecExtend<T, vec::IntoIter<T>> for VecDeque<T, A> { + fn spec_extend(&mut self, mut iterator: vec::IntoIter<T>) { + let slice = iterator.as_slice(); + self.reserve(slice.len()); + + unsafe { + self.copy_slice(self.head, slice); + self.head = self.wrap_add(self.head, slice.len()); + } + iterator.forget_remaining_elements(); + } +} + +impl<'a, T: 'a, I, A: Allocator> SpecExtend<&'a T, I> for VecDeque<T, A> +where + I: Iterator<Item = &'a T>, + T: Copy, +{ + default fn spec_extend(&mut self, iterator: I) { + self.spec_extend(iterator.copied()) + } +} + +impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for VecDeque<T, A> +where + T: Copy, +{ + fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { + let slice = iterator.as_slice(); + self.reserve(slice.len()); + + unsafe { + self.copy_slice(self.head, slice); + self.head = self.wrap_add(self.head, slice.len()); + } + } +} diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index 2be83f68f01..f2869a54713 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -163,6 +163,300 @@ fn test_insert() { } #[test] +fn test_get() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + + assert_eq!(tester.len(), 3); + + assert_eq!(tester.get(1), Some(&2)); + assert_eq!(tester.get(2), Some(&3)); + assert_eq!(tester.get(0), Some(&1)); + assert_eq!(tester.get(3), None); + + tester.remove(0); + + assert_eq!(tester.len(), 2); + assert_eq!(tester.get(0), Some(&2)); + assert_eq!(tester.get(1), Some(&3)); + assert_eq!(tester.get(2), None); +} + +#[test] +fn test_get_mut() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + + assert_eq!(tester.len(), 3); + + if let Some(elem) = tester.get_mut(0) { + assert_eq!(*elem, 1); + *elem = 10; + } + + if let Some(elem) = tester.get_mut(2) { + assert_eq!(*elem, 3); + *elem = 30; + } + + assert_eq!(tester.get(0), Some(&10)); + assert_eq!(tester.get(2), Some(&30)); + assert_eq!(tester.get_mut(3), None); + + tester.remove(2); + + assert_eq!(tester.len(), 2); + assert_eq!(tester.get(0), Some(&10)); + assert_eq!(tester.get(1), Some(&2)); + assert_eq!(tester.get(2), None); +} + +#[test] +fn test_swap() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + + assert_eq!(tester, [1, 2, 3]); + + tester.swap(0, 0); + assert_eq!(tester, [1, 2, 3]); + tester.swap(0, 1); + assert_eq!(tester, [2, 1, 3]); + tester.swap(2, 1); + assert_eq!(tester, [2, 3, 1]); + tester.swap(1, 2); + assert_eq!(tester, [2, 1, 3]); + tester.swap(0, 2); + assert_eq!(tester, [3, 1, 2]); + tester.swap(2, 2); + assert_eq!(tester, [3, 1, 2]); +} + +#[test] +#[should_panic = "assertion failed: j < self.len()"] +fn test_swap_panic() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + tester.swap(2, 3); +} + +#[test] +fn test_reserve_exact() { + let mut tester: VecDeque<i32> = VecDeque::with_capacity(1); + assert!(tester.capacity() == 1); + tester.reserve_exact(50); + assert!(tester.capacity() >= 51); + tester.reserve_exact(40); + assert!(tester.capacity() >= 51); + tester.reserve_exact(200); + assert!(tester.capacity() >= 200); +} + +#[test] +#[should_panic = "capacity overflow"] +fn test_reserve_exact_panic() { + let mut tester: VecDeque<i32> = VecDeque::new(); + tester.reserve_exact(usize::MAX); +} + +#[test] +fn test_try_reserve_exact() { + let mut tester: VecDeque<i32> = VecDeque::with_capacity(1); + assert!(tester.capacity() == 1); + assert_eq!(tester.try_reserve_exact(100), Ok(())); + assert!(tester.capacity() >= 100); + assert_eq!(tester.try_reserve_exact(50), Ok(())); + assert!(tester.capacity() >= 100); + assert_eq!(tester.try_reserve_exact(200), Ok(())); + assert!(tester.capacity() >= 200); + assert_eq!(tester.try_reserve_exact(0), Ok(())); + assert!(tester.capacity() >= 200); + assert!(tester.try_reserve_exact(usize::MAX).is_err()); +} + +#[test] +fn test_try_reserve() { + let mut tester: VecDeque<i32> = VecDeque::with_capacity(1); + assert!(tester.capacity() == 1); + assert_eq!(tester.try_reserve(100), Ok(())); + assert!(tester.capacity() >= 100); + assert_eq!(tester.try_reserve(50), Ok(())); + assert!(tester.capacity() >= 100); + assert_eq!(tester.try_reserve(200), Ok(())); + assert!(tester.capacity() >= 200); + assert_eq!(tester.try_reserve(0), Ok(())); + assert!(tester.capacity() >= 200); + assert!(tester.try_reserve(usize::MAX).is_err()); +} + +#[test] +fn test_contains() { + let mut tester = VecDeque::new(); + tester.push_back(1); + tester.push_back(2); + tester.push_back(3); + + assert!(tester.contains(&1)); + assert!(tester.contains(&3)); + assert!(!tester.contains(&0)); + assert!(!tester.contains(&4)); + tester.remove(0); + assert!(!tester.contains(&1)); + assert!(tester.contains(&2)); + assert!(tester.contains(&3)); +} + +#[test] +fn test_rotate_left_right() { + let mut tester: VecDeque<_> = (1..=10).collect(); + + assert_eq!(tester.len(), 10); + + tester.rotate_left(0); + assert_eq!(tester, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + + tester.rotate_right(0); + assert_eq!(tester, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + + tester.rotate_left(3); + assert_eq!(tester, [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]); + + tester.rotate_right(5); + assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]); + + tester.rotate_left(tester.len()); + assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]); + + tester.rotate_right(tester.len()); + assert_eq!(tester, [9, 10, 1, 2, 3, 4, 5, 6, 7, 8]); + + tester.rotate_left(1); + assert_eq!(tester, [10, 1, 2, 3, 4, 5, 6, 7, 8, 9]); +} + +#[test] +#[should_panic = "assertion failed: mid <= self.len()"] +fn test_rotate_left_panic() { + let mut tester: VecDeque<_> = (1..=10).collect(); + tester.rotate_left(tester.len() + 1); +} + +#[test] +#[should_panic = "assertion failed: k <= self.len()"] +fn test_rotate_right_panic() { + let mut tester: VecDeque<_> = (1..=10).collect(); + tester.rotate_right(tester.len() + 1); +} + +#[test] +fn test_binary_search() { + // If the givin VecDeque is not sorted, the returned result is unspecified and meaningless, + // as this method performs a binary search. + + let tester: VecDeque<_> = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + + assert_eq!(tester.binary_search(&0), Ok(0)); + assert_eq!(tester.binary_search(&5), Ok(5)); + assert_eq!(tester.binary_search(&55), Ok(10)); + assert_eq!(tester.binary_search(&4), Err(5)); + assert_eq!(tester.binary_search(&-1), Err(0)); + assert!(matches!(tester.binary_search(&1), Ok(1..=2))); + + let tester: VecDeque<_> = [1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3].into(); + assert_eq!(tester.binary_search(&1), Ok(0)); + assert!(matches!(tester.binary_search(&2), Ok(1..=4))); + assert!(matches!(tester.binary_search(&3), Ok(5..=13))); + assert_eq!(tester.binary_search(&-2), Err(0)); + assert_eq!(tester.binary_search(&0), Err(0)); + assert_eq!(tester.binary_search(&4), Err(14)); + assert_eq!(tester.binary_search(&5), Err(14)); +} + +#[test] +fn test_binary_search_by() { + // If the givin VecDeque is not sorted, the returned result is unspecified and meaningless, + // as this method performs a binary search. + + let tester: VecDeque<_> = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + + assert_eq!(tester.binary_search_by(|x| x.cmp(&0)), Ok(0)); + assert_eq!(tester.binary_search_by(|x| x.cmp(&5)), Ok(5)); + assert_eq!(tester.binary_search_by(|x| x.cmp(&55)), Ok(10)); + assert_eq!(tester.binary_search_by(|x| x.cmp(&4)), Err(5)); + assert_eq!(tester.binary_search_by(|x| x.cmp(&-1)), Err(0)); + assert!(matches!(tester.binary_search_by(|x| x.cmp(&1)), Ok(1..=2))); +} + +#[test] +fn test_binary_search_key() { + // If the givin VecDeque is not sorted, the returned result is unspecified and meaningless, + // as this method performs a binary search. + + let tester: VecDeque<_> = [ + (-1, 0), + (2, 10), + (6, 5), + (7, 1), + (8, 10), + (10, 2), + (20, 3), + (24, 5), + (25, 18), + (28, 13), + (31, 21), + (32, 4), + (54, 25), + ] + .into(); + + assert_eq!(tester.binary_search_by_key(&-1, |&(a, _b)| a), Ok(0)); + assert_eq!(tester.binary_search_by_key(&8, |&(a, _b)| a), Ok(4)); + assert_eq!(tester.binary_search_by_key(&25, |&(a, _b)| a), Ok(8)); + assert_eq!(tester.binary_search_by_key(&54, |&(a, _b)| a), Ok(12)); + assert_eq!(tester.binary_search_by_key(&-2, |&(a, _b)| a), Err(0)); + assert_eq!(tester.binary_search_by_key(&1, |&(a, _b)| a), Err(1)); + assert_eq!(tester.binary_search_by_key(&4, |&(a, _b)| a), Err(2)); + assert_eq!(tester.binary_search_by_key(&13, |&(a, _b)| a), Err(6)); + assert_eq!(tester.binary_search_by_key(&55, |&(a, _b)| a), Err(13)); + assert_eq!(tester.binary_search_by_key(&100, |&(a, _b)| a), Err(13)); + + let tester: VecDeque<_> = [ + (0, 0), + (2, 1), + (6, 1), + (5, 1), + (3, 1), + (1, 2), + (2, 3), + (4, 5), + (5, 8), + (8, 13), + (1, 21), + (2, 34), + (4, 55), + ] + .into(); + + assert_eq!(tester.binary_search_by_key(&0, |&(_a, b)| b), Ok(0)); + assert!(matches!(tester.binary_search_by_key(&1, |&(_a, b)| b), Ok(1..=4))); + assert_eq!(tester.binary_search_by_key(&8, |&(_a, b)| b), Ok(8)); + assert_eq!(tester.binary_search_by_key(&13, |&(_a, b)| b), Ok(9)); + assert_eq!(tester.binary_search_by_key(&55, |&(_a, b)| b), Ok(12)); + assert_eq!(tester.binary_search_by_key(&-1, |&(_a, b)| b), Err(0)); + assert_eq!(tester.binary_search_by_key(&4, |&(_a, b)| b), Err(7)); + assert_eq!(tester.binary_search_by_key(&56, |&(_a, b)| b), Err(13)); + assert_eq!(tester.binary_search_by_key(&100, |&(_a, b)| b), Err(13)); +} + +#[test] fn make_contiguous_big_tail() { let mut tester = VecDeque::with_capacity(15); diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index a42f1c3b4bb..4bcc78ae0f4 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1956,6 +1956,25 @@ where } } +#[stable(feature = "shared_from_str", since = "1.62.0")] +impl From<Rc<str>> for Rc<[u8]> { + /// Converts a reference-counted string slice into a byte slice. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let string: Rc<str> = Rc::from("eggplant"); + /// let bytes: Rc<[u8]> = Rc::from(string); + /// assert_eq!("eggplant".as_bytes(), bytes.as_ref()); + /// ``` + #[inline] + fn from(rc: Rc<str>) -> Self { + // SAFETY: `str` has the same layout as `[u8]`. + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const [u8]) } + } +} + #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]> { type Error = Rc<[T]>; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a19999cd725..1e2caddcacb 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2556,6 +2556,25 @@ where } } +#[stable(feature = "shared_from_str", since = "1.62.0")] +impl From<Arc<str>> for Arc<[u8]> { + /// Converts an atomically reference-counted string slice into a byte slice. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let string: Arc<str> = Arc::from("eggplant"); + /// let bytes: Arc<[u8]> = Arc::from(string); + /// assert_eq!("eggplant".as_bytes(), bytes.as_ref()); + /// ``` + #[inline] + fn from(rc: Arc<str>) -> Self { + // SAFETY: `str` has the same layout as `[u8]`. + unsafe { Arc::from_raw(Arc::into_raw(rc) as *const [u8]) } + } +} + #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]> { type Error = Arc<[T]>; diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 03c532bb697..8134eea570a 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -121,6 +121,11 @@ impl<T, A: Allocator> IntoIter<T, A> { ptr::drop_in_place(remaining); } } + + /// Forgets to Drop the remaining elements while still allowing the backing allocation to be freed. + pub(crate) fn forget_remaining_elements(&mut self) { + self.ptr = self.end; + } } #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index 0efc4893c3c..868f2f1e323 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -2,7 +2,7 @@ use crate::boxed::Box; #[rustc_specialization_trait] pub(super) unsafe trait IsZero { - /// Whether this value is zero + /// Whether this value's representation is all zeros fn is_zero(&self) -> bool; } @@ -49,6 +49,13 @@ unsafe impl<T> IsZero for *mut T { } } +unsafe impl<T: IsZero, const N: usize> IsZero for [T; N] { + #[inline] + fn is_zero(&self) -> bool { + self.iter().all(IsZero::is_zero) + } +} + // `Option<&T>` and `Option<Box<T>>` are guaranteed to represent `None` as null. // For fat pointers, the bytes that would be the pointer metadata in the `Some` // variant are padding in the `None` variant, so ignoring them and diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 9bf42e779c9..3dc8a4fbba8 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2989,48 +2989,6 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> { } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "vec_from_array_ref", since = "1.61.0")] -impl<T: Clone, const N: usize> From<&[T; N]> for Vec<T> { - /// Allocate a `Vec<T>` and fill it by cloning `s`'s items. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from(b"raw"), vec![b'r', b'a', b'w']); - /// ``` - #[cfg(not(test))] - fn from(s: &[T; N]) -> Vec<T> { - s.to_vec() - } - - #[cfg(test)] - fn from(s: &[T; N]) -> Vec<T> { - crate::slice::to_vec(s, Global) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "vec_from_array_ref", since = "1.61.0")] -impl<T: Clone, const N: usize> From<&mut [T; N]> for Vec<T> { - /// Allocate a `Vec<T>` and fill it by cloning `s`'s items. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); - /// ``` - #[cfg(not(test))] - fn from(s: &mut [T; N]) -> Vec<T> { - s.to_vec() - } - - #[cfg(test)] - fn from(s: &mut [T; N]) -> Vec<T> { - crate::slice::to_vec(s, Global) - } -} - #[stable(feature = "vec_from_cow_slice", since = "1.14.0")] impl<'a, T> From<Cow<'a, [T]>> for Vec<T> where diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index c3b4534096d..506ee0ecfa2 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -62,7 +62,7 @@ impl<T, A: Allocator> SpecExtend<T, IntoIter<T>> for Vec<T, A> { unsafe { self.append_elements(iterator.as_slice() as _); } - iterator.ptr = iterator.end; + iterator.forget_remaining_elements(); } } |
