From b3c39dfa6078b3ec620cd78351c85b56ae7078e3 Mon Sep 17 00:00:00 2001 From: Alex Huszagh Date: Tue, 30 Jun 2026 13:51:35 -0500 Subject: [PATCH] Migrate to using `MaybeUninit` correctly. This avoids the stack borrow violations and ensures that the array is correctly used and no `mem::uninitialized` is used. This causes API-breaking changes by changing to use an array of `MaybeUninit` values, rather than a `MaybeUninit` array, and ensure these are correctly initialized. - Closes [#5](https://github.com/Alexhuszagh/rust-stackvector/issues/5) - Addresses [rustsec/advisory-db#3005](https://github.com/rustsec/advisory-db/issues/3005) --- Cargo.toml | 2 +- README.md | 13 +- src/lib.rs | 654 +++++++++++++++++++++++++++-------------------------- 3 files changed, 339 insertions(+), 330 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8b99fe0..d932d2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ categories = ["data-structures"] description = "StackVec: vector-like facade for stack-allocated arrays." documentation = "https://docs.rs/stackvector" edition = "2021" -rust-version = "1.56.0" +rust-version = "1.60.0" keywords = ["vec", "vector", "stack", "no_std"] license = "MIT/Apache-2.0" name = "stackvector" diff --git a/README.md b/README.md index b1025cb..0861144 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -rust-stackvector -================ +# stackvector [Documentation](https://docs.rs/stackvector/) @@ -7,7 +6,7 @@ rust-stackvector "StackVec": vector-like facade for stack-allocated arrays. -# Comparison to ArrayVec +## Comparison to ArrayVec [ArrayVec](https://github.com/bluss/arrayvec) is a relatively mature stack vector implementation, using a backing array like stackvector. The main differences between ArrayVec and StackVec are in the compatibility with Vec's API, as well as the ease-of-creation. @@ -25,12 +24,12 @@ Likewise, stackvector is missing certain convenience methods that are not presen **Version Support** -Both ArrayVec and stackvector have support for Rustc versions as old as 1.20.0. +stackvector has support for Rustc versions as old as 1.60.0. -# License +## License StackVector is derived from Servo's [smallvec](https://github.com/servo/rust-smallve), and like smallvec, it is dual licensed under either the MIT or Apache 2.0 license. -# Version Support +## Version Support -Stackvector has been tested on version of Rustc as low as 1.36.0 (needed for `mem::MaybeUninit`). +Stackvector has been tested on version of Rustc as low as 1.60.0. diff --git a/src/lib.rs b/src/lib.rs index 3c59839..78520b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,39 +23,10 @@ extern crate alloc; -use alloc::vec::Vec; use alloc::borrow::{Borrow, BorrowMut}; +use alloc::vec::Vec; use core::{cmp, fmt, hash, iter, mem, ops, ptr, slice}; -// ARRAY - -/// Types that can be used as the backing store for a StackVec -pub unsafe trait Array { - /// The type of the array's elements. - type Item; - /// Returns the number of items the array can hold. - fn size() -> usize; - /// Returns a pointer to the first element of the array. - fn ptr(&self) -> *const Self::Item; - /// Returns a mutable pointer to the first element of the array. - fn ptr_mut(&mut self) -> *mut Self::Item; -} - -macro_rules! impl_array( - ($($size:expr),+) => { - $( - unsafe impl Array for [T; $size] { - type Item = T; - fn size() -> usize { $size } - fn ptr(&self) -> *const T { self.as_ptr() } - fn ptr_mut(&mut self) -> *mut T { self.as_mut_ptr() } - } - )+ - } -); - -impl_array! { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000 } - // VEC LIKE /// Common operations implemented by both `Vec` and `StackVec`. @@ -76,7 +47,7 @@ impl_array! { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, /// let mut vec = Vec::new(); /// initialize(&mut vec); /// -/// let mut stack_vec = StackVec::<[u8; 8]>::new(); +/// let mut stack_vec = StackVec::::new(); /// initialize(&mut stack_vec); /// ``` pub trait VecLike: @@ -130,7 +101,7 @@ impl VecLike for Vec { /// initialize(&mut vec); /// assert_eq!(&vec, b"Test!"); /// -/// let mut stack_vec = StackVec::<[u8; 8]>::new(); +/// let mut stack_vec = StackVec::::new(); /// initialize(&mut stack_vec); /// assert_eq!(&stack_vec as &[_], b"Test!"); /// ``` @@ -205,13 +176,18 @@ impl<'a> SetLenOnDrop<'a> { fn new(len: &'a mut usize) -> Self { SetLenOnDrop { local_len: *len, - len: len, + len, } } #[inline] - unsafe fn increment_len(&mut self, increment: usize) { - self.local_len += increment; + unsafe fn increment_len(&mut self, n: usize) { + self.local_len += n; + } + + #[inline] + unsafe fn decrement_len(&mut self, n: usize) { + self.local_len -= n; } } @@ -246,13 +222,13 @@ impl Drop for DropOnPanic { /// /// The amount of data that a `StackVec` can store inline depends on its backing store. The backing /// store can be any type that implements the `Array` trait; usually it is a small fixed-sized -/// array. For example a `StackVec<[u64; 8]>` can hold up to eight 64-bit integers inline. +/// array. For example a `StackVec` can hold up to eight 64-bit integers inline. /// /// ## Example /// /// ```rust,should_panic /// use stackvector::StackVec; -/// let mut v = StackVec::<[u8; 4]>::new(); // initialize an empty vector +/// let mut v = StackVec::::new(); // initialize an empty vector /// /// // The vector can hold up to 4 items without spilling onto the heap. /// v.extend(0..4); @@ -261,30 +237,30 @@ impl Drop for DropOnPanic { /// // Pushing another element will force the buffer to spill and panic: /// v.push(4); /// ``` -pub struct StackVec { +pub struct StackVec { // The capacity field is used for iteration and other optimizations. // Publicly expose the fields, so they may be used in constant // initialization. - pub data: mem::MaybeUninit, + data: [mem::MaybeUninit; N], length: usize, } -impl StackVec { +impl StackVec { /// Construct an empty vector #[inline] - pub fn new() -> StackVec { + pub fn new() -> StackVec { StackVec { length: 0, - data: mem::MaybeUninit::uninit(), + data: [const { mem::MaybeUninit::uninit() }; N], } } - /// Construct a new `StackVec` from a `Vec`. + /// Construct a new `StackVec` from a `Vec`. /// - /// Elements will be copied to the inline buffer if vec.len() <= A::size(). + /// Elements will be copied to the inline buffer if vec.len() <= N. /// /// ```rust - /// #![cfg_attr(not(feature = "std"), no_std)] + /// # #[cfg(feature = "std")] { /// /// extern crate alloc; /// @@ -293,28 +269,28 @@ impl StackVec { /// use stackvector::StackVec; /// /// let vec = vec![1, 2, 3, 4, 5]; - /// let stack_vec: StackVec<[_; 5]> = StackVec::from_vec(vec); + /// let stack_vec: StackVec<_, 5> = StackVec::from_vec(vec); /// /// assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); + /// # } /// ``` #[inline] - pub fn from_vec(vec: Vec) -> StackVec { - assert!(vec.len() <= A::size()); + pub fn from_vec(vec: Vec) -> StackVec { + assert!(vec.len() <= N); unsafe { Self::from_vec_unchecked(vec) } } - /// Construct a new `StackVec` from a `Vec` without bounds checking. + /// Construct a new `StackVec` from a `Vec` without bounds checking. #[allow(deprecated)] - pub unsafe fn from_vec_unchecked(mut vec: Vec) -> StackVec { - let mut data: A = mem::uninitialized(); + pub unsafe fn from_vec_unchecked(vec: Vec) -> StackVec { + let mut v = Self::new(); let len = vec.len(); - vec.set_len(0); - ptr::copy_nonoverlapping(vec.as_ptr(), data.ptr_mut(), len); - - StackVec { - length: len, - data: mem::MaybeUninit::new(data), + for (index, item) in vec.into_iter().enumerate() { + v.data[index].write(item); } + v.length = len; + + v } /// Constructs a new `StackVec` on the stack from an `A` without @@ -324,19 +300,17 @@ impl StackVec { /// use stackvector::StackVec; /// /// let buf = [1, 2, 3, 4, 5]; - /// let stack_vec: StackVec<_> = StackVec::from_buf(buf); + /// let stack_vec: StackVec = StackVec::from_buf(buf); /// /// assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] - pub fn from_buf(buf: A) -> StackVec { - StackVec { - length: A::size(), - data: mem::MaybeUninit::new(buf), - } + pub fn from_buf(buf: [T; N]) -> StackVec { + let len = buf.len(); + unsafe { StackVec::from_buf_and_len_unchecked(buf, len) } } - /// Constructs a new `StackVec` on the stack from an `A` without + /// Constructs a new `StackVec` on the stack from an `[T; N]` without /// copying elements. Also sets the length, which must be less or /// equal to the size of `buf`. /// @@ -344,36 +318,42 @@ impl StackVec { /// use stackvector::StackVec; /// /// let buf = [1, 2, 3, 4, 5, 0, 0, 0]; - /// let stack_vec: StackVec<_> = StackVec::from_buf_and_len(buf, 5); + /// let stack_vec: StackVec = StackVec::from_buf_and_len(buf, 5); /// /// assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] - pub fn from_buf_and_len(buf: A, len: usize) -> StackVec { - assert!(len <= A::size()); + pub fn from_buf_and_len(buf: [T; N], len: usize) -> StackVec { + assert!(len <= N && len <= buf.len()); unsafe { StackVec::from_buf_and_len_unchecked(buf, len) } } /// Constructs a new `StackVec` on the stack from an `A` without /// copying elements. Also sets the length. The user is responsible - /// for ensuring that `len <= A::size()`. + /// for ensuring that `len <= N`. /// /// ```rust /// use stackvector::StackVec; /// /// let buf = [1, 2, 3, 4, 5, 0, 0, 0]; - /// let stack_vec: StackVec<_> = unsafe { + /// let stack_vec: StackVec = unsafe { /// StackVec::from_buf_and_len_unchecked(buf, 5) /// }; /// /// assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] - pub unsafe fn from_buf_and_len_unchecked(buf: A, len: usize) -> StackVec { - StackVec { - length: len, - data: mem::MaybeUninit::new(buf), + pub unsafe fn from_buf_and_len_unchecked(buf: [T; N], len: usize) -> StackVec { + let mut v = Self::new(); + { + let mut local_len = SetLenOnDrop::new(&mut v.length); + for (index, item) in buf.into_iter().take(len).enumerate() { + v.data[index].write(item); + unsafe { local_len.increment_len(1) }; + } } + + v } /// Sets the length of a vector. @@ -383,6 +363,7 @@ impl StackVec { /// vector is actually the specified size. #[inline] pub unsafe fn set_len(&mut self, new_len: usize) { + debug_assert!(new_len <= N); self.length = new_len; } @@ -401,14 +382,15 @@ impl StackVec { /// The number of items the vector can hold. #[inline] pub fn capacity(&self) -> usize { - A::size() + N } /// Empty the vector and return an iterator over its former contents. - pub fn drain(&mut self) -> Drain<'_, A::Item> { + pub fn drain(&mut self) -> Drain<'_, T> { unsafe { let slice = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()); - self.set_len(0); + // NOTE: Cannot be `set_len` due to stack borrow rules + self.length = 0; Drain { iter: slice.iter_mut(), @@ -418,23 +400,26 @@ impl StackVec { /// Append an item to the vector. #[inline] - pub fn push(&mut self, value: A::Item) { + pub fn push(&mut self, value: T) { assert!(self.len() < self.capacity()); unsafe { - ptr::write(self.as_mut_ptr().add(self.length), value); - self.length += 1; + let len = self.len(); + self.data[len].write(value); + self.set_len(len + 1); } } /// Remove an item from the end of the vector and return it, or None if empty. #[inline] - pub fn pop(&mut self) -> Option { - unsafe { - if self.len() == 0 { - None - } else { - self.length -= 1; - Some(ptr::read(self.as_mut_ptr().add(self.length))) + pub fn pop(&mut self) -> Option { + let len = self.len(); + if len == 0 { + None + } else { + unsafe { + self.set_len(len - 1); + let init = self.as_ptr().add(self.len()); + Some(ptr::read(init)) } } } @@ -446,18 +431,34 @@ impl StackVec { /// `shrink_to_fit` after truncating. pub fn truncate(&mut self, len: usize) { unsafe { - while len < self.length { - self.length -= 1; - ptr::drop_in_place(self.as_mut_ptr().add(self.length)); + while len < self.len() { + self.set_len(self.len() - 1); + self.data[self.len()].assume_init_drop(); } } } + /// Returns a raw pointer to the slice’s buffer. + /// + /// The caller must ensure that the slice outlives the pointer this function returns, + /// or else it will end up dangling. + fn as_ptr(&self) -> *const T { + self.data.as_ptr() as *const T + } + + /// Returns an unsafe mutable pointer to the slice’s buffer. + /// + /// The caller must ensure that the slice outlives the pointer this function returns, + /// or else it will end up dangling. + fn as_mut_ptr(&mut self) -> *mut T { + self.data.as_mut_ptr() as *mut T + } + /// Extracts a slice containing the entire vector. /// /// Equivalent to `&s[..]`. #[inline] - pub fn as_slice(&self) -> &[A::Item] { + pub fn as_slice(&self) -> &[T] { self } @@ -465,7 +466,7 @@ impl StackVec { /// /// Equivalent to `&mut s[..]`. #[inline] - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { + pub fn as_mut_slice(&mut self) -> &mut [T] { self } @@ -475,7 +476,7 @@ impl StackVec { /// /// Panics if `index` is out of bounds. #[inline] - pub fn swap_remove(&mut self, index: usize) -> A::Item { + pub fn swap_remove(&mut self, index: usize) -> T { let len = self.len(); self.swap(len - 1, index); unsafe { self.pop().unwrap_unchecked() } @@ -491,7 +492,7 @@ impl StackVec { /// left. /// /// Panics if `index` is out of bounds. - pub fn remove(&mut self, index: usize) -> A::Item { + pub fn remove(&mut self, index: usize) -> T { assert!(index < self.len()); unsafe { self.length -= 1; @@ -505,7 +506,7 @@ impl StackVec { /// Insert an element at position `index`, shifting all elements after it to the right. /// /// Panics if `index` is out of bounds. - pub fn insert(&mut self, index: usize, element: A::Item) { + pub fn insert(&mut self, index: usize, element: T) { assert!(index < self.len() && self.len() < self.capacity()); unsafe { let ptr = self.as_mut_ptr().add(index); @@ -517,20 +518,16 @@ impl StackVec { /// Insert multiple elements at position `index`, shifting all following elements toward the /// back. - pub fn insert_many>( - &mut self, - index: usize, - iterable: I, - ) { + pub fn insert_many>(&mut self, index: usize, iterable: I) { let mut iter = iterable.into_iter(); if index == self.len() { return self.extend(iter); } - let (lower_size_bound, _) = iter.size_hint(); - assert!(lower_size_bound <= isize::MAX as usize); // Ensure offset is indexable - assert!(index + lower_size_bound >= index); // Protect against overflow - assert!(self.len() + lower_size_bound <= self.capacity()); + let (lower_bound, _) = iter.size_hint(); + assert!(lower_bound <= isize::MAX as usize); // Ensure offset is indexable + assert!(index + lower_bound >= index); // Protect against overflow + assert!(self.len() + lower_bound <= self.capacity()); let mut num_added = 0; let old_len = self.len(); @@ -541,17 +538,17 @@ impl StackVec { let ptr = start.add(index); // Move the trailing elements. - ptr::copy(ptr, ptr.add(lower_size_bound), old_len - index); + ptr::copy(ptr, ptr.add(lower_bound), old_len - index); // In case the iterator panics, don't double-drop the items we just copied above. - self.set_len(0); + self.length = 0; let mut guard = DropOnPanic { start, - skip: index..(index + lower_size_bound), - len: old_len + lower_size_bound, + skip: index..(index + lower_bound), + len: old_len + lower_bound, }; - while num_added < lower_size_bound { + while num_added < lower_bound { let element = match iter.next() { Some(x) => x, None => break, @@ -562,13 +559,9 @@ impl StackVec { num_added += 1; } - if num_added < lower_size_bound { + if num_added < lower_bound { // Iterator provided fewer elements than the hint. Move the tail backward. - ptr::copy( - ptr.add(lower_size_bound), - ptr.add(num_added), - old_len - index, - ); + ptr::copy(ptr.add(lower_bound), ptr.add(num_added), old_len - index); } // There are no more duplicate or uninitialized slots, so the guard is not needed. self.set_len(old_len + num_added); @@ -583,18 +576,18 @@ impl StackVec { } /// Convert a StackVec to a Vec. - pub fn into_vec(self) -> Vec { + pub fn into_vec(self) -> Vec { self.into_iter().collect() } - /// Convert the StackVec into an `A`. - pub fn into_inner(self) -> Result { - if self.len() != A::size() { + /// Convert the StackVec into a `[T; N]`. + pub fn into_inner(self) -> Result<[T; N], Self> { + if self.len() != N { Err(self) } else { unsafe { let this = mem::ManuallyDrop::new(self); - let array = ptr::read(this.as_ptr() as *const A); + let array = ptr::read(this.as_ptr() as *const [T; N]); Ok(array) } } @@ -605,7 +598,7 @@ impl StackVec { /// In other words, remove all elements `e` such that `f(&e)` returns `false`. /// This method operates in place and preserves the order of the retained /// elements. - pub fn retain bool>(&mut self, mut f: F) { + pub fn retain bool>(&mut self, mut f: F) { let mut del = 0; let len = self.len(); for i in 0..len { @@ -621,7 +614,7 @@ impl StackVec { /// Removes consecutive duplicate elements. pub fn dedup(&mut self) where - A::Item: PartialEq, + T: PartialEq, { self.dedup_by(|a, b| a == b); } @@ -629,26 +622,29 @@ impl StackVec { /// Removes consecutive duplicate elements using the given equality relation. pub fn dedup_by(&mut self, mut same_bucket: F) where - F: FnMut(&mut A::Item, &mut A::Item) -> bool, + F: FnMut(&mut T, &mut T) -> bool, { // See the implementation of Vec::dedup_by in the // standard library for an explanation of this algorithm. let len = self.len(); + assert!(len <= self.data.len()); if len <= 1 { return; } + // NOTE: Not ideal but use pointers since the type checker cannot guarantee + // that the derefs point to different locations in the array. let ptr = self.as_mut_ptr(); let mut w: usize = 1; unsafe { for r in 1..len { - let p_r = ptr.offset(r as isize); - let p_wm1 = ptr.offset((w - 1) as isize); + let p_r = ptr.add(r); + let p_wm1 = ptr.add(w - 1); if !same_bucket(&mut *p_r, &mut *p_wm1) { if r != w { let p_w = p_wm1.offset(1); - mem::swap(&mut *p_r, &mut *p_w); + ptr::swap(p_r, p_w); } w += 1; } @@ -661,46 +657,51 @@ impl StackVec { /// Removes consecutive elements that map to the same key. pub fn dedup_by_key(&mut self, mut key: F) where - F: FnMut(&mut A::Item) -> K, + F: FnMut(&mut T) -> K, K: PartialEq, { self.dedup_by(|a, b| key(a) == key(b)); } } -impl StackVec +impl StackVec where - A::Item: Copy, + T: Copy, { /// Copy the elements from a slice into a new `StackVec`. /// /// For slices of `Copy` types, this is more efficient than `StackVec::from(slice)`. - pub fn from_slice(slice: &[A::Item]) -> Self { - assert!(slice.len() <= A::size()); - StackVec { - length: slice.len(), - data: unsafe { - let mut data: mem::MaybeUninit = mem::MaybeUninit::uninit(); - let ptr = data.as_mut_ptr() as *mut A::Item; - ptr::copy_nonoverlapping(slice.as_ptr(), ptr, slice.len()); - data - }, + pub fn from_slice(slice: &[T]) -> Self { + assert!(slice.len() <= N); + let mut v = StackVec::new(); + unsafe { + let mut local_len = SetLenOnDrop::new(&mut v.length); + for (index, item) in slice.iter().enumerate() { + v.data[index].write(*item); + local_len.increment_len(1); + } } + v } /// Copy elements from a slice into the vector at position `index`, shifting any following /// elements toward the back. /// /// For slices of `Copy` types, this is more efficient than `insert`. - pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) { + pub fn insert_from_slice(&mut self, index: usize, slice: &[T]) { + // NOTE: Cannot overflow, since the number of bytes of both must be <= isize::MAX, + // so we cannot have unsigned integer wrapping. + // https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety assert!(index <= self.len() && self.len() + slice.len() <= self.capacity()); - unsafe { - let len = self.len(); - let slice_ptr = slice.as_ptr(); - let ptr = self.as_mut_ptr().add(index); - ptr::copy(ptr, ptr.add(slice.len()), len - index); - ptr::copy_nonoverlapping(slice_ptr, ptr, slice.len()); - self.set_len(len + slice.len()); + let len = self.len(); + // NOTE: this is safe since the length isn't set, so there won't be duplicate drops + let ptr = unsafe { self.as_mut_ptr().add(index) }; + unsafe { ptr::copy(ptr, ptr.add(slice.len()), len - index) }; + + let mut local_len = SetLenOnDrop::new(&mut self.length); + for (i, item) in slice.iter().enumerate() { + self.data[index + i].write(*item); + unsafe { local_len.increment_len(1) }; } } @@ -708,15 +709,23 @@ where /// /// For slices of `Copy` types, this is more efficient than `extend`. #[inline] - pub fn extend_from_slice(&mut self, slice: &[A::Item]) { + pub fn extend_from_slice(&mut self, slice: &[T]) { + // NOTE: Cannot overflow, since the number of bytes of both must be <= isize::MAX, + // so we cannot have unsigned integer wrapping. + // https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety + assert!(self.len() + slice.len() <= self.capacity()); let len = self.len(); - self.insert_from_slice(len, slice); + let mut local_len = SetLenOnDrop::new(&mut self.length); + for (i, item) in slice.iter().enumerate() { + self.data[len + i].write(*item); + unsafe { local_len.increment_len(1) }; + } } } -impl StackVec +impl StackVec where - A::Item: Clone, + T: Clone, { /// Resizes the vector so that its length is equal to `len`. /// @@ -724,7 +733,7 @@ where /// /// If `len` is greater than the current length, `value` is appended to the /// vector until its length equals `len`. - pub fn resize(&mut self, len: usize, value: A::Item) { + pub fn resize(&mut self, len: usize, value: T) { assert!(len <= self.capacity()); let old_len = self.len(); if len > old_len { @@ -738,75 +747,74 @@ where /// ``` /// use stackvector::StackVec; /// - /// let v = StackVec::<[char; 128]>::from_elem('d', 2); + /// let v = StackVec::::from_elem('d', 2); /// assert_eq!(v, StackVec::from_buf(['d', 'd'])); /// ``` - pub fn from_elem(elem: A::Item, n: usize) -> Self { - assert!(n <= A::size()); - let mut v = StackVec::::new(); - unsafe { - let ptr = v.as_mut_ptr(); + pub fn from_elem(elem: T, n: usize) -> Self { + assert!(n <= N); + let mut v = StackVec::::new(); + { let mut local_len = SetLenOnDrop::new(&mut v.length); - for i in 0..n as isize { - ptr::write(ptr.offset(i), elem.clone()); - local_len.increment_len(1); + for i in 0..n { + v.data[i].write(elem.clone()); + unsafe { local_len.increment_len(1) }; } } v } } -impl ops::Deref for StackVec { - type Target = [A::Item]; +impl ops::Deref for StackVec { + type Target = [T]; #[inline] - fn deref(&self) -> &[A::Item] { + fn deref(&self) -> &[T] { unsafe { - let ptr = self.data.as_ptr() as *const A::Item; + let ptr = self.as_ptr(); slice::from_raw_parts(ptr, self.len()) } } } -impl ops::DerefMut for StackVec { +impl ops::DerefMut for StackVec { #[inline] - fn deref_mut(&mut self) -> &mut [A::Item] { + fn deref_mut(&mut self) -> &mut [T] { unsafe { - let ptr = self.data.as_mut_ptr() as *mut A::Item; + let ptr = self.as_mut_ptr(); slice::from_raw_parts_mut(ptr, self.len()) } } } -impl AsRef<[A::Item]> for StackVec { +impl AsRef<[T]> for StackVec { #[inline] - fn as_ref(&self) -> &[A::Item] { + fn as_ref(&self) -> &[T] { self } } -impl AsMut<[A::Item]> for StackVec { +impl AsMut<[T]> for StackVec { #[inline] - fn as_mut(&mut self) -> &mut [A::Item] { + fn as_mut(&mut self) -> &mut [T] { self } } -impl Borrow<[A::Item]> for StackVec { +impl Borrow<[T]> for StackVec { #[inline] - fn borrow(&self) -> &[A::Item] { + fn borrow(&self) -> &[T] { self } } -impl BorrowMut<[A::Item]> for StackVec { +impl BorrowMut<[T]> for StackVec { #[inline] - fn borrow_mut(&mut self) -> &mut [A::Item] { + fn borrow_mut(&mut self) -> &mut [T] { self } } #[cfg(feature = "std")] -impl> ::std::io::Write for StackVec { +impl ::std::io::Write for StackVec { #[inline] fn write(&mut self, buf: &[u8]) -> ::std::io::Result { self.extend_from_slice(buf); @@ -825,88 +833,88 @@ impl> ::std::io::Write for StackVec { } } -impl<'a, A: Array> From<&'a [A::Item]> for StackVec +impl<'a, T, const N: usize> From<&'a [T]> for StackVec where - A::Item: Clone, + T: Clone, { #[inline] - fn from(slice: &'a [A::Item]) -> StackVec { - slice.into_iter().cloned().collect() + fn from(slice: &'a [T]) -> StackVec { + slice.iter().cloned().collect() } } -impl From> for StackVec { +impl From> for StackVec { #[inline] - fn from(vec: Vec) -> StackVec { + fn from(vec: Vec) -> StackVec { StackVec::from_vec(vec) } } -impl From for StackVec { +impl From<[T; N]> for StackVec { #[inline] - fn from(array: A) -> StackVec { + fn from(array: [T; N]) -> StackVec { StackVec::from_buf(array) } } macro_rules! impl_index { ($index_type: ty, $output_type: ty) => { - impl ops::Index<$index_type> for StackVec { + impl ops::Index<$index_type> for StackVec { type Output = $output_type; #[inline] fn index(&self, index: $index_type) -> &$output_type { - &(&**self)[index] + &self.as_slice()[index] } } - impl ops::IndexMut<$index_type> for StackVec { + impl ops::IndexMut<$index_type> for StackVec { #[inline] fn index_mut(&mut self, index: $index_type) -> &mut $output_type { - &mut (&mut **self)[index] + &mut self.as_mut_slice()[index] } } }; } -impl_index!(usize, A::Item); -impl_index!(ops::Range, [A::Item]); -impl_index!(ops::RangeFrom, [A::Item]); -impl_index!(ops::RangeFull, [A::Item]); -impl_index!(ops::RangeTo, [A::Item]); -impl_index!(ops::RangeInclusive, [A::Item]); -impl_index!(ops::RangeToInclusive, [A::Item]); +impl_index!(usize, T); +impl_index!(ops::Range, [T]); +impl_index!(ops::RangeFrom, [T]); +impl_index!(ops::RangeFull, [T]); +impl_index!(ops::RangeTo, [T]); +impl_index!(ops::RangeInclusive, [T]); +impl_index!(ops::RangeToInclusive, [T]); -impl ExtendFromSlice for StackVec +impl ExtendFromSlice for StackVec where - A::Item: Copy, + T: Copy, { - fn extend_from_slice(&mut self, other: &[A::Item]) { + fn extend_from_slice(&mut self, other: &[T]) { StackVec::extend_from_slice(self, other) } } -impl VecLike for StackVec { +impl VecLike for StackVec { #[inline] - fn push(&mut self, value: A::Item) { + fn push(&mut self, value: T) { StackVec::push(self, value); } #[inline] - fn pop(&mut self) -> Option { + fn pop(&mut self) -> Option { StackVec::pop(self) } } -impl iter::FromIterator for StackVec { - fn from_iter>(iterable: I) -> StackVec { +impl iter::FromIterator for StackVec { + fn from_iter>(iterable: I) -> StackVec { let mut v = StackVec::new(); v.extend(iterable); v } } -impl Extend for StackVec { - fn extend>(&mut self, iterable: I) { +impl Extend for StackVec { + fn extend>(&mut self, iterable: I) { // size_hint() has no safety guarantees, and TrustedLen // is nightly only, so we can't do any optimizations with // size_hint. @@ -916,113 +924,114 @@ impl Extend for StackVec { } } -impl fmt::Debug for StackVec +impl fmt::Debug for StackVec where - A::Item: fmt::Debug, + T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list().entries(self.iter()).finish() } } -impl Default for StackVec { +impl Default for StackVec { #[inline] - fn default() -> StackVec { + fn default() -> StackVec { StackVec::new() } } -impl Drop for StackVec { +impl Drop for StackVec { fn drop(&mut self) { unsafe { - ptr::drop_in_place(&mut self[..]); + // NOTE: as a precaution to avoid duplicate drops + let len = self.len(); + let mut local_len = SetLenOnDrop::new(&mut self.length); + for item in &mut self.data[..len] { + item.assume_init_drop(); + local_len.decrement_len(1); + } } } } -impl Clone for StackVec +impl Clone for StackVec where - A::Item: Clone, + T: Clone, { - fn clone(&self) -> StackVec { - let mut new_vector = StackVec::new(); + fn clone(&self) -> StackVec { + let mut v = StackVec::new(); for element in self.iter() { - new_vector.push(element.clone()) + v.push(element.clone()) } - new_vector + v } } -impl PartialEq> for StackVec +impl PartialEq> for StackVec where - A::Item: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &StackVec) -> bool { + fn eq(&self, other: &StackVec) -> bool { self[..] == other[..] } - - #[inline] - fn ne(&self, other: &StackVec) -> bool { - self[..] != other[..] - } } -impl Eq for StackVec where A::Item: Eq {} +impl Eq for StackVec where T: Eq {} -impl PartialOrd for StackVec +impl PartialOrd for StackVec where - A::Item: PartialOrd, + T: PartialOrd, { #[inline] - fn partial_cmp(&self, other: &StackVec) -> Option { + fn partial_cmp(&self, other: &StackVec) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } -impl Ord for StackVec +impl Ord for StackVec where - A::Item: Ord, + T: Ord, { #[inline] - fn cmp(&self, other: &StackVec) -> cmp::Ordering { + fn cmp(&self, other: &StackVec) -> cmp::Ordering { Ord::cmp(&**self, &**other) } } -impl hash::Hash for StackVec +impl hash::Hash for StackVec where - A::Item: hash::Hash, + T: hash::Hash, { fn hash(&self, state: &mut H) { - (**self).hash(state) + self.as_slice().hash(state) } } -unsafe impl Send for StackVec where A::Item: Send {} +unsafe impl Send for StackVec where T: Send {} /// An iterator that consumes a `StackVec` and yields its items by value. /// /// Returned from [`StackVec::into_iter`][1]. /// /// [1]: struct.StackVec.html#method.into_iter -pub struct IntoIter { - data: StackVec, +pub struct IntoIter { + data: StackVec, current: usize, end: usize, } -impl Drop for IntoIter { +impl Drop for IntoIter { fn drop(&mut self) { for _ in self {} } } -impl Iterator for IntoIter { - type Item = A::Item; +impl Iterator for IntoIter { + type Item = T; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.current == self.end { None } else { @@ -1041,9 +1050,9 @@ impl Iterator for IntoIter { } } -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option { if self.current == self.end { None } else { @@ -1055,11 +1064,11 @@ impl DoubleEndedIterator for IntoIter { } } -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter {} -impl IntoIterator for StackVec { - type IntoIter = IntoIter; - type Item = A::Item; +impl IntoIterator for StackVec { + type IntoIter = IntoIter; + type Item = T; fn into_iter(mut self) -> Self::IntoIter { unsafe { // Set StackVec len to zero as `IntoIter` drop handles dropping of the elements @@ -1074,17 +1083,17 @@ impl IntoIterator for StackVec { } } -impl<'a, A: Array> IntoIterator for &'a StackVec { - type IntoIter = slice::Iter<'a, A::Item>; - type Item = &'a A::Item; +impl<'a, T, const N: usize> IntoIterator for &'a StackVec { + type IntoIter = slice::Iter<'a, T>; + type Item = &'a T; fn into_iter(self) -> Self::IntoIter { self.iter() } } -impl<'a, A: Array> IntoIterator for &'a mut StackVec { - type IntoIter = slice::IterMut<'a, A::Item>; - type Item = &'a mut A::Item; +impl<'a, T, const N: usize> IntoIterator for &'a mut StackVec { + type IntoIter = slice::IterMut<'a, T>; + type Item = &'a mut T; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } @@ -1103,7 +1112,7 @@ impl<'a, A: Array> IntoIterator for &'a mut StackVec { /// # #[macro_use] extern crate stackvector; /// # use stackvector::StackVec; /// # fn main() { -/// let v: StackVec<[_; 128]> = stackvec![1, 2, 3]; +/// let v: StackVec = stackvec![1, 2, 3]; /// assert_eq!(v[0], 1); /// assert_eq!(v[1], 2); /// assert_eq!(v[2], 3); @@ -1116,7 +1125,7 @@ impl<'a, A: Array> IntoIterator for &'a mut StackVec { /// # #[macro_use] extern crate stackvector; /// # use stackvector::StackVec; /// # fn main() { -/// let v: StackVec<[_; 0x8000]> = stackvec![1; 3]; +/// let v: StackVec = stackvec![1; 3]; /// assert_eq!(v, StackVec::from_buf([1, 1, 1])); /// # } /// ``` @@ -1157,6 +1166,7 @@ mod test { use alloc::borrow::ToOwned; use alloc::boxed::Box; use alloc::rc::Rc; + use alloc::string::String; use alloc::vec; use core::iter::FromIterator; @@ -1243,14 +1253,14 @@ mod test { #[test] pub fn test_zero() { - let v = StackVec::<[usize; 0]>::new(); + let v = StackVec::::new(); assert_eq!(v.len(), 0); } #[test] #[should_panic] pub fn test_panic() { - let mut v = StackVec::<[usize; 0]>::new(); + let mut v = StackVec::::new(); v.push(0); } @@ -1258,7 +1268,7 @@ mod test { #[test] pub fn test_inline() { - let mut v = StackVec::<[_; 16]>::new(); + let mut v = StackVec::::new(); v.push("hello".to_owned()); v.push("there".to_owned()); assert_eq!(&*v, &["hello".to_owned(), "there".to_owned(),][..]); @@ -1267,7 +1277,7 @@ mod test { #[test] #[should_panic] pub fn test_spill() { - let mut v = StackVec::<[_; 2]>::new(); + let mut v = StackVec::::new(); v.push("hello".to_owned()); assert_eq!(v[0], "hello"); v.push("there".to_owned()); @@ -1288,7 +1298,7 @@ mod test { #[test] #[should_panic] pub fn test_double_spill() { - let mut v = StackVec::<[_; 2]>::new(); + let mut v = StackVec::::new(); v.push("hello".to_owned()); v.push("there".to_owned()); v.push("burma".to_owned()); @@ -1315,39 +1325,39 @@ mod test { /// https://github.com/servo/rust-smallvec/issues/4 #[test] fn issue_4() { - StackVec::<[Box; 2]>::new(); + StackVec::, 2>::new(); } /// https://github.com/servo/rust-smallvec/issues/5 #[test] fn issue_5() { - assert!(Some(StackVec::<[&u32; 2]>::new()).is_some()); + assert!(Some(StackVec::<&u32, 2>::new()).is_some()); } #[test] fn drain_test() { - let mut v: StackVec<[u8; 2]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); v.push(3); assert_eq!(v.drain().collect::>(), &[3]); } #[test] fn drain_rev_test() { - let mut v: StackVec<[u8; 2]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); v.push(3); assert_eq!(v.drain().rev().collect::>(), &[3]); } #[test] fn into_iter() { - let mut v: StackVec<[u8; 2]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); v.push(3); assert_eq!(v.into_iter().collect::>(), &[3]); } #[test] fn into_iter_rev() { - let mut v: StackVec<[u8; 2]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); v.push(3); assert_eq!(v.into_iter().rev().collect::>(), &[3]); } @@ -1366,7 +1376,7 @@ mod test { { let cell = Cell::new(0); - let mut v: StackVec<[DropCounter; 2]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); v.push(DropCounter(&cell)); v.into_iter(); assert_eq!(cell.get(), 1); @@ -1374,7 +1384,7 @@ mod test { { let cell = Cell::new(0); - let mut v: StackVec<[DropCounter; 2]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); v.push(DropCounter(&cell)); v.push(DropCounter(&cell)); assert!(v.into_iter().next().is_some()); @@ -1384,13 +1394,13 @@ mod test { #[test] fn test_capacity() { - let v: StackVec<[u8; 2]> = StackVec::new(); + let v: StackVec = StackVec::new(); assert_eq!(v.capacity(), 2); } #[test] fn test_truncate() { - let mut v: StackVec<[Box; 8]> = StackVec::new(); + let mut v: StackVec, 8> = StackVec::new(); for x in 0..8 { v.push(Box::new(x)); @@ -1408,7 +1418,7 @@ mod test { #[test] fn test_insert_many() { - let mut v: StackVec<[u8; 8]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); for x in 0..4 { v.push(x); } @@ -1422,7 +1432,7 @@ mod test { #[test] fn test_insert_many_buggy_iterator() { - let mut v: StackVec<[u8; 64]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); for x in 0..4 { v.push(x); } @@ -1432,14 +1442,14 @@ mod test { &[0, 65, 65, 65, 65, 65, 65, 65, 65, 65, 1, 2, 3] ); - let mut v: StackVec<[u8; 64]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); for x in 0..4 { v.push(x); } v.insert_many(1, BadBoundsIterator2::new()); assert_eq!(v.len(), 33); - let mut v: StackVec<[u8; 64]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); for x in 0..4 { v.push(x); } @@ -1450,7 +1460,7 @@ mod test { #[should_panic] #[test] fn test_insert_many_panic_buggy_iterator() { - let mut v: StackVec<[u8; 8]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); for x in 0..4 { v.push(x); } @@ -1459,7 +1469,7 @@ mod test { #[test] fn test_insert_from_slice() { - let mut v: StackVec<[u8; 8]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); for x in 0..4 { v.push(x); } @@ -1473,7 +1483,7 @@ mod test { #[test] fn test_extend_from_slice() { - let mut v: StackVec<[u8; 8]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); for x in 0..4 { v.push(x); } @@ -1498,15 +1508,15 @@ mod test { } } - let mut v = StackVec::<[_; 1]>::new(); + let mut v = StackVec::::new(); v.push(DropPanic); } #[test] fn test_eq() { - let mut a: StackVec<[u32; 2]> = StackVec::new(); - let mut b: StackVec<[u32; 2]> = StackVec::new(); - let mut c: StackVec<[u32; 2]> = StackVec::new(); + let mut a: StackVec = StackVec::new(); + let mut b: StackVec = StackVec::new(); + let mut c: StackVec = StackVec::new(); // a = [1, 2] a.push(1); a.push(2); @@ -1523,9 +1533,9 @@ mod test { #[test] fn test_ord() { - let mut a: StackVec<[u32; 2]> = StackVec::new(); - let mut b: StackVec<[u32; 2]> = StackVec::new(); - let mut c: StackVec<[u32; 2]> = StackVec::new(); + let mut a: StackVec = StackVec::new(); + let mut b: StackVec = StackVec::new(); + let mut c: StackVec = StackVec::new(); // a = [1] a.push(1); // b = [1, 1] @@ -1548,14 +1558,14 @@ mod test { use std::hash::Hash; { - let mut a: StackVec<[u32; 2]> = StackVec::new(); + let mut a: StackVec = StackVec::new(); let b = [1, 2]; a.extend(b.iter().cloned()); let mut hasher = DefaultHasher::new(); assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher)); } { - let mut a: StackVec<[u32; 4]> = StackVec::new(); + let mut a: StackVec = StackVec::new(); let b = [1, 2, 11, 12]; a.extend(b.iter().cloned()); let mut hasher = DefaultHasher::new(); @@ -1565,7 +1575,7 @@ mod test { #[test] fn test_as_ref() { - let mut a: StackVec<[u32; 3]> = StackVec::new(); + let mut a: StackVec = StackVec::new(); a.push(1); assert_eq!(a.as_ref(), [1]); a.push(2); @@ -1576,7 +1586,7 @@ mod test { #[test] fn test_as_mut() { - let mut a: StackVec<[u32; 3]> = StackVec::new(); + let mut a: StackVec = StackVec::new(); a.push(1); assert_eq!(a.as_mut(), [1]); a.push(2); @@ -1591,7 +1601,7 @@ mod test { fn test_borrow() { use core::borrow::Borrow; - let mut a: StackVec<[u32; 3]> = StackVec::new(); + let mut a: StackVec = StackVec::new(); a.push(1); assert_eq!(a.borrow(), [1]); a.push(2); @@ -1604,7 +1614,7 @@ mod test { fn test_borrow_mut() { use core::borrow::BorrowMut; - let mut a: StackVec<[u32; 3]> = StackVec::new(); + let mut a: StackVec = StackVec::new(); a.push(1); assert_eq!(a.borrow_mut(), [1]); a.push(2); @@ -1617,47 +1627,47 @@ mod test { #[test] fn test_from() { - assert_eq!(&StackVec::<[u32; 2]>::from(&[1][..])[..], [1]); - assert_eq!(&StackVec::<[u32; 3]>::from(&[1, 2, 3][..])[..], [1, 2, 3]); + assert_eq!(&StackVec::::from(&[1][..])[..], [1]); + assert_eq!(&StackVec::::from(&[1, 2, 3][..])[..], [1, 2, 3]); let vec = vec![]; - let stack_vec: StackVec<[u8; 3]> = StackVec::from(vec); + let stack_vec: StackVec = StackVec::from(vec); assert_eq!(&*stack_vec, &[]); drop(stack_vec); let vec = vec![1, 2, 3, 4, 5]; - let stack_vec: StackVec<[u8; 5]> = StackVec::from(vec); + let stack_vec: StackVec = StackVec::from(vec); assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); drop(stack_vec); let vec = vec![1, 2, 3, 4, 5]; - let stack_vec: StackVec<[u8; 5]> = StackVec::from(vec); + let stack_vec: StackVec = StackVec::from(vec); assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); drop(stack_vec); let array = [1]; - let stack_vec: StackVec<[u8; 1]> = StackVec::from(array); + let stack_vec: StackVec = StackVec::from(array); assert_eq!(&*stack_vec, &[1]); drop(stack_vec); let array = [99; 128]; - let stack_vec: StackVec<[u8; 128]> = StackVec::from(array); + let stack_vec: StackVec = StackVec::from(array); assert_eq!(&*stack_vec, vec![99u8; 128].as_slice()); drop(stack_vec); } #[test] fn test_from_slice() { - assert_eq!(&StackVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]); + assert_eq!(&StackVec::::from_slice(&[1][..])[..], [1]); assert_eq!( - &StackVec::<[u32; 3]>::from_slice(&[1, 2, 3][..])[..], + &StackVec::::from_slice(&[1, 2, 3][..])[..], [1, 2, 3] ); } #[test] fn test_exact_size_iterator() { - let mut vec = StackVec::<[u32; 3]>::from(&[1, 2, 3][..]); + let mut vec = StackVec::::from(&[1, 2, 3][..]); assert_eq!(vec.clone().into_iter().len(), 3); assert_eq!(vec.drain().len(), 3); } @@ -1674,65 +1684,65 @@ mod test { assert_eq!(&vec[..], [1, 2, 3]); } - let mut vec = StackVec::<[i32; 3]>::from(&[3, 1, 2][..]); + let mut vec = StackVec::::from(&[3, 1, 2][..]); test(&mut vec); } #[test] fn test_into_vec() { - let vec = StackVec::<[u8; 2]>::from_iter(0..2); + let vec = StackVec::::from_iter(0..2); assert_eq!(vec.into_vec(), vec![0, 1]); - let vec = StackVec::<[u8; 3]>::from_iter(0..3); + let vec = StackVec::::from_iter(0..3); assert_eq!(vec.into_vec(), vec![0, 1, 2]); } #[test] fn test_into_inner() { - let vec = StackVec::<[u8; 2]>::from_iter(0..2); + let vec = StackVec::::from_iter(0..2); assert_eq!(vec.into_inner(), Ok([0, 1])); - let vec = StackVec::<[u8; 2]>::from_iter(0..1); + let vec = StackVec::::from_iter(0..1); assert_eq!(vec.clone().into_inner(), Err(vec)); - let vec = StackVec::<[u8; 3]>::from_iter(0..3); + let vec = StackVec::::from_iter(0..3); assert_eq!(vec.clone().into_inner(), Ok([0, 1, 2])); - let vec = StackVec::<[u8; 4]>::from_iter(0..3); + let vec = StackVec::::from_iter(0..3); assert_eq!(vec.clone().into_inner(), Err(vec)); } #[test] fn test_from_vec() { let vec = vec![]; - let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec); + let stack_vec: StackVec = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[]); drop(stack_vec); let vec = vec![]; - let stack_vec: StackVec<[u8; 1]> = StackVec::from_vec(vec); + let stack_vec: StackVec = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[]); drop(stack_vec); let vec = vec![1]; - let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec); + let stack_vec: StackVec = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[1]); drop(stack_vec); let vec = vec![1, 2, 3]; - let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec); + let stack_vec: StackVec = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[1, 2, 3]); drop(stack_vec); let vec = vec![1, 2, 3, 4, 5]; - let stack_vec: StackVec<[u8; 5]> = StackVec::from_vec(vec); + let stack_vec: StackVec = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); drop(stack_vec); } #[test] fn test_retain() { - let mut sv: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 2, 3, 3, 4]); + let mut sv: StackVec = StackVec::from_slice(&[1, 2, 3, 3, 4]); sv.retain(|&mut i| i != 3); assert_eq!(sv.pop(), Some(4)); assert_eq!(sv.pop(), Some(2)); @@ -1741,7 +1751,7 @@ mod test { // Test that drop implementations are called for inline. let one = Rc::new(1); - let mut sv: StackVec<[Rc; 3]> = StackVec::new(); + let mut sv: StackVec, 3> = StackVec::new(); sv.push(Rc::clone(&one)); assert_eq!(Rc::strong_count(&one), 2); sv.retain(|_| false); @@ -1750,26 +1760,26 @@ mod test { #[test] fn test_dedup() { - let mut dupes: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 1, 2, 3, 3]); + let mut dupes: StackVec = StackVec::from_slice(&[1, 1, 2, 3, 3]); dupes.dedup(); assert_eq!(&*dupes, &[1, 2, 3]); - let mut empty: StackVec<[i32; 5]> = StackVec::new(); + let mut empty: StackVec = StackVec::new(); empty.dedup(); assert!(empty.is_empty()); - let mut all_ones: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 1, 1, 1, 1]); + let mut all_ones: StackVec = StackVec::from_slice(&[1, 1, 1, 1, 1]); all_ones.dedup(); assert_eq!(all_ones.len(), 1); - let mut no_dupes: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 2, 3, 4, 5]); + let mut no_dupes: StackVec = StackVec::from_slice(&[1, 2, 3, 4, 5]); no_dupes.dedup(); assert_eq!(no_dupes.len(), 5); } #[test] fn test_resize() { - let mut v: StackVec<[i32; 8]> = StackVec::new(); + let mut v: StackVec = StackVec::new(); v.push(1); v.resize(5, 0); assert_eq!(v[..], [1, 0, 0, 0, 0][..]); @@ -1785,12 +1795,12 @@ mod test { let data = [1, 2, 3, 4, 5]; - let mut small_vec: StackVec<[u8; 5]> = StackVec::new(); + let mut small_vec: StackVec = StackVec::new(); let len = small_vec.write(&data[..]).unwrap(); assert_eq!(len, 5); assert_eq!(small_vec.as_ref(), data.as_ref()); - let mut small_vec: StackVec<[u8; 5]> = StackVec::new(); + let mut small_vec: StackVec = StackVec::new(); small_vec.write_all(&data[..]).unwrap(); assert_eq!(small_vec.as_ref(), data.as_ref()); }