diff --git a/CHANGELOG.md b/CHANGELOG.md index 645d403c..b1344ecf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added `truncate` to `IndexMap`. - Added `get_index` and `get_index_mut` to `IndexMap`. - Added `String::uDisplay`. +- Added `LenT` generic to `Vec` and `VecView` to save memory when using a sane capacity value. ### Changed diff --git a/src/binary_heap.rs b/src/binary_heap.rs index b15ec959..31e2185f 100644 --- a/src/binary_heap.rs +++ b/src/binary_heap.rs @@ -57,7 +57,7 @@ impl private::Sealed for Min {} /// struct if you want to write code that's generic over both. pub struct BinaryHeapInner + ?Sized> { pub(crate) _kind: PhantomData, - pub(crate) data: VecInner, + pub(crate) data: VecInner, } /// A priority queue implemented with a binary heap. @@ -181,7 +181,7 @@ impl BinaryHeap { impl BinaryHeap { /// Returns the underlying `Vec`. Order is arbitrary and time is *O*(1). - pub fn into_vec(self) -> Vec { + pub fn into_vec(self) -> Vec { self.data } } diff --git a/src/de.rs b/src/de.rs index 455295b7..1c8c1c48 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1,6 +1,6 @@ use crate::{ - binary_heap::Kind as BinaryHeapKind, BinaryHeap, Deque, HistoryBuffer, IndexMap, IndexSet, - LinearMap, String, Vec, + binary_heap::Kind as BinaryHeapKind, len_type::LenType, BinaryHeap, Deque, HistoryBuffer, + IndexMap, IndexSet, LinearMap, String, Vec, }; use core::{ fmt, @@ -95,7 +95,7 @@ where } } -impl<'de, T, const N: usize> Deserialize<'de> for Vec +impl<'de, T, LenT: LenType, const N: usize> Deserialize<'de> for Vec where T: Deserialize<'de>, { @@ -103,13 +103,14 @@ where where D: Deserializer<'de>, { - struct ValueVisitor<'de, T, const N: usize>(PhantomData<(&'de (), T)>); + struct ValueVisitor<'de, T, LenT: LenType, const N: usize>(PhantomData<(&'de (), T, LenT)>); - impl<'de, T, const N: usize> serde::de::Visitor<'de> for ValueVisitor<'de, T, N> + impl<'de, T, LenT, const N: usize> serde::de::Visitor<'de> for ValueVisitor<'de, T, LenT, N> where T: Deserialize<'de>, + LenT: LenType, { - type Value = Vec; + type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a sequence") diff --git a/src/defmt.rs b/src/defmt.rs index 9c4d2779..9c8b0d5b 100644 --- a/src/defmt.rs +++ b/src/defmt.rs @@ -1,12 +1,13 @@ //! Defmt implementations for heapless types use crate::{ + len_type::LenType, string::{StringInner, StringStorage}, vec::{VecInner, VecStorage}, }; use defmt::Formatter; -impl + ?Sized> defmt::Format for VecInner +impl + ?Sized> defmt::Format for VecInner where T: defmt::Format, { diff --git a/src/indexmap.rs b/src/indexmap.rs index d3eb3fd4..ace113f3 100644 --- a/src/indexmap.rs +++ b/src/indexmap.rs @@ -138,7 +138,7 @@ macro_rules! probe_loop { } struct CoreMap { - entries: Vec, N>, + entries: Vec, N, usize>, indices: [Option; N], } @@ -1417,7 +1417,7 @@ where #[derive(Clone)] pub struct IntoIter { - entries: Vec, N>, + entries: Vec, N, usize>, } impl Iterator for IntoIter { diff --git a/src/len_type.rs b/src/len_type.rs new file mode 100644 index 00000000..370f9ef4 --- /dev/null +++ b/src/len_type.rs @@ -0,0 +1,107 @@ +use core::{ + fmt::{Debug, Display}, + ops::{Add, AddAssign, Sub, SubAssign}, +}; + +pub trait Sealed: + Send + + Sync + + Copy + + Display + + Debug + + PartialEq + + Add + + AddAssign + + Sub + + SubAssign + + PartialOrd + + TryFrom + + TryInto +{ + /// The zero value of the integer type. + const ZERO: Self; + /// The one value of the integer type. + const ONE: Self; + /// The maximum value of this type, as a `usize`. + const MAX: usize; + + /// An infallible conversion from `usize` to `LenT`. + #[inline] + fn from_usize(val: usize) -> Self { + val.try_into().unwrap() + } + + /// An infallible conversion from `LenT` to `usize`. + #[inline] + fn into_usize(self) -> usize { + self.try_into().unwrap() + } +} + +macro_rules! impl_lentype { + ($($(#[$meta:meta])* $LenT:ty),*) => {$( + $(#[$meta])* + impl Sealed for $LenT { + const ZERO: Self = 0; + const ONE: Self = 1; + const MAX: usize = Self::MAX as _; + } + + $(#[$meta])* + impl LenType for $LenT {} + )*} +} + +/// A sealed trait representing a valid type to use as a length for a container. +/// +/// This cannot be implemented in user code, and is restricted to `u8`, `u16`, `u32`, and `usize`. +pub trait LenType: Sealed {} + +impl_lentype!( + u8, + u16, + #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] + u32, + usize +); + +macro_rules! impl_lentodefault { + ($LenT:ty: $($len:literal),*) => {$( + impl SmallestLenType for Const<$len> { + type Type = $LenT; + } + )*}; +} + +/// A struct to create individual types for mapping with [`SmallestLenType`]. +/// +/// See the documentation of [`DefaultLenType`] for a detailed explanation. +pub struct Const; + +/// A trait to map [`Const`] to it's respective [`LenType`]. +/// +/// See the documentation of [`DefaultLenType`] for a detailed explanation. +#[diagnostic::on_unimplemented( + message = "Length `N` does not have a default `LenType` mapping", + note = "Provide the `LenType` explicitly, such as `usize`" +)] +pub trait SmallestLenType { + type Type: LenType; +} + +/// A type alias to perform the `const N: usize` -> `LenType` mapping. +/// +/// This is impossible to perform directly, but it is possible to write a `const N: usize` -> related `Type` mapping via a const generic argument, +/// then map from that to an unrelated type via a trait with associated types. +/// +/// [`Const`] is the "related type" in the above explaination, [`SmallestLenType`] is the mapping trait. +pub type DefaultLenType = as SmallestLenType>::Type; + +impl_lentodefault!(u8: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255); +impl_lentodefault!(u16: 256, 300, 400, 500, 512, 600, 700, 800, 900, 1000, 1024, 2000, 2048, 4000, 4096, 8000, 8192, 16000, 16384, 32000, 32768, 65000, 65535); +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +impl_lentodefault!(u32: 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648); + +pub const fn check_capacity_fits() { + assert!(LenT::MAX >= N, "The capacity is larger than `LenT` can hold, increase the size of `LenT` or reduce the capacity"); +} diff --git a/src/lib.rs b/src/lib.rs index cd6180a9..0516c614 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,6 +165,7 @@ pub use indexmap::{ ValuesMut as IndexMapValuesMut, }; pub use indexset::{FnvIndexSet, IndexSet, Iter as IndexSetIter}; +pub use len_type::LenType; pub use linear_map::LinearMap; pub use string::String; @@ -178,6 +179,7 @@ pub mod deque; pub mod histbuf; mod indexmap; mod indexset; +mod len_type; pub mod linear_map; mod slice; pub mod storage; diff --git a/src/linear_map.rs b/src/linear_map.rs index c96dece1..b7051737 100644 --- a/src/linear_map.rs +++ b/src/linear_map.rs @@ -89,7 +89,7 @@ pub type ViewStorage = ViewVecStorage<(K, V)>; /// Base struct for [`LinearMap`] and [`LinearMapView`] pub struct LinearMapInner + ?Sized> { - pub(crate) buffer: VecInner<(K, V), S>, + pub(crate) buffer: VecInner<(K, V), usize, S>, } /// A fixed capacity map/dictionary that performs lookups via linear search. @@ -543,7 +543,7 @@ pub struct IntoIter where K: Eq, { - inner: as IntoIterator>::IntoIter, + inner: as IntoIterator>::IntoIter, } impl Iterator for IntoIter diff --git a/src/ser.rs b/src/ser.rs index 26d2858e..402cbfbf 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -4,6 +4,7 @@ use crate::{ binary_heap::{BinaryHeapInner, Kind as BinaryHeapKind}, deque::DequeInner, histbuf::{HistBufStorage, HistoryBufferInner}, + len_type::LenType, linear_map::{LinearMapInner, LinearMapStorage}, string::{StringInner, StringStorage}, vec::{VecInner, VecStorage}, @@ -48,7 +49,7 @@ where } } -impl + ?Sized> Serialize for VecInner +impl> Serialize for VecInner where T: Serialize, { diff --git a/src/string/mod.rs b/src/string/mod.rs index 1a5b968a..29b885fe 100644 --- a/src/string/mod.rs +++ b/src/string/mod.rs @@ -11,8 +11,11 @@ use core::{ str::{self, Utf8Error}, }; -use crate::vec::{OwnedVecStorage, Vec, VecInner, ViewVecStorage}; use crate::CapacityError; +use crate::{ + len_type::LenType, + vec::{OwnedVecStorage, Vec, VecInner, ViewVecStorage}, +}; mod drain; pub use drain::Drain; @@ -131,7 +134,7 @@ pub type ViewStorage = ViewVecStorage; /// In most cases you should use [`String`] or [`StringView`] directly. Only use this /// struct if you want to write code that's generic over both. pub struct StringInner { - vec: VecInner, + vec: VecInner, } /// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html). @@ -229,9 +232,11 @@ impl String { /// # Ok::<(), core::str::Utf8Error>(()) /// ``` #[inline] - pub fn from_utf8(vec: Vec) -> Result { + pub fn from_utf8(vec: Vec) -> Result { core::str::from_utf8(&vec)?; - Ok(Self { vec }) + + // SAFETY: UTF-8 invariant has just been checked by `str::from_utf8`. + Ok(unsafe { Self::from_utf8_unchecked(vec) }) } /// Convert UTF-8 bytes into a `String`, without checking that the string @@ -256,8 +261,10 @@ impl String { /// assert_eq!("💖", sparkle_heart); /// ``` #[inline] - pub const unsafe fn from_utf8_unchecked(vec: Vec) -> Self { - Self { vec } + pub unsafe fn from_utf8_unchecked(vec: Vec) -> Self { + Self { + vec: vec.cast_len_type(), + } } /// Converts a `String` into a byte vector. @@ -279,7 +286,7 @@ impl String { /// # Ok::<(), heapless::CapacityError>(()) /// ``` #[inline] - pub fn into_bytes(self) -> Vec { + pub fn into_bytes(self) -> Vec { self.vec } } @@ -457,7 +464,7 @@ impl StringInner { /// assert_eq!(s, "olleh"); /// # Ok::<(), heapless::CapacityError>(()) /// ``` - pub unsafe fn as_mut_vec(&mut self) -> &mut VecInner { + pub unsafe fn as_mut_vec(&mut self) -> &mut VecInner { &mut self.vec } @@ -1068,7 +1075,7 @@ mod tests { #[test] fn into_bytes() { let s: String<4> = String::try_from("ab").unwrap(); - let b: Vec = s.into_bytes(); + let b: Vec = s.into_bytes(); assert_eq!(b.len(), 2); assert_eq!(b"ab", &b[..]); } diff --git a/src/ufmt.rs b/src/ufmt.rs index ef6e36ab..01e54165 100644 --- a/src/ufmt.rs +++ b/src/ufmt.rs @@ -1,4 +1,5 @@ use crate::{ + len_type::LenType, string::{StringInner, StringStorage}, vec::{VecInner, VecStorage}, CapacityError, @@ -24,7 +25,7 @@ impl uWrite for StringInner { } } -impl + ?Sized> uWrite for VecInner { +impl + ?Sized> uWrite for VecInner { type Error = CapacityError; #[inline] fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { diff --git a/src/vec/drain.rs b/src/vec/drain.rs index 5ba523fd..69af854e 100644 --- a/src/vec/drain.rs +++ b/src/vec/drain.rs @@ -6,38 +6,31 @@ use core::{ slice, }; +use crate::len_type::LenType; + use super::VecView; /// A draining iterator for [`Vec`](super::Vec). /// /// This `struct` is created by [`Vec::drain`](super::Vec::drain). /// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// use heapless::{vec, Vec}; -/// -/// let mut v = Vec::<_, 4>::from_array([0, 1, 2]); -/// let iter: vec::Drain<'_, _> = v.drain(..); -/// ``` -pub struct Drain<'a, T: 'a> { +pub struct Drain<'a, T: 'a, LenT: LenType> { /// Index of tail to preserve - pub(super) tail_start: usize, + pub(super) tail_start: LenT, /// Length of tail - pub(super) tail_len: usize, + pub(super) tail_len: LenT, /// Current remaining range to remove pub(super) iter: slice::Iter<'a, T>, - pub(super) vec: NonNull>, + pub(super) vec: NonNull>, } -impl fmt::Debug for Drain<'_, T> { +impl fmt::Debug for Drain<'_, T, LenT> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() } } -impl Drain<'_, T> { +impl Drain<'_, T, LenT> { /// Returns the remaining items of this iterator as a slice. /// /// # Examples @@ -57,16 +50,16 @@ impl Drain<'_, T> { } } -impl AsRef<[T]> for Drain<'_, T> { +impl AsRef<[T]> for Drain<'_, T, LenT> { fn as_ref(&self) -> &[T] { self.as_slice() } } -unsafe impl Sync for Drain<'_, T> {} -unsafe impl Send for Drain<'_, T> {} +unsafe impl Sync for Drain<'_, T, LenT> {} +unsafe impl Send for Drain<'_, T, LenT> {} -impl Iterator for Drain<'_, T> { +impl Iterator for Drain<'_, T, LenT> { type Item = T; #[inline] @@ -81,7 +74,7 @@ impl Iterator for Drain<'_, T> { } } -impl DoubleEndedIterator for Drain<'_, T> { +impl DoubleEndedIterator for Drain<'_, T, LenT> { #[inline] fn next_back(&mut self) -> Option { self.iter @@ -90,25 +83,26 @@ impl DoubleEndedIterator for Drain<'_, T> { } } -impl Drop for Drain<'_, T> { +impl Drop for Drain<'_, T, LenT> { fn drop(&mut self) { /// Moves back the un-`Drain`ed elements to restore the original `Vec`. - struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); + struct DropGuard<'r, 'a, T, LenT: LenType>(&'r mut Drain<'a, T, LenT>); - impl Drop for DropGuard<'_, '_, T> { + impl Drop for DropGuard<'_, '_, T, LenT> { fn drop(&mut self) { - if self.0.tail_len > 0 { + if self.0.tail_len > LenT::ZERO { unsafe { let source_vec = self.0.vec.as_mut(); // memmove back untouched tail, update to new length let start = source_vec.len(); - let tail = self.0.tail_start; + let tail = self.0.tail_start.into_usize(); + let tail_len = self.0.tail_len.into_usize(); if tail != start { let dst = source_vec.as_mut_ptr().add(start); let src = source_vec.as_ptr().add(tail); - ptr::copy(src, dst, self.0.tail_len); + ptr::copy(src, dst, tail_len); } - source_vec.set_len(start + self.0.tail_len); + source_vec.set_len(start + tail_len); } } } @@ -125,8 +119,9 @@ impl Drop for Drain<'_, T> { unsafe { let vec = vec.as_mut(); let old_len = vec.len(); - vec.set_len(old_len + drop_len + self.tail_len); - vec.truncate(old_len + self.tail_len); + let tail_len = self.tail_len.into_usize(); + vec.set_len(old_len + drop_len + tail_len); + vec.truncate(old_len + tail_len); } return; @@ -159,9 +154,9 @@ impl Drop for Drain<'_, T> { } } -impl ExactSizeIterator for Drain<'_, T> {} +impl ExactSizeIterator for Drain<'_, T, LenT> {} -impl FusedIterator for Drain<'_, T> {} +impl FusedIterator for Drain<'_, T, LenT> {} #[cfg(test)] mod tests { diff --git a/src/vec/mod.rs b/src/vec/mod.rs index ec8e6ccb..b8039c94 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -11,6 +11,7 @@ use core::{ slice, }; +use crate::len_type::{check_capacity_fits, DefaultLenType, LenType}; use crate::CapacityError; mod drain; @@ -21,6 +22,7 @@ mod storage { use crate::{ binary_heap::{BinaryHeapInner, BinaryHeapView}, deque::{DequeInner, DequeView}, + len_type::LenType, }; use super::{VecInner, VecView}; @@ -56,10 +58,12 @@ mod storage { fn borrow(&self) -> &[MaybeUninit]; fn borrow_mut(&mut self) -> &mut [MaybeUninit]; - fn as_vec_view(this: &VecInner) -> &VecView + fn as_vec_view(this: &VecInner) -> &VecView where Self: VecStorage; - fn as_vec_mut_view(this: &mut VecInner) -> &mut VecView + fn as_vec_mut_view( + this: &mut VecInner, + ) -> &mut VecView where Self: VecStorage; @@ -98,13 +102,15 @@ mod storage { &mut self.buffer } - fn as_vec_view(this: &VecInner) -> &VecView + fn as_vec_view(this: &VecInner) -> &VecView where Self: VecStorage, { this } - fn as_vec_mut_view(this: &mut VecInner) -> &mut VecView + fn as_vec_mut_view( + this: &mut VecInner, + ) -> &mut VecView where Self: VecStorage, { @@ -148,13 +154,15 @@ mod storage { &mut self.buffer } - fn as_vec_view(this: &VecInner) -> &VecView + fn as_vec_view(this: &VecInner) -> &VecView where Self: VecStorage, { this } - fn as_vec_mut_view(this: &mut VecInner) -> &mut VecView + fn as_vec_mut_view( + this: &mut VecInner, + ) -> &mut VecView where Self: VecStorage, { @@ -200,9 +208,9 @@ pub use drain::Drain; /// /// In most cases you should use [`Vec`] or [`VecView`] directly. Only use this /// struct if you want to write code that's generic over both. -pub struct VecInner + ?Sized> { +pub struct VecInner + ?Sized> { phantom: PhantomData, - len: usize, + len: LenT, buffer: S, } @@ -241,9 +249,14 @@ pub struct VecInner + ?Sized> { /// use heapless::{Vec, VecView}; /// /// let vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); -/// let view: &VecView<_> = &vec; +/// let view: &VecView<_, _> = &vec; /// ``` -pub type Vec = VecInner>; +/// +/// For uncommmon capacity values, or in generic scenarios, you may have to provide the `LenT` generic yourself. +/// +/// This should be the smallest unsigned integer type that your capacity fits in, or `usize` if you don't want to consider this. +pub type Vec> = + VecInner>; /// A [`Vec`] with dynamic capacity /// @@ -259,16 +272,16 @@ pub type Vec = VecInner>; /// use heapless::{Vec, VecView}; /// /// let mut vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); -/// let view: &VecView<_> = &vec; +/// let view: &VecView<_, _> = &vec; /// assert_eq!(view, &[1, 2, 3, 4]); /// -/// let mut_view: &mut VecView<_> = &mut vec; +/// let mut_view: &mut VecView<_, _> = &mut vec; /// mut_view.push(5); /// assert_eq!(vec, [1, 2, 3, 4, 5]); /// ``` -pub type VecView = VecInner>; +pub type VecView = VecInner>; -impl Vec { +impl Vec { const ELEM: MaybeUninit = MaybeUninit::uninit(); const INIT: [MaybeUninit; N] = [Self::ELEM; N]; // important for optimization of `new` @@ -286,9 +299,11 @@ impl Vec { /// static mut X: Vec = Vec::new(); /// ``` pub const fn new() -> Self { + const { check_capacity_fits::() } + Self { phantom: PhantomData, - len: 0, + len: LenT::ZERO, buffer: VecStorageInner { buffer: Self::INIT }, } } @@ -333,7 +348,7 @@ impl Vec { if N == M { Self { phantom: PhantomData, - len: N, + len: LenT::from_usize(N), // NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit; N] // have the same layout when N == M. buffer: unsafe { mem::transmute_copy(&src) }, @@ -347,7 +362,7 @@ impl Vec { dst_elem.write(unsafe { ptr::read(src_elem) }); } - v.len = M; + unsafe { v.set_len(M) }; v } } @@ -392,9 +407,27 @@ impl Vec { } new } + + /// Casts the `LenT` type to a new type, preserving everything else about the vector. + /// + /// This can be useful if you need to pass a `Vec` into a `Vec` for example. + /// + /// This will check at compile time if the `N` value will fit into `NewLenT`, and error if not. + pub fn cast_len_type(self) -> Vec { + const { check_capacity_fits::() } + let this = ManuallyDrop::new(self); + + // SAFETY: Pointer argument is derived from a reference, meeting the safety documented invariants. + // This also prevents double drops by wrapping `self` in `ManuallyDrop`. + Vec { + len: NewLenT::from_usize(this.len()), + buffer: unsafe { ptr::read(&this.buffer) }, + phantom: PhantomData, + } + } } -impl + ?Sized> VecInner { +impl + ?Sized> VecInner { /// Removes the specified range from the vector in bulk, returning all /// removed elements as an iterator. If the iterator is dropped before /// being fully consumed, it drops the remaining removed elements. @@ -427,7 +460,7 @@ impl + ?Sized> VecInner { /// v.drain(..); /// assert_eq!(v, &[]); /// ``` - pub fn drain(&mut self, range: R) -> Drain<'_, T> + pub fn drain(&mut self, range: R) -> Drain<'_, T, LenT> where R: RangeBounds, { @@ -450,8 +483,8 @@ impl + ?Sized> VecInner { let vec = NonNull::from(self.as_mut_view()); let range_slice = slice::from_raw_parts(vec.as_ref().as_ptr().add(start), end - start); Drain { - tail_start: end, - tail_len: len - end, + tail_start: LenT::from_usize(end), + tail_len: LenT::from_usize(len - end), iter: range_slice.iter(), vec, } @@ -464,7 +497,7 @@ impl + ?Sized> VecInner { /// ```rust /// # use heapless::{Vec, VecView}; /// let vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); - /// let view: &VecView = vec.as_view(); + /// let view: &VecView = vec.as_view(); /// ``` /// /// It is often preferable to do the same through type coerction, since `Vec` implements `Unsize>`: @@ -472,10 +505,10 @@ impl + ?Sized> VecInner { /// ```rust /// # use heapless::{Vec, VecView}; /// let vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); - /// let view: &VecView = &vec; + /// let view: &VecView = &vec; /// ``` #[inline] - pub fn as_view(&self) -> &VecView { + pub fn as_view(&self) -> &VecView { S::as_vec_view(self) } @@ -483,19 +516,19 @@ impl + ?Sized> VecInner { /// /// ```rust /// # use heapless::{Vec, VecView}; - /// let mut vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); - /// let view: &mut VecView = vec.as_mut_view(); + /// let mut vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); + /// let view: &mut VecView = vec.as_mut_view(); /// ``` /// /// It is often preferable to do the same through type coerction, since `Vec` implements `Unsize>`: /// /// ```rust /// # use heapless::{Vec, VecView}; - /// let mut vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); - /// let view: &mut VecView = &mut vec; + /// let mut vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); + /// let view: &mut VecView = &mut vec; /// ``` #[inline] - pub fn as_mut_view(&mut self) -> &mut VecView { + pub fn as_mut_view(&mut self) -> &mut VecView { S::as_vec_mut_view(self) } @@ -523,7 +556,12 @@ impl + ?Sized> VecInner { pub fn as_slice(&self) -> &[T] { // NOTE(unsafe) avoid bound checks in the slicing operation // &buffer[..self.len] - unsafe { slice::from_raw_parts(self.buffer.borrow().as_ptr().cast::(), self.len) } + unsafe { + slice::from_raw_parts( + self.buffer.borrow().as_ptr().cast::(), + self.len.into_usize(), + ) + } } /// Extracts a mutable slice containing the entire vector. @@ -543,7 +581,10 @@ impl + ?Sized> VecInner { // NOTE(unsafe) avoid bound checks in the slicing operation // &mut buffer[..self.len] unsafe { - slice::from_raw_parts_mut(self.buffer.borrow_mut().as_mut_ptr().cast::(), self.len) + slice::from_raw_parts_mut( + self.buffer.borrow_mut().as_mut_ptr().cast::(), + self.len.into_usize(), + ) } } @@ -590,21 +631,23 @@ impl + ?Sized> VecInner { where T: Clone, { - pub fn extend_from_slice_inner( - len: &mut usize, + pub fn extend_from_slice_inner( + len: &mut LenT, buf: &mut [MaybeUninit], other: &[T], ) -> Result<(), CapacityError> where T: Clone, { - if *len + other.len() > buf.len() { + if len.into_usize() + other.len() > buf.len() { // won't fit in the `Vec`; don't modify anything and return an error Err(CapacityError) } else { for elem in other { - unsafe { *buf.get_unchecked_mut(*len) = MaybeUninit::new(elem.clone()) } - *len += 1; + unsafe { + *buf.get_unchecked_mut(len.into_usize()) = MaybeUninit::new(elem.clone()); + } + *len += LenT::ONE; } Ok(()) } @@ -615,10 +658,10 @@ impl + ?Sized> VecInner { /// Removes the last element from a vector and returns it, or `None` if it's empty pub fn pop(&mut self) -> Option { - if self.len != 0 { - Some(unsafe { self.pop_unchecked() }) - } else { + if self.len == LenT::ZERO { None + } else { + Some(unsafe { self.pop_unchecked() }) } } @@ -626,7 +669,7 @@ impl + ?Sized> VecInner { /// /// Returns back the `item` if the vector is full. pub fn push(&mut self, item: T) -> Result<(), T> { - if self.len < self.capacity() { + if self.len() < self.capacity() { unsafe { self.push_unchecked(item) } Ok(()) } else { @@ -642,10 +685,10 @@ impl + ?Sized> VecInner { pub unsafe fn pop_unchecked(&mut self) -> T { debug_assert!(!self.is_empty()); - self.len -= 1; + self.len -= LenT::ONE; self.buffer .borrow_mut() - .get_unchecked_mut(self.len) + .get_unchecked_mut(self.len.into_usize()) .as_ptr() .read() } @@ -660,9 +703,12 @@ impl + ?Sized> VecInner { // use `ptr::write` to avoid running `T`'s destructor on the uninitialized memory debug_assert!(!self.is_full()); - *self.buffer.borrow_mut().get_unchecked_mut(self.len) = MaybeUninit::new(item); + *self + .buffer + .borrow_mut() + .get_unchecked_mut(self.len.into_usize()) = MaybeUninit::new(item); - self.len += 1; + self.len += LenT::ONE; } /// Shortens the vector, keeping the first `len` elements and dropping the rest. @@ -678,12 +724,12 @@ impl + ?Sized> VecInner { // Note: It's intentional that this is `>` and not `>=`. // Changing it to `>=` has negative performance // implications in some cases. See rust-lang/rust#78884 for more. - if len > self.len { + if len > self.len() { return; } - let remaining_len = self.len - len; + let remaining_len = self.len() - len; let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); - self.len = len; + self.len = LenT::from_usize(len); ptr::drop_in_place(s); } } @@ -703,8 +749,8 @@ impl + ?Sized> VecInner { return Err(CapacityError); } - if new_len > self.len { - while self.len < new_len { + if new_len > self.len() { + while self.len() < new_len { self.push(value.clone()).ok(); } } else { @@ -820,7 +866,7 @@ impl + ?Sized> VecInner { pub unsafe fn set_len(&mut self, new_len: usize) { debug_assert!(new_len <= self.capacity()); - self.len = new_len; + self.len = LenT::from_usize(new_len); } /// Removes an element from the vector and returns it. @@ -851,7 +897,7 @@ impl + ?Sized> VecInner { /// assert_eq!(&*v, ["baz", "qux"]); /// ``` pub fn swap_remove(&mut self, index: usize) -> T { - assert!(index < self.len); + assert!(index < self.len()); unsafe { self.swap_remove_unchecked(index) } } @@ -888,18 +934,18 @@ impl + ?Sized> VecInner { let value = ptr::read(self.as_ptr().add(index)); let base_ptr = self.as_mut_ptr(); ptr::copy(base_ptr.add(length - 1), base_ptr.add(index), 1); - self.len -= 1; + self.len -= LenT::ONE; value } /// Returns true if the vec is full pub fn is_full(&self) -> bool { - self.len == self.capacity() + self.len() == self.capacity() } /// Returns true if the vec is empty pub fn is_empty(&self) -> bool { - self.len == 0 + self.len == LenT::ZERO } /// Returns `true` if `needle` is a prefix of the Vec. @@ -921,7 +967,7 @@ impl + ?Sized> VecInner { T: PartialEq, { let n = needle.len(); - self.len >= n && needle == &self[..n] + self.len() >= n && needle == &self[..n] } /// Returns `true` if `needle` is a suffix of the Vec. @@ -1107,7 +1153,7 @@ impl + ?Sized> VecInner { where F: FnMut(&mut T) -> bool, { - let original_len = self.len(); + let original_len = self.len; // Avoid double drop if the drop guard is not executed, // since we may make some holes during the process. unsafe { self.set_len(0) }; @@ -1123,56 +1169,57 @@ impl + ?Sized> VecInner { // This drop guard will be invoked when predicate or `drop` of element panicked. // It shifts unchecked elements to cover holes and `set_len` to the correct length. // In cases when predicate and `drop` never panick, it will be optimized out. - struct BackshiftOnDrop<'a, T, S: VecStorage + ?Sized> { - v: &'a mut VecInner, - processed_len: usize, - deleted_cnt: usize, - original_len: usize, + struct BackshiftOnDrop<'a, T, LenT: LenType, S: VecStorage + ?Sized> { + v: &'a mut VecInner, + processed_len: LenT, + deleted_cnt: LenT, + original_len: LenT, } - impl + ?Sized> Drop for BackshiftOnDrop<'_, T, S> { + impl + ?Sized> Drop for BackshiftOnDrop<'_, T, LenT, S> { fn drop(&mut self) { - if self.deleted_cnt > 0 { + if self.deleted_cnt > LenT::ZERO { // SAFETY: Trailing unchecked items must be valid since we never touch them. unsafe { ptr::copy( - self.v.as_ptr().add(self.processed_len), + self.v.as_ptr().add(self.processed_len.into_usize()), self.v .as_mut_ptr() - .add(self.processed_len - self.deleted_cnt), - self.original_len - self.processed_len, + .add((self.processed_len - self.deleted_cnt).into_usize()), + (self.original_len - self.processed_len).into_usize(), ); } } // SAFETY: After filling holes, all items are in contiguous memory. unsafe { - self.v.set_len(self.original_len - self.deleted_cnt); + self.v + .set_len((self.original_len - self.deleted_cnt).into_usize()); } } } let mut g = BackshiftOnDrop { v: self, - processed_len: 0, - deleted_cnt: 0, + processed_len: LenT::ZERO, + deleted_cnt: LenT::ZERO, original_len, }; - fn process_loop + ?Sized, const DELETED: bool>( - original_len: usize, + fn process_loop + ?Sized, const DELETED: bool>( + original_len: LenT, f: &mut F, - g: &mut BackshiftOnDrop<'_, T, S>, + g: &mut BackshiftOnDrop<'_, T, LenT, S>, ) where F: FnMut(&mut T) -> bool, { while g.processed_len != original_len { let p = g.v.as_mut_ptr(); // SAFETY: Unchecked element must be valid. - let cur = unsafe { &mut *p.add(g.processed_len) }; + let cur = unsafe { &mut *p.add(g.processed_len.into_usize()) }; if !f(cur) { // Advance early to avoid double drop if `drop_in_place` panicked. - g.processed_len += 1; - g.deleted_cnt += 1; + g.processed_len += LenT::ONE; + g.deleted_cnt += LenT::ONE; // SAFETY: We never touch this element again after dropped. unsafe { ptr::drop_in_place(cur) }; // We already advanced the counter. @@ -1186,19 +1233,19 @@ impl + ?Sized> VecInner { // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element. // We use copy for move, and never touch this element again. unsafe { - let hole_slot = p.add(g.processed_len - g.deleted_cnt); + let hole_slot = p.add((g.processed_len - g.deleted_cnt).into_usize()); ptr::copy_nonoverlapping(cur, hole_slot, 1); } } - g.processed_len += 1; + g.processed_len += LenT::ONE; } } // Stage 1: Nothing was deleted. - process_loop::(original_len, &mut f, &mut g); + process_loop::(original_len, &mut f, &mut g); // Stage 2: Some elements were deleted. - process_loop::(original_len, &mut f, &mut g); + process_loop::(original_len, &mut f, &mut g); // All item are processed. This can be optimized to `set_len` by LLVM. drop(g); @@ -1232,19 +1279,19 @@ impl + ?Sized> VecInner { /// ``` #[inline] pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { - &mut self.buffer.borrow_mut()[self.len..] + &mut self.buffer.borrow_mut()[self.len.into_usize()..] } } // Trait implementations -impl Default for Vec { +impl Default for Vec { fn default() -> Self { Self::new() } } -impl + ?Sized> fmt::Debug for VecInner +impl + ?Sized> fmt::Debug for VecInner where T: fmt::Debug, { @@ -1253,7 +1300,7 @@ where } } -impl + ?Sized> fmt::Write for VecInner { +impl + ?Sized> fmt::Write for VecInner { fn write_str(&mut self, s: &str) -> fmt::Result { match self.extend_from_slice(s.as_bytes()) { Ok(()) => Ok(()), @@ -1262,13 +1309,13 @@ impl + ?Sized> fmt::Write for VecInner { } } -impl From<[T; M]> for Vec { +impl From<[T; M]> for Vec { fn from(array: [T; M]) -> Self { Self::from_array(array) } } -impl + ?Sized> Drop for VecInner { +impl + ?Sized> Drop for VecInner { fn drop(&mut self) { let mut_slice = self.as_mut_slice(); // We drop each element used in the vector by turning into a `&mut [T]`. @@ -1279,7 +1326,7 @@ impl + ?Sized> Drop for VecInner { #[cfg(feature = "alloc")] /// Converts the given `alloc::vec::Vec` into a `Vec`. -impl TryFrom> for Vec { +impl TryFrom> for Vec { type Error = CapacityError; /// Converts the given `alloc::vec::Vec` into a `Vec`. @@ -1288,7 +1335,7 @@ impl TryFrom> for Vec { /// /// Returns `Err` if the length of the `alloc::vec::Vec` is greater than `N`. fn try_from(alloc_vec: alloc::vec::Vec) -> Result { - let mut vec = Vec::new(); + let mut vec = Self::new(); for e in alloc_vec { // Push each element individually to allow handling capacity errors. @@ -1301,7 +1348,7 @@ impl TryFrom> for Vec { #[cfg(feature = "alloc")] /// Converts the given `Vec` into an `alloc::vec::Vec`. -impl TryFrom> for alloc::vec::Vec { +impl TryFrom> for alloc::vec::Vec { type Error = alloc::collections::TryReserveError; /// Converts the given `Vec` into an `alloc::vec::Vec`. @@ -1309,8 +1356,8 @@ impl TryFrom> for alloc::vec::Vec { /// # Errors /// /// Returns `Err` if the `alloc::vec::Vec` fails to allocate memory. - fn try_from(vec: Vec) -> Result { - let mut alloc_vec = alloc::vec::Vec::new(); + fn try_from(vec: Vec) -> Result { + let mut alloc_vec = Self::new(); // Allocate enough space for the elements, return an error if the // allocation fails. @@ -1324,7 +1371,7 @@ impl TryFrom> for alloc::vec::Vec { } } -impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec { +impl<'a, T: Clone, LenT: LenType, const N: usize> TryFrom<&'a [T]> for Vec { type Error = CapacityError; fn try_from(slice: &'a [T]) -> Result { @@ -1332,7 +1379,7 @@ impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec { } } -impl + ?Sized> Extend for VecInner { +impl + ?Sized> Extend for VecInner { fn extend(&mut self, iter: I) where I: IntoIterator, @@ -1341,7 +1388,7 @@ impl + ?Sized> Extend for VecInner { } } -impl<'a, T, S: VecStorage + ?Sized> Extend<&'a T> for VecInner +impl<'a, T, LenT: LenType, S: VecStorage + ?Sized> Extend<&'a T> for VecInner where T: 'a + Copy, { @@ -1353,7 +1400,7 @@ where } } -impl + ?Sized> hash::Hash for VecInner +impl + ?Sized> hash::Hash for VecInner where T: core::hash::Hash, { @@ -1362,7 +1409,7 @@ where } } -impl<'a, T, S: VecStorage + ?Sized> IntoIterator for &'a VecInner { +impl<'a, T, LenT: LenType, S: VecStorage + ?Sized> IntoIterator for &'a VecInner { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; @@ -1371,7 +1418,9 @@ impl<'a, T, S: VecStorage + ?Sized> IntoIterator for &'a VecInner { } } -impl<'a, T, S: VecStorage + ?Sized> IntoIterator for &'a mut VecInner { +impl<'a, T, LenT: LenType, S: VecStorage + ?Sized> IntoIterator + for &'a mut VecInner +{ type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; @@ -1380,7 +1429,7 @@ impl<'a, T, S: VecStorage + ?Sized> IntoIterator for &'a mut VecInner { } } -impl FromIterator for Vec { +impl FromIterator for Vec { fn from_iter(iter: I) -> Self where I: IntoIterator, @@ -1396,24 +1445,24 @@ impl FromIterator for Vec { /// An iterator that moves out of an [`Vec`][`Vec`]. /// /// This struct is created by calling the `into_iter` method on [`Vec`][`Vec`]. -pub struct IntoIter { - vec: Vec, - next: usize, +pub struct IntoIter { + vec: Vec, + next: LenT, } -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { - if self.next < self.vec.len() { + if self.next < self.vec.len { let item = unsafe { self.vec .buffer .buffer - .get_unchecked_mut(self.next) + .get_unchecked_mut(self.next.into_usize()) .as_ptr() .read() }; - self.next += 1; + self.next += LenT::ONE; Some(item) } else { None @@ -1421,105 +1470,128 @@ impl Iterator for IntoIter { } } -impl Clone for IntoIter +impl Clone for IntoIter where T: Clone, { fn clone(&self) -> Self { let mut vec = Vec::new(); - if self.next < self.vec.len() { + if self.next < self.vec.len { let s = unsafe { slice::from_raw_parts( - self.vec.buffer.buffer.as_ptr().cast::().add(self.next), - self.vec.len() - self.next, + self.vec + .buffer + .buffer + .as_ptr() + .cast::() + .add(self.next.into_usize()), + (self.vec.len - self.next).into_usize(), ) }; vec.extend_from_slice(s).ok(); } - Self { vec, next: 0 } - } -} - -impl Drop for IntoIter { - fn drop(&mut self) { - unsafe { - // Drop all the elements that have not been moved out of vec - ptr::drop_in_place(&mut self.vec.as_mut_slice()[self.next..]); - // Prevent dropping of other elements - self.vec.len = 0; + Self { + vec, + next: LenT::ZERO, } } } -impl IntoIterator for Vec { - type Item = T; - type IntoIter = IntoIter; - - fn into_iter(self) -> Self::IntoIter { - IntoIter { vec: self, next: 0 } +impl Drop for IntoIter { + fn drop(&mut self) { + unsafe { + // Drop all the elements that have not been moved out of vec + ptr::drop_in_place(&mut self.vec.as_mut_slice()[self.next.into_usize()..]); + // Prevent dropping of other elements + self.vec.len = LenT::ZERO; + } } } -impl + ?Sized, SB: VecStorage + ?Sized> PartialEq> - for VecInner +impl IntoIterator for Vec { + type Item = T; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter { + vec: self, + next: LenT::ZERO, + } + } +} + +impl PartialEq> for VecInner where A: PartialEq, + LenTA: LenType, + LenTB: LenType, + SA: VecStorage + ?Sized, + SB: VecStorage + ?Sized, { - fn eq(&self, other: &VecInner) -> bool { + fn eq(&self, other: &VecInner) -> bool { self.as_slice().eq(other.as_slice()) } } -impl + ?Sized> PartialEq> for [A; M] +impl PartialEq> for [A; M] where A: PartialEq, + LenTB: LenType, + SB: VecStorage, { - fn eq(&self, other: &VecInner) -> bool { + fn eq(&self, other: &VecInner) -> bool { self.eq(other.as_slice()) } } -impl + ?Sized, const M: usize> PartialEq> for &[A; M] +impl PartialEq> for &[A; M] where A: PartialEq, + LenTB: LenType, + SB: VecStorage, { - fn eq(&self, other: &VecInner) -> bool { + fn eq(&self, other: &VecInner) -> bool { (*self).eq(other) } } -impl + ?Sized> PartialEq> for [A] +impl PartialEq> for [A] where A: PartialEq, + LenTB: LenType, + SB: VecStorage, { - fn eq(&self, other: &VecInner) -> bool { + fn eq(&self, other: &VecInner) -> bool { self.eq(other.as_slice()) } } -impl + ?Sized> PartialEq> for &[A] +impl PartialEq> for &[A] where A: PartialEq, + LenTB: LenType, + SB: VecStorage, { - fn eq(&self, other: &VecInner) -> bool { + fn eq(&self, other: &VecInner) -> bool { (*self).eq(other) } } -impl + ?Sized> PartialEq> for &mut [A] +impl> PartialEq> for &mut [A] where A: PartialEq, { - fn eq(&self, other: &VecInner) -> bool { + fn eq(&self, other: &VecInner) -> bool { (**self).eq(other) } } -impl + ?Sized, const N: usize> PartialEq<[B; N]> for VecInner +impl PartialEq<[B; N]> for VecInner where A: PartialEq, + SA: VecStorage + ?Sized, { #[inline] fn eq(&self, other: &[B; N]) -> bool { @@ -1527,9 +1599,11 @@ where } } -impl + ?Sized, const N: usize> PartialEq<&[B; N]> for VecInner +impl PartialEq<&[B; N]> for VecInner where A: PartialEq, + LenTA: LenType, + SA: VecStorage + ?Sized, { #[inline] fn eq(&self, other: &&[B; N]) -> bool { @@ -1537,9 +1611,11 @@ where } } -impl + ?Sized> PartialEq<[B]> for VecInner +impl PartialEq<[B]> for VecInner where A: PartialEq, + LenTA: LenType, + SA: VecStorage + ?Sized, { #[inline] fn eq(&self, other: &[B]) -> bool { @@ -1547,9 +1623,11 @@ where } } -impl + ?Sized> PartialEq<&[B]> for VecInner +impl PartialEq<&[B]> for VecInner where A: PartialEq, + LenTA: LenType, + SA: VecStorage + ?Sized, { #[inline] fn eq(&self, other: &&[B]) -> bool { @@ -1557,9 +1635,11 @@ where } } -impl + ?Sized> PartialEq<&mut [B]> for VecInner +impl PartialEq<&mut [B]> for VecInner where A: PartialEq, + LenTA: LenType, + SA: VecStorage + ?Sized, { #[inline] fn eq(&self, other: &&mut [B]) -> bool { @@ -1568,19 +1648,19 @@ where } // Implements Eq if underlying data is Eq -impl + ?Sized> Eq for VecInner where T: Eq {} +impl + ?Sized> Eq for VecInner where T: Eq {} -impl + ?Sized, SB: VecStorage + ?Sized> PartialOrd> - for VecInner +impl + ?Sized, SB: VecStorage + ?Sized> + PartialOrd> for VecInner where T: PartialOrd, { - fn partial_cmp(&self, other: &VecInner) -> Option { + fn partial_cmp(&self, other: &VecInner) -> Option { self.as_slice().partial_cmp(other.as_slice()) } } -impl + ?Sized> Ord for VecInner +impl + ?Sized> Ord for VecInner where T: Ord, { @@ -1590,7 +1670,7 @@ where } } -impl + ?Sized> ops::Deref for VecInner { +impl + ?Sized> ops::Deref for VecInner { type Target = [T]; fn deref(&self) -> &Self::Target { @@ -1598,52 +1678,52 @@ impl + ?Sized> ops::Deref for VecInner { } } -impl + ?Sized> ops::DerefMut for VecInner { +impl + ?Sized> ops::DerefMut for VecInner { fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() } } -impl + ?Sized> borrow::Borrow<[T]> for VecInner { +impl + ?Sized> borrow::Borrow<[T]> for VecInner { fn borrow(&self) -> &[T] { self.as_slice() } } -impl + ?Sized> borrow::BorrowMut<[T]> for VecInner { +impl + ?Sized> borrow::BorrowMut<[T]> for VecInner { fn borrow_mut(&mut self) -> &mut [T] { self.as_mut_slice() } } -impl + ?Sized> AsRef for VecInner { +impl + ?Sized> AsRef for VecInner { #[inline] fn as_ref(&self) -> &Self { self } } -impl + ?Sized> AsMut for VecInner { +impl + ?Sized> AsMut for VecInner { #[inline] fn as_mut(&mut self) -> &mut Self { self } } -impl + ?Sized> AsRef<[T]> for VecInner { +impl + ?Sized> AsRef<[T]> for VecInner { #[inline] fn as_ref(&self) -> &[T] { self } } -impl + ?Sized> AsMut<[T]> for VecInner { +impl + ?Sized> AsMut<[T]> for VecInner { #[inline] fn as_mut(&mut self) -> &mut [T] { self } } -impl Clone for Vec +impl Clone for Vec where T: Clone, { @@ -1726,7 +1806,7 @@ mod tests { { let v: Vec = Vec::new(); let v: Box> = Box::new(v); - let mut v: Box> = v; + let mut v: Box> = v; v.push(Droppable::new()).ok().unwrap(); v.push(Droppable::new()).ok().unwrap(); assert_eq!(Droppable::count(), 2); @@ -1739,7 +1819,7 @@ mod tests { { let v: Vec = Vec::new(); let v: Box> = Box::new(v); - let mut v: Box> = v; + let mut v: Box> = v; v.push(Droppable::new()).ok().unwrap(); v.push(Droppable::new()).ok().unwrap(); assert_eq!(Droppable::count(), 2);