diff --git a/src/binary_heap.rs b/src/binary_heap.rs index 7e676a3851..a72e099599 100644 --- a/src/binary_heap.rs +++ b/src/binary_heap.rs @@ -17,10 +17,7 @@ use core::{ ptr, slice, }; -use crate::{ - storage::{OwnedStorage, Storage, ViewStorage}, - vec::{Vec, VecInner}, -}; +use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage}; /// Min-heap pub enum Min {} @@ -58,7 +55,7 @@ impl private::Sealed for Min {} /// /// In most cases you should use [`BinaryHeap`] or [`BinaryHeapView`] directly. Only use this /// struct if you want to write code that's generic over both. -pub struct BinaryHeapInner { +pub struct BinaryHeapInner + ?Sized> { pub(crate) _kind: PhantomData, pub(crate) data: VecInner, } @@ -109,7 +106,7 @@ pub struct BinaryHeapInner { /// // The heap should now be empty. /// assert!(heap.is_empty()) /// ``` -pub type BinaryHeap = BinaryHeapInner>; +pub type BinaryHeap = BinaryHeapInner>; /// A priority queue implemented with a binary heap. /// @@ -158,7 +155,7 @@ pub type BinaryHeap = BinaryHeapInner = BinaryHeapInner; +pub type BinaryHeapView = BinaryHeapInner>; impl BinaryHeap { /* Constructors */ @@ -198,7 +195,7 @@ impl BinaryHeap { } } -impl BinaryHeapInner +impl + ?Sized> BinaryHeapInner where T: Ord, K: Kind, @@ -519,7 +516,7 @@ pub struct PeekMutInner<'a, T, K, S> where T: Ord, K: Kind, - S: Storage, + S: VecStorage + ?Sized, { heap: &'a mut BinaryHeapInner, sift: bool, @@ -530,20 +527,20 @@ where /// /// This `struct` is created by [`BinaryHeap::peek_mut`]. /// See its documentation for more. -pub type PeekMut<'a, T, K, const N: usize> = PeekMutInner<'a, T, K, OwnedStorage>; +pub type PeekMut<'a, T, K, const N: usize> = PeekMutInner<'a, T, K, OwnedVecStorage>; /// Structure wrapping a mutable reference to the greatest item on a /// `BinaryHeap`. /// /// This `struct` is created by [`BinaryHeapView::peek_mut`]. /// See its documentation for more. -pub type PeekMutView<'a, T, K> = PeekMutInner<'a, T, K, ViewStorage>; +pub type PeekMutView<'a, T, K> = PeekMutInner<'a, T, K, ViewVecStorage>; impl Drop for PeekMutInner<'_, T, K, S> where T: Ord, K: Kind, - S: Storage, + S: VecStorage + ?Sized, { fn drop(&mut self) { if self.sift { @@ -556,7 +553,7 @@ impl Deref for PeekMutInner<'_, T, K, S> where T: Ord, K: Kind, - S: Storage, + S: VecStorage + ?Sized, { type Target = T; fn deref(&self) -> &T { @@ -570,7 +567,7 @@ impl DerefMut for PeekMutInner<'_, T, K, S> where T: Ord, K: Kind, - S: Storage, + S: VecStorage + ?Sized, { fn deref_mut(&mut self) -> &mut T { debug_assert!(!self.heap.is_empty()); @@ -583,7 +580,7 @@ impl<'a, T, K, S> PeekMutInner<'a, T, K, S> where T: Ord, K: Kind, - S: Storage, + S: VecStorage + ?Sized, { /// Removes the peeked value from the heap and returns it. pub fn pop(mut this: PeekMutInner<'a, T, K, S>) -> T { @@ -631,7 +628,7 @@ impl fmt::Debug for BinaryHeapInner where K: Kind, T: Ord + fmt::Debug, - S: Storage, + S: VecStorage + ?Sized, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter()).finish() @@ -642,7 +639,7 @@ impl<'a, T, K, S> IntoIterator for &'a BinaryHeapInner where K: Kind, T: Ord, - S: Storage, + S: VecStorage + ?Sized, { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; @@ -656,7 +653,7 @@ where mod tests { use static_assertions::assert_not_impl_any; - use super::{BinaryHeap, Max, Min}; + use super::{BinaryHeap, BinaryHeapView, Max, Min}; // Ensure a `BinaryHeap` containing `!Send` values stays `!Send` itself. assert_not_impl_any!(BinaryHeap<*const (), Max, 4>: Send); @@ -829,4 +826,13 @@ mod tests { assert_eq!(heap.pop(), Some(1)); assert_eq!(heap.pop(), None); } + + fn _test_variance<'a: 'b, 'b>(x: BinaryHeap<&'a (), Max, 42>) -> BinaryHeap<&'b (), Max, 42> { + x + } + fn _test_variance_view<'a: 'b, 'b, 'c>( + x: &'c BinaryHeapView<&'a (), Max>, + ) -> &'c BinaryHeapView<&'b (), Max> { + x + } } diff --git a/src/deque.rs b/src/deque.rs index 5f09756f75..695630142c 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -33,19 +33,21 @@ //! } //! ``` -use core::borrow::{Borrow, BorrowMut}; use core::fmt; use core::iter::FusedIterator; +use core::marker::PhantomData; use core::mem::MaybeUninit; use core::{ptr, slice}; -use crate::storage::{OwnedStorage, Storage, ViewStorage}; +use crate::vec::{OwnedVecStorage, VecStorage, VecStorageInner, ViewVecStorage}; /// Base struct for [`Deque`] and [`Deque`], generic over the [`Storage`]. /// /// In most cases you should use [`Deque`] or [`Deque`] directly. Only use this /// struct if you want to write code that's generic over both. -pub struct DequeInner { +pub struct DequeInner + ?Sized> { + // This phantomdata is required because otherwise rustc thinks that `T` is not used + phantom: PhantomData, /// Front index. Always 0..=(N-1) front: usize, /// Back index. Always 0..=(N-1). @@ -54,7 +56,7 @@ pub struct DequeInner { /// Used to distinguish "empty" and "full" cases when `front == back`. /// May only be `true` if `front == back`, always `false` otherwise. full: bool, - buffer: S::Buffer>, + buffer: S, } /// A fixed capacity double-ended queue. @@ -91,7 +93,7 @@ pub struct DequeInner { /// println!("{}", x); /// } /// ``` -pub type Deque = DequeInner>; +pub type Deque = DequeInner>; /// A double-ended queue with dynamic capacity. /// @@ -130,7 +132,7 @@ pub type Deque = DequeInner>; /// println!("{}", x); /// } /// ``` -pub type DequeView = DequeInner; +pub type DequeView = DequeInner>; impl Deque { const INIT: MaybeUninit = MaybeUninit::uninit(); @@ -153,7 +155,10 @@ impl Deque { crate::sealed::greater_than_0::(); Self { - buffer: [Self::INIT; N], + phantom: PhantomData, + buffer: VecStorageInner { + buffer: [Self::INIT; N], + }, front: 0, back: 0, full: false, @@ -191,7 +196,7 @@ impl Deque { } } -impl DequeInner { +impl + ?Sized> DequeInner { /// Returns the maximum number of elements the deque can hold. pub fn storage_capacity(&self) -> usize { self.buffer.borrow().len() @@ -794,7 +799,7 @@ impl Default for Deque { } } -impl Drop for DequeInner { +impl + ?Sized> Drop for DequeInner { fn drop(&mut self) { // safety: `self` is left in an inconsistent state but it doesn't matter since // it's getting dropped. Nothing should be able to observe `self` after drop. @@ -802,21 +807,21 @@ impl Drop for DequeInner { } } -impl fmt::Debug for DequeInner { +impl + ?Sized> fmt::Debug for DequeInner { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self).finish() } } /// As with the standard library's `VecDeque`, items are added via `push_back`. -impl Extend for DequeInner { +impl + ?Sized> Extend for DequeInner { fn extend>(&mut self, iter: I) { for item in iter { self.push_back(item).ok().unwrap(); } } } -impl<'a, T: 'a + Copy, S: Storage> Extend<&'a T> for DequeInner { +impl<'a, T: 'a + Copy, S: VecStorage + ?Sized> Extend<&'a T> for DequeInner { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().copied()) } @@ -846,7 +851,7 @@ impl IntoIterator for Deque { } } -impl<'a, T, S: Storage> IntoIterator for &'a DequeInner { +impl<'a, T, S: VecStorage + ?Sized> IntoIterator for &'a DequeInner { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -855,7 +860,7 @@ impl<'a, T, S: Storage> IntoIterator for &'a DequeInner { } } -impl<'a, T, S: Storage> IntoIterator for &'a mut DequeInner { +impl<'a, T, S: VecStorage + ?Sized> IntoIterator for &'a mut DequeInner { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; diff --git a/src/histbuf.rs b/src/histbuf.rs index 93e79fbe33..ec8d45ebe4 100644 --- a/src/histbuf.rs +++ b/src/histbuf.rs @@ -31,8 +31,6 @@ //! assert_eq!(avg, 4); //! ``` -use core::borrow::Borrow; -use core::borrow::BorrowMut; use core::fmt; use core::marker::PhantomData; use core::mem::MaybeUninit; @@ -40,18 +38,84 @@ use core::ops::Deref; use core::ptr; use core::slice; -use crate::storage::OwnedStorage; -use crate::storage::Storage; -use crate::storage::ViewStorage; +mod storage { + use core::mem::MaybeUninit; + + /// Trait defining how data for a container is stored. + /// + /// There's two implementations available: + /// + /// - [`OwnedHistBufStorage`]: stores the data in an array `[T; N]` whose size is known at compile time. + /// - [`ViewHistBufStorage`]: stores the data in an unsized `[T]`. + /// + /// This allows containers to be generic over either sized or unsized storage. For example, + /// the [`vec`](crate::vec) module contains a [`HistBufInner`](crate::vec::HistBufInner) struct + /// that's generic on [`Storage`], and two type aliases for convenience: + /// + /// - [`HistBuf`](crate::vec::HistBuf) = `HistBufInner>` + /// - [`HistBufView`](crate::vec::HistBufView) = `HistBufInner>` + /// + /// `HistBuf` can be unsized into `HistBufView`, either by unsizing coercions such as `&mut HistBuf -> &mut HistBufView` or + /// `Box -> Box`, or explicitly with [`.as_view()`](crate::vec::HistBuf::as_view) or [`.as_mut_view()`](crate::vec::HistBuf::as_mut_view). + /// + /// This trait is sealed, so you cannot implement it for your own types. You can only use + /// the implementations provided by this crate. + #[allow(private_bounds)] + pub trait HistBufStorage: HistBufSealedStorage {} + + pub trait HistBufSealedStorage { + // part of the sealed trait so that no trait is publicly implemented by `OwnedHistBufStorage` besides `Storage` + fn borrow(&self) -> &[MaybeUninit]; + fn borrow_mut(&mut self) -> &mut [MaybeUninit]; + } + + // One sealed layer of indirection to hide the internal details (The MaybeUninit). + pub struct HistBufStorageInner { + pub(crate) buffer: T, + } + + /// Implementation of [`HistBufStorage`] that stores the data in an array `[T; N]` whose size is known at compile time. + pub type OwnedHistBufStorage = HistBufStorageInner<[MaybeUninit; N]>; + /// Implementation of [`HistBufStorage`] that stores the data in an unsized `[T]`. + pub type ViewHistBufStorage = HistBufStorageInner<[MaybeUninit]>; + + impl HistBufSealedStorage for OwnedHistBufStorage { + fn borrow(&self) -> &[MaybeUninit] { + &self.buffer + } + fn borrow_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buffer + } + } + impl HistBufStorage for OwnedHistBufStorage {} + + impl HistBufSealedStorage for ViewHistBufStorage { + fn borrow(&self) -> &[MaybeUninit] { + &self.buffer + } + fn borrow_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buffer + } + } + impl HistBufStorage for ViewHistBufStorage {} +} + +pub use storage::{HistBufStorage, OwnedHistBufStorage, ViewHistBufStorage}; + +use storage::HistBufStorageInner; + +use self::storage::HistBufSealedStorage; /// Base struct for [`HistoryBuffer`] and [`HistoryBufferView`], generic over the [`Storage`]. /// /// In most cases you should use [`HistoryBuffer`] or [`HistoryBufferView`] directly. Only use this /// struct if you want to write code that's generic over both. -pub struct HistoryBufferInner { +pub struct HistoryBufferInner + ?Sized> { + // This phantomdata is required because otherwise rustc thinks that `T` is not used + phantom: PhantomData, write_at: usize, filled: bool, - data: S::Buffer>, + data: S, } /// A "history buffer", similar to a write-only ring buffer of fixed length. @@ -86,7 +150,7 @@ pub struct HistoryBufferInner { /// let avg = buf.as_slice().iter().sum::() / buf.len(); /// assert_eq!(avg, 4); /// ``` -pub type HistoryBuffer = HistoryBufferInner>; +pub type HistoryBuffer = HistoryBufferInner>; /// A "view" into a [`HistoryBuffer`] /// @@ -119,7 +183,7 @@ pub type HistoryBuffer = HistoryBufferInner() / buf.len(); /// assert_eq!(avg, 4); /// ``` -pub type HistoryBufferView = HistoryBufferInner; +pub type HistoryBufferView = HistoryBufferInner>; impl HistoryBuffer { const INIT: MaybeUninit = MaybeUninit::uninit(); @@ -143,7 +207,10 @@ impl HistoryBuffer { crate::sealed::greater_than_0::(); Self { - data: [Self::INIT; N], + phantom: PhantomData, + data: HistBufStorageInner { + buffer: [Self::INIT; N], + }, write_at: 0, filled: false, } @@ -169,13 +236,16 @@ where #[inline] pub fn new_with(t: T) -> Self { Self { - data: [MaybeUninit::new(t); N], + phantom: PhantomData, + data: HistBufStorageInner { + buffer: [MaybeUninit::new(t); N], + }, write_at: 0, filled: true, } } } -impl HistoryBufferInner { +impl + ?Sized> HistoryBufferInner { /// Clears the buffer, replacing every element with the given value. pub fn clear_with(&mut self, t: T) { // SAFETY: we reset the values just after @@ -189,7 +259,7 @@ impl HistoryBufferInner { } } -impl HistoryBufferInner { +impl + ?Sized> HistoryBufferInner { /// Clears the buffer pub fn clear(&mut self) { // SAFETY: we reset the values just after @@ -199,7 +269,7 @@ impl HistoryBufferInner { } } -impl HistoryBufferInner { +impl + ?Sized> HistoryBufferInner { unsafe fn drop_contents(&mut self) { unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut( @@ -407,7 +477,7 @@ impl HistoryBufferInner { } } -impl Extend for HistoryBufferInner { +impl + ?Sized> Extend for HistoryBufferInner { fn extend(&mut self, iter: I) where I: IntoIterator, @@ -418,7 +488,7 @@ impl Extend for HistoryBufferInner { } } -impl<'a, T, S: Storage> Extend<&'a T> for HistoryBufferInner +impl<'a, T, S: HistBufStorage + ?Sized> Extend<&'a T> for HistoryBufferInner where T: 'a + Clone, { @@ -436,7 +506,7 @@ where { fn clone(&self) -> Self { let mut ret = Self::new(); - for (new, old) in ret.data.iter_mut().zip(self.as_slice()) { + for (new, old) in ret.data.borrow_mut().iter_mut().zip(self.as_slice()) { new.write(old.clone()); } ret.filled = self.filled; @@ -445,13 +515,13 @@ where } } -impl Drop for HistoryBufferInner { +impl + ?Sized> Drop for HistoryBufferInner { fn drop(&mut self) { unsafe { self.drop_contents() } } } -impl Deref for HistoryBufferInner { +impl + ?Sized> Deref for HistoryBufferInner { type Target = [T]; fn deref(&self) -> &[T] { @@ -459,14 +529,14 @@ impl Deref for HistoryBufferInner { } } -impl AsRef<[T]> for HistoryBufferInner { +impl + ?Sized> AsRef<[T]> for HistoryBufferInner { #[inline] fn as_ref(&self) -> &[T] { self } } -impl fmt::Debug for HistoryBufferInner +impl + ?Sized> fmt::Debug for HistoryBufferInner where T: fmt::Debug, { @@ -481,7 +551,7 @@ impl Default for HistoryBuffer { } } -impl PartialEq for HistoryBufferInner +impl + ?Sized> PartialEq for HistoryBufferInner where T: PartialEq, { @@ -494,7 +564,7 @@ where /// /// In most cases you should use [`OldestOrdered`] or [`OldestOrderedView`] directly. Only use this /// struct if you want to write code that's generic over both. -pub struct OldestOrderedInner<'a, T, S: Storage> { +pub struct OldestOrderedInner<'a, T, S: HistBufStorage + ?Sized> { phantom: PhantomData, inner: core::iter::Chain, core::slice::Iter<'a, T>>, } @@ -502,11 +572,12 @@ pub struct OldestOrderedInner<'a, T, S: Storage> { /// Double ended iterator on the underlying buffer ordered from the oldest data /// to the newest /// This type exists for backwards compatibility. It is always better to convert it to an [`OldestOrderedView`] with [`into_view`](OldestOrdered::into_view) -pub type OldestOrdered<'a, T, const N: usize> = OldestOrderedInner<'a, T, OwnedStorage>; +pub type OldestOrdered<'a, T, const N: usize> = + OldestOrderedInner<'a, T, OwnedHistBufStorage>; /// Double ended iterator on the underlying buffer ordered from the oldest data /// to the newest -pub type OldestOrderedView<'a, T> = OldestOrderedInner<'a, T, ViewStorage>; +pub type OldestOrderedView<'a, T> = OldestOrderedInner<'a, T, ViewHistBufStorage>; impl<'a, T, const N: usize> OldestOrdered<'a, T, N> { /// Remove the `N` const-generic parameter from the iterator @@ -534,7 +605,7 @@ impl<'a, T> OldestOrderedView<'a, T> { } } -impl<'a, T, S: Storage> Clone for OldestOrderedInner<'a, T, S> { +impl<'a, T, S: HistBufStorage + ?Sized> Clone for OldestOrderedInner<'a, T, S> { fn clone(&self) -> Self { Self { phantom: PhantomData, @@ -543,7 +614,7 @@ impl<'a, T, S: Storage> Clone for OldestOrderedInner<'a, T, S> { } } -impl<'a, T, S: Storage> Iterator for OldestOrderedInner<'a, T, S> { +impl<'a, T, S: HistBufStorage + ?Sized> Iterator for OldestOrderedInner<'a, T, S> { type Item = &'a T; fn next(&mut self) -> Option<&'a T> { @@ -568,7 +639,7 @@ mod tests { use static_assertions::assert_not_impl_any; - use super::HistoryBuffer; + use super::{HistoryBuffer, HistoryBufferView}; // Ensure a `HistoryBuffer` containing `!Send` values stays `!Send` itself. assert_not_impl_any!(HistoryBuffer<*const (), 4>: Send); @@ -855,4 +926,13 @@ mod tests { x.clear(); assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 3); } + + fn _test_variance<'a: 'b, 'b>(x: HistoryBuffer<&'a (), 42>) -> HistoryBuffer<&'b (), 42> { + x + } + fn _test_variance_view<'a: 'b, 'b, 'c>( + x: &'c HistoryBufferView<&'a ()>, + ) -> &'c HistoryBufferView<&'b ()> { + x + } } diff --git a/src/lib.rs b/src/lib.rs index 17f6056dc3..ee56732ce2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -144,7 +144,7 @@ pub mod mpmc; ) ))] pub mod pool; -pub mod sorted_linked_list; +// pub mod sorted_linked_list; #[cfg(any( // assume we have all atomics available if we're using portable-atomic feature = "portable-atomic", diff --git a/src/linear_map.rs b/src/linear_map.rs index 28f4e83d42..40fd94dca2 100644 --- a/src/linear_map.rs +++ b/src/linear_map.rs @@ -4,26 +4,22 @@ use core::{borrow::Borrow, fmt, mem, ops, slice}; -use crate::{ - storage::{OwnedStorage, Storage, ViewStorage}, - vec::VecInner, - Vec, -}; +use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage}; /// Base struct for [`LinearMap`] and [`LinearMapView`] -pub struct LinearMapInner { +pub struct LinearMapInner + ?Sized> { pub(crate) buffer: VecInner<(K, V), S>, } /// A fixed capacity map/dictionary that performs lookups via linear search. /// /// Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1). -pub type LinearMap = LinearMapInner>; +pub type LinearMap = LinearMapInner>; /// A dynamic capacity map/dictionary that performs lookups via linear search. /// /// Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1). -pub type LinearMapView = LinearMapInner; +pub type LinearMapView = LinearMapInner>; impl LinearMap { /// Creates an empty `LinearMap`. @@ -54,7 +50,7 @@ impl LinearMap { } } -impl LinearMapInner +impl + ?Sized> LinearMapInner where K: Eq, { @@ -371,7 +367,7 @@ where } } -impl<'a, K, V, Q, S: Storage> ops::Index<&'a Q> for LinearMapInner +impl<'a, K, V, Q, S: VecStorage<(K, V)> + ?Sized> ops::Index<&'a Q> for LinearMapInner where K: Borrow + Eq, Q: Eq + ?Sized, @@ -383,7 +379,7 @@ where } } -impl<'a, K, V, Q, S: Storage> ops::IndexMut<&'a Q> for LinearMapInner +impl<'a, K, V, Q, S: VecStorage<(K, V)> + ?Sized> ops::IndexMut<&'a Q> for LinearMapInner where K: Borrow + Eq, Q: Eq + ?Sized, @@ -414,7 +410,7 @@ where } } -impl fmt::Debug for LinearMapInner +impl + ?Sized> fmt::Debug for LinearMapInner where K: Eq + fmt::Debug, V: fmt::Debug, @@ -472,7 +468,7 @@ where } } -impl<'a, K, V, S: Storage> IntoIterator for &'a LinearMapInner +impl<'a, K, V, S: VecStorage<(K, V)> + ?Sized> IntoIterator for &'a LinearMapInner where K: Eq, { @@ -519,8 +515,8 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { } } -impl PartialEq> - for LinearMapInner +impl + ?Sized, S2: VecStorage<(K, V)> + ?Sized> + PartialEq> for LinearMapInner where K: Eq, V: PartialEq, @@ -533,7 +529,7 @@ where } } -impl Eq for LinearMapInner +impl + ?Sized> Eq for LinearMapInner where K: Eq, V: PartialEq, @@ -544,7 +540,7 @@ where mod test { use static_assertions::assert_not_impl_any; - use super::LinearMap; + use super::{LinearMap, LinearMapView}; // Ensure a `LinearMap` containing `!Send` keys stays `!Send` itself. assert_not_impl_any!(LinearMap<*const (), (), 4>: Send); @@ -619,4 +615,23 @@ mod test { assert_eq!(v, src.remove(k).unwrap()); } } + + fn _test_variance_value<'a: 'b, 'b>( + x: LinearMap, + ) -> LinearMap { + x + } + fn _test_variance_value_view<'a: 'b, 'b, 'c>( + x: &'c LinearMapView, + ) -> &'c LinearMapView { + x + } + fn _test_variance_key<'a: 'b, 'b>(x: LinearMap<&'a (), u32, 42>) -> LinearMap<&'b (), u32, 42> { + x + } + fn _test_variance_key_view<'a: 'b, 'b, 'c>( + x: &'c LinearMapView<&'a (), u32>, + ) -> &'c LinearMapView<&'b (), u32> { + x + } } diff --git a/src/sorted_linked_list.rs b/src/sorted_linked_list.rs index a3c9cb502f..fbbe114ed4 100644 --- a/src/sorted_linked_list.rs +++ b/src/sorted_linked_list.rs @@ -26,7 +26,6 @@ //! //! [`BinaryHeap`]: `crate::binary_heap::BinaryHeap` -use core::borrow::{Borrow, BorrowMut}; use core::cmp::Ordering; use core::fmt; use core::marker::PhantomData; @@ -34,7 +33,76 @@ use core::mem::MaybeUninit; use core::ops::{Deref, DerefMut}; use core::ptr; -use crate::storage::{OwnedStorage, Storage, ViewStorage}; +mod storage { + use super::Node; + + /// Trait defining how data for a container is stored. + /// + /// There's two implementations available: + /// + /// - [`OwnedSortedLinkedListStorage`]: stores the data in an array `[T; N]` whose size is known at compile time. + /// - [`ViewSortedLinkedListStorage`]: stores the data in an unsized `[T]`. + /// + /// This allows containers to be generic over either sized or unsized storage. For example, + /// the [`vec`](crate::vec) module contains a [`SortedLinkedListInner`](crate::vec::SortedLinkedListInner) struct + /// that's generic on [`Storage`], and two type aliases for convenience: + /// + /// - [`SortedLinkedList`](crate::vec::SortedLinkedList) = `SortedLinkedListInner>` + /// - [`SortedLinkedListView`](crate::vec::SortedLinkedListView) = `SortedLinkedListInner>` + /// + /// `SortedLinkedList` can be unsized into `SortedLinkedListView`, either by unsizing coercions such as `&mut SortedLinkedList -> &mut SortedLinkedListView` or + /// `Box -> Box`, or explicitly with [`.as_view()`](crate::vec::SortedLinkedList::as_view) or [`.as_mut_view()`](crate::vec::SortedLinkedList::as_mut_view). + /// + /// This trait is sealed, so you cannot implement it for your own types. You can only use + /// the implementations provided by this crate. + #[allow(private_bounds)] + pub trait SortedLinkedListStorage: SortedLinkedListSealedStorage {} + + pub trait SortedLinkedListSealedStorage { + // part of the sealed trait so that no trait is publicly implemented by `OwnedSortedLinkedListStorage` besides `Storage` + fn borrow(&self) -> &[Node]; + fn borrow_mut(&mut self) -> &mut [Node]; + } + + // One sealed layer of indirection to hide the internal details (The MaybeUninit). + pub struct SortedLinkedListStorageInner { + pub(crate) buffer: T, + } + + /// Implementation of [`SortedLinkedListStorage`] that stores the data in an array `[T; N]` whose size is known at compile time. + pub type OwnedSortedLinkedListStorage = + SortedLinkedListStorageInner<[Node; N]>; + /// Implementation of [`SortedLinkedListStorage`] that stores the data in an unsized `[T]`. + pub type ViewSortedLinkedListStorage = SortedLinkedListStorageInner<[Node]>; + + impl SortedLinkedListSealedStorage + for OwnedSortedLinkedListStorage + { + fn borrow(&self) -> &[Node] { + &self.buffer + } + fn borrow_mut(&mut self) -> &mut [Node] { + &mut self.buffer + } + } + impl SortedLinkedListStorage + for OwnedSortedLinkedListStorage + { + } + + impl SortedLinkedListSealedStorage for ViewSortedLinkedListStorage { + fn borrow(&self) -> &[Node] { + &self.buffer + } + fn borrow_mut(&mut self) -> &mut [Node] { + &mut self.buffer + } + } + impl SortedLinkedListStorage for ViewSortedLinkedListStorage {} +} +pub use storage::{ + OwnedSortedLinkedListStorage, SortedLinkedListStorage, ViewSortedLinkedListStorage, +}; /// Trait for defining an index for the linked list, never implemented by users. pub trait SortedLinkedListIndex: Copy { @@ -93,20 +161,21 @@ pub struct Node { pub struct SortedLinkedListInner where Idx: SortedLinkedListIndex, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { head: Idx, free: Idx, - _kind: PhantomData, - list: S::Buffer>, + phantom: PhantomData<(K, T)>, + list: S, } /// The linked list. pub type SortedLinkedList = - SortedLinkedListInner>; + SortedLinkedListInner>; /// The linked list. -pub type SortedLinkedListView = SortedLinkedListInner; +pub type SortedLinkedListView = + SortedLinkedListInner>; // Internal macro for generating indexes for the linkedlist and const new for the linked list macro_rules! impl_index_and_const_new { @@ -168,10 +237,12 @@ macro_rules! impl_index_and_const_new { crate::sealed::smaller_than::(); let mut list = SortedLinkedList { - list: [Self::UNINIT; N], + list: OwnedSortedLinkedListStorage { + buffer: [Self::UNINIT; N], + }, head: $name::none(), free: unsafe { $name::new_unchecked(0) }, - _kind: PhantomData, + phantom: PhantomData, }; if N == 0 { @@ -183,7 +254,7 @@ macro_rules! impl_index_and_const_new { // Initialize indexes while free < N - 1 { - list.list[free].next = unsafe { $name::new_unchecked(free as $ty + 1) }; + list.list.buffer[free].next = unsafe { $name::new_unchecked(free as $ty + 1) }; free += 1; } @@ -215,7 +286,7 @@ where impl SortedLinkedListInner where Idx: SortedLinkedListIndex, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { /// Internal access helper #[inline(always)] @@ -267,7 +338,7 @@ where T: Ord, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { /// Pushes a value onto the list without checking if the list is full. /// @@ -554,23 +625,24 @@ where T: Ord, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { list: &'a SortedLinkedListInner, index: Idx, } /// Iterator for the linked list. -pub type Iter<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, OwnedStorage>; +pub type Iter<'a, T, Idx, K, const N: usize> = + IterInner<'a, T, Idx, K, OwnedSortedLinkedListStorage>; /// Iterator for the linked list. -pub type IterView<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, ViewStorage>; +pub type IterView<'a, T, Idx, K> = IterInner<'a, T, Idx, K, ViewSortedLinkedListStorage>; impl<'a, T, Idx, K, S> Iterator for IterInner<'a, T, Idx, K, S> where T: Ord, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { type Item = &'a T; @@ -593,7 +665,7 @@ where T: Ord, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { list: &'a mut SortedLinkedListInner, is_head: bool, @@ -603,16 +675,18 @@ where } /// Comes from [`SortedLinkedList::find_mut`]. -pub type FindMut<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, OwnedStorage>; +pub type FindMut<'a, T, Idx, K, const N: usize> = + FindMutInner<'a, T, Idx, K, OwnedSortedLinkedListStorage>; /// Comes from [`SortedLinkedList::find_mut`]. -pub type FindMutView<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, ViewStorage>; +pub type FindMutView<'a, T, Idx, K, const N: usize> = + FindMutInner<'a, T, Idx, K, ViewSortedLinkedListStorage>; impl<'a, T, Idx, K, S> FindMutInner<'a, T, Idx, K, S> where T: Ord, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { fn pop_internal(&mut self) -> T { if self.is_head { @@ -701,7 +775,7 @@ where T: Ord, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { fn drop(&mut self) { // Only resort the list if the element has changed @@ -717,7 +791,7 @@ where T: Ord, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { type Target = T; @@ -732,7 +806,7 @@ where T: Ord, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { fn deref_mut(&mut self) -> &mut Self::Target { self.maybe_changed = true; @@ -771,7 +845,7 @@ where T: Ord + core::fmt::Debug, Idx: SortedLinkedListIndex, K: Kind, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter()).finish() @@ -781,7 +855,7 @@ where impl Drop for SortedLinkedListInner where Idx: SortedLinkedListIndex, - S: Storage, + S: SortedLinkedListStorage + ?Sized, { fn drop(&mut self) { let mut index = self.head; @@ -927,4 +1001,15 @@ mod tests { assert_eq!(ll.peek().unwrap(), &1001); } + + fn _test_variance<'a: 'b, 'b>( + x: SortedLinkedList<&'a (), LinkedIndexUsize, Max, 42>, + ) -> SortedLinkedList<&'b (), LinkedIndexUsize, Max, 42> { + x + } + fn _test_variance_view<'a: 'b, 'b, 'c>( + x: &'c SortedLinkedListView<&'a (), LinkedIndexUsize, Max>, + ) -> &'c SortedLinkedListView<&'b (), LinkedIndexUsize, Max> { + x + } } diff --git a/src/string/mod.rs b/src/string/mod.rs index d88dbf0fd0..bf4fff058a 100644 --- a/src/string/mod.rs +++ b/src/string/mod.rs @@ -11,11 +11,7 @@ use core::{ str::{self, Utf8Error}, }; -use crate::{ - storage::{OwnedStorage, Storage, ViewStorage}, - vec::VecInner, - Vec, -}; +use crate::vec::{OwnedVecStorage, Vec, VecInner, VecStorage, ViewVecStorage}; mod drain; pub use drain::Drain; @@ -46,15 +42,15 @@ impl fmt::Display for FromUtf16Error { /// /// 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 { +pub struct StringInner + ?Sized> { vec: VecInner, } /// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html). -pub type String = StringInner>; +pub type String = StringInner>; /// A dynamic capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html). -pub type StringView = StringInner; +pub type StringView = StringInner>; impl StringView { /// Removes the specified range from the string in bulk, returning all @@ -349,7 +345,7 @@ impl String { } } -impl StringInner { +impl + ?Sized> StringInner { /// Extracts a string slice containing the entire string. /// /// # Examples @@ -690,26 +686,26 @@ impl Clone for String { } } -impl fmt::Debug for StringInner { +impl + ?Sized> fmt::Debug for StringInner { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ::fmt(self, f) } } -impl fmt::Display for StringInner { +impl + ?Sized> fmt::Display for StringInner { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ::fmt(self, f) } } -impl hash::Hash for StringInner { +impl + ?Sized> hash::Hash for StringInner { #[inline] fn hash(&self, hasher: &mut H) { ::hash(self, hasher) } } -impl fmt::Write for StringInner { +impl + ?Sized> fmt::Write for StringInner { fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { self.push_str(s).map_err(|_| fmt::Error) } @@ -719,7 +715,7 @@ impl fmt::Write for StringInner { } } -impl ops::Deref for StringInner { +impl + ?Sized> ops::Deref for StringInner { type Target = str; fn deref(&self) -> &str { @@ -727,45 +723,47 @@ impl ops::Deref for StringInner { } } -impl ops::DerefMut for StringInner { +impl + ?Sized> ops::DerefMut for StringInner { fn deref_mut(&mut self) -> &mut str { self.as_mut_str() } } -impl borrow::Borrow for StringInner { +impl + ?Sized> borrow::Borrow for StringInner { fn borrow(&self) -> &str { self.as_str() } } -impl borrow::BorrowMut for StringInner { +impl + ?Sized> borrow::BorrowMut for StringInner { fn borrow_mut(&mut self) -> &mut str { self.as_mut_str() } } -impl AsRef for StringInner { +impl + ?Sized> AsRef for StringInner { #[inline] fn as_ref(&self) -> &str { self } } -impl AsRef<[u8]> for StringInner { +impl + ?Sized> AsRef<[u8]> for StringInner { #[inline] fn as_ref(&self) -> &[u8] { self.as_bytes() } } -impl PartialEq> for StringInner { +impl + ?Sized, S2: VecStorage + ?Sized> PartialEq> + for StringInner +{ fn eq(&self, rhs: &StringInner) -> bool { str::eq(&**self, &**rhs) } } // String == str -impl PartialEq for StringInner { +impl + ?Sized> PartialEq for StringInner { #[inline] fn eq(&self, other: &str) -> bool { str::eq(self, other) @@ -773,7 +771,7 @@ impl PartialEq for StringInner { } // String == &'str -impl PartialEq<&str> for StringInner { +impl + ?Sized> PartialEq<&str> for StringInner { #[inline] fn eq(&self, other: &&str) -> bool { str::eq(self, &other[..]) @@ -781,7 +779,7 @@ impl PartialEq<&str> for StringInner { } // str == String -impl PartialEq> for str { +impl + ?Sized> PartialEq> for str { #[inline] fn eq(&self, other: &StringInner) -> bool { str::eq(self, &other[..]) @@ -789,23 +787,25 @@ impl PartialEq> for str { } // &'str == String -impl PartialEq> for &str { +impl + ?Sized> PartialEq> for &str { #[inline] fn eq(&self, other: &StringInner) -> bool { str::eq(self, &other[..]) } } -impl Eq for StringInner {} +impl + ?Sized> Eq for StringInner {} -impl PartialOrd> for StringInner { +impl + ?Sized, S2: VecStorage + ?Sized> PartialOrd> + for StringInner +{ #[inline] fn partial_cmp(&self, other: &StringInner) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } -impl Ord for StringInner { +impl + ?Sized> Ord for StringInner { #[inline] fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(&**self, &**other) diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 1e1583a43e..d85d114693 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -1,8 +1,8 @@ //! A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). use core::borrow; +use core::marker::PhantomData; use core::{ - borrow::{Borrow, BorrowMut}, cmp::Ordering, fmt, hash, mem::{self, ManuallyDrop, MaybeUninit}, @@ -11,18 +11,84 @@ use core::{ slice, }; -use crate::storage::{OwnedStorage, Storage, ViewStorage}; - mod drain; + +mod storage { + use core::mem::MaybeUninit; + + /// Trait defining how data for a container is stored. + /// + /// There's two implementations available: + /// + /// - [`OwnedVecStorage`]: stores the data in an array `[T; N]` whose size is known at compile time. + /// - [`ViewVecStorage`]: stores the data in an unsized `[T]`. + /// + /// This allows containers to be generic over either sized or unsized storage. For example, + /// the [`vec`](crate::vec) module contains a [`VecInner`](crate::vec::VecInner) struct + /// that's generic on [`Storage`], and two type aliases for convenience: + /// + /// - [`Vec`](crate::vec::Vec) = `VecInner>` + /// - [`VecView`](crate::vec::VecView) = `VecInner>` + /// + /// `Vec` can be unsized into `VecView`, either by unsizing coercions such as `&mut Vec -> &mut VecView` or + /// `Box -> Box`, or explicitly with [`.as_view()`](crate::vec::Vec::as_view) or [`.as_mut_view()`](crate::vec::Vec::as_mut_view). + /// + /// This trait is sealed, so you cannot implement it for your own types. You can only use + /// the implementations provided by this crate. + #[allow(private_bounds)] + pub trait VecStorage: VecSealedStorage {} + + pub trait VecSealedStorage { + // part of the sealed trait so that no trait is publicly implemented by `OwnedVecStorage` besides `Storage` + fn borrow(&self) -> &[MaybeUninit]; + fn borrow_mut(&mut self) -> &mut [MaybeUninit]; + } + + // One sealed layer of indirection to hide the internal details (The MaybeUninit). + pub struct VecStorageInner { + pub(crate) buffer: T, + } + + /// Implementation of [`VecStorage`] that stores the data in an array `[T; N]` whose size is known at compile time. + pub type OwnedVecStorage = VecStorageInner<[MaybeUninit; N]>; + /// Implementation of [`VecStorage`] that stores the data in an unsized `[T]`. + pub type ViewVecStorage = VecStorageInner<[MaybeUninit]>; + + impl VecSealedStorage for OwnedVecStorage { + fn borrow(&self) -> &[MaybeUninit] { + &self.buffer + } + fn borrow_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buffer + } + } + impl VecStorage for OwnedVecStorage {} + + impl VecSealedStorage for ViewVecStorage { + fn borrow(&self) -> &[MaybeUninit] { + &self.buffer + } + fn borrow_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buffer + } + } + impl VecStorage for ViewVecStorage {} +} +pub use storage::{OwnedVecStorage, VecStorage, ViewVecStorage}; + +pub(crate) use storage::VecStorageInner; + pub use drain::Drain; /// Base struct for [`Vec`] and [`VecView`], generic over the [`Storage`]. /// /// 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 { +pub struct VecInner + ?Sized> { + // This phantomdata is required because otherwise rustc thinks that `T` is not used + phantom: PhantomData, len: usize, - buffer: S::Buffer>, + buffer: S, } /// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). @@ -62,7 +128,7 @@ pub struct VecInner { /// let vec: Vec = Vec::from_slice(&[1, 2, 3, 4]).unwrap(); /// let view: &VecView<_> = &vec; /// ``` -pub type Vec = VecInner>; +pub type Vec = VecInner>; /// A [`Vec`] with dynamic capacity /// @@ -85,7 +151,7 @@ pub type Vec = VecInner>; /// mut_view.push(5); /// assert_eq!(vec, [1, 2, 3, 4, 5]); /// ``` -pub type VecView = VecInner; +pub type VecView = VecInner>; impl Vec { const ELEM: MaybeUninit = MaybeUninit::uninit(); @@ -106,8 +172,9 @@ impl Vec { /// ``` pub const fn new() -> Self { Self { + phantom: PhantomData, len: 0, - buffer: Self::INIT, + buffer: VecStorageInner { buffer: Self::INIT }, } } @@ -152,6 +219,7 @@ impl Vec { if N == M { Self { + phantom: PhantomData, len: N, // NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit; N] // have the same layout when N == M. @@ -160,7 +228,7 @@ impl Vec { } else { let mut v = Vec::::new(); - for (src_elem, dst_elem) in src.iter().zip(v.buffer.iter_mut()) { + for (src_elem, dst_elem) in src.iter().zip(v.buffer.buffer.iter_mut()) { // NOTE(unsafe) src element is not going to drop as src itself // is wrapped in a ManuallyDrop. dst_elem.write(unsafe { ptr::read(src_elem) }); @@ -296,7 +364,7 @@ impl Vec { /// /// This method is not available on a `VecView`, use [`storage_len`](VecInner::storage_capacity) instead pub const fn capacity(&self) -> usize { - self.buffer.len() + self.buffer.buffer.len() } } @@ -365,7 +433,7 @@ impl VecView { } } -impl VecInner { +impl + ?Sized> VecInner { /// Returns a raw pointer to the vector’s buffer. pub fn as_ptr(&self) -> *const T { self.buffer.borrow().as_ptr() as *const T @@ -993,14 +1061,14 @@ impl 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: Storage> { + struct BackshiftOnDrop<'a, T, S: VecStorage + ?Sized> { v: &'a mut VecInner, processed_len: usize, deleted_cnt: usize, original_len: usize, } - impl<'a, T, S: Storage> Drop for BackshiftOnDrop<'a, T, S> { + impl<'a, T, S: VecStorage + ?Sized> Drop for BackshiftOnDrop<'a, T, S> { fn drop(&mut self) { if self.deleted_cnt > 0 { // SAFETY: Trailing unchecked items must be valid since we never touch them. @@ -1028,7 +1096,7 @@ impl VecInner { original_len, }; - fn process_loop( + fn process_loop + ?Sized, const DELETED: bool>( original_len: usize, f: &mut F, g: &mut BackshiftOnDrop<'_, T, S>, @@ -1114,7 +1182,7 @@ impl Default for Vec { } } -impl fmt::Debug for VecInner +impl + ?Sized> fmt::Debug for VecInner where T: fmt::Debug, { @@ -1123,7 +1191,7 @@ where } } -impl 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(()), @@ -1138,7 +1206,7 @@ impl From<[T; M]> for Vec { } } -impl 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]`. @@ -1155,7 +1223,7 @@ impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec { } } -impl Extend for VecInner { +impl + ?Sized> Extend for VecInner { fn extend(&mut self, iter: I) where I: IntoIterator, @@ -1164,7 +1232,7 @@ impl Extend for VecInner { } } -impl<'a, T, S: Storage> Extend<&'a T> for VecInner +impl<'a, T, S: VecStorage + ?Sized> Extend<&'a T> for VecInner where T: 'a + Copy, { @@ -1176,7 +1244,7 @@ where } } -impl hash::Hash for VecInner +impl + ?Sized> hash::Hash for VecInner where T: core::hash::Hash, { @@ -1185,7 +1253,7 @@ where } } -impl<'a, T, S: Storage> IntoIterator for &'a VecInner { +impl<'a, T, S: VecStorage + ?Sized> IntoIterator for &'a VecInner { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; @@ -1194,7 +1262,7 @@ impl<'a, T, S: Storage> IntoIterator for &'a VecInner { } } -impl<'a, T, S: Storage> IntoIterator for &'a mut VecInner { +impl<'a, T, S: VecStorage + ?Sized> IntoIterator for &'a mut VecInner { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; @@ -1228,7 +1296,14 @@ impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { if self.next < self.vec.len() { - let item = unsafe { self.vec.buffer.get_unchecked_mut(self.next).as_ptr().read() }; + let item = unsafe { + self.vec + .buffer + .buffer + .get_unchecked_mut(self.next) + .as_ptr() + .read() + }; self.next += 1; Some(item) } else { @@ -1247,7 +1322,7 @@ where if self.next < self.vec.len() { let s = unsafe { slice::from_raw_parts( - (self.vec.buffer.as_ptr() as *const T).add(self.next), + (self.vec.buffer.buffer.as_ptr() as *const T).add(self.next), self.vec.len() - self.next, ) }; @@ -1278,7 +1353,8 @@ impl IntoIterator for Vec { } } -impl PartialEq> for VecInner +impl + ?Sized, SB: VecStorage + ?Sized> PartialEq> + for VecInner where A: PartialEq, { @@ -1287,7 +1363,7 @@ where } } -impl PartialEq> for [A; M] +impl + ?Sized> PartialEq> for [A; M] where A: PartialEq, { @@ -1296,7 +1372,7 @@ where } } -impl PartialEq> for &[A; M] +impl + ?Sized, const M: usize> PartialEq> for &[A; M] where A: PartialEq, { @@ -1305,7 +1381,7 @@ where } } -impl PartialEq> for [A] +impl + ?Sized> PartialEq> for [A] where A: PartialEq, { @@ -1314,7 +1390,7 @@ where } } -impl PartialEq> for &[A] +impl + ?Sized> PartialEq> for &[A] where A: PartialEq, { @@ -1323,7 +1399,7 @@ where } } -impl PartialEq> for &mut [A] +impl + ?Sized> PartialEq> for &mut [A] where A: PartialEq, { @@ -1332,7 +1408,7 @@ where } } -impl PartialEq<[B; N]> for VecInner +impl + ?Sized, const N: usize> PartialEq<[B; N]> for VecInner where A: PartialEq, { @@ -1342,7 +1418,7 @@ where } } -impl PartialEq<&[B; N]> for VecInner +impl + ?Sized, const N: usize> PartialEq<&[B; N]> for VecInner where A: PartialEq, { @@ -1352,7 +1428,7 @@ where } } -impl PartialEq<[B]> for VecInner +impl + ?Sized> PartialEq<[B]> for VecInner where A: PartialEq, { @@ -1362,7 +1438,7 @@ where } } -impl PartialEq<&[B]> for VecInner +impl + ?Sized> PartialEq<&[B]> for VecInner where A: PartialEq, { @@ -1372,7 +1448,7 @@ where } } -impl PartialEq<&mut [B]> for VecInner +impl + ?Sized> PartialEq<&mut [B]> for VecInner where A: PartialEq, { @@ -1383,9 +1459,10 @@ where } // Implements Eq if underlying data is Eq -impl Eq for VecInner where T: Eq {} +impl + ?Sized> Eq for VecInner where T: Eq {} -impl PartialOrd> for VecInner +impl + ?Sized, SB: VecStorage + ?Sized> PartialOrd> + for VecInner where T: PartialOrd, { @@ -1394,7 +1471,7 @@ where } } -impl Ord for VecInner +impl + ?Sized> Ord for VecInner where T: Ord, { @@ -1404,7 +1481,7 @@ where } } -impl ops::Deref for VecInner { +impl + ?Sized> ops::Deref for VecInner { type Target = [T]; fn deref(&self) -> &Self::Target { @@ -1412,45 +1489,45 @@ impl ops::Deref for VecInner { } } -impl ops::DerefMut for VecInner { +impl + ?Sized> ops::DerefMut for VecInner { fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() } } -impl borrow::Borrow<[T]> for VecInner { +impl + ?Sized> borrow::Borrow<[T]> for VecInner { fn borrow(&self) -> &[T] { self.as_slice() } } -impl borrow::BorrowMut<[T]> for VecInner { +impl + ?Sized> borrow::BorrowMut<[T]> for VecInner { fn borrow_mut(&mut self) -> &mut [T] { self.as_mut_slice() } } -impl AsRef> for VecInner { +impl + ?Sized> AsRef> for VecInner { #[inline] fn as_ref(&self) -> &Self { self } } -impl AsMut> for VecInner { +impl + ?Sized> AsMut> for VecInner { #[inline] fn as_mut(&mut self) -> &mut Self { self } } -impl AsRef<[T]> for VecInner { +impl + ?Sized> AsRef<[T]> for VecInner { #[inline] fn as_ref(&self) -> &[T] { self } } -impl AsMut<[T]> for VecInner { +impl + ?Sized> AsMut<[T]> for VecInner { #[inline] fn as_mut(&mut self) -> &mut [T] { self @@ -1959,4 +2036,11 @@ mod tests { assert!(v.spare_capacity_mut().is_empty()); } + + fn _test_variance<'a: 'b, 'b>(x: Vec<&'a (), 42>) -> Vec<&'b (), 42> { + x + } + fn _test_variance_view<'a: 'b, 'b, 'c>(x: &'c VecView<&'a ()>) -> &'c VecView<&'b ()> { + x + } }