Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-introduce covariance for containers #502

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 25 additions & 19 deletions src/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down Expand Up @@ -54,11 +51,11 @@ mod private {
impl private::Sealed for Max {}
impl private::Sealed for Min {}

/// Base struct for [`BinaryHeap`] and [`BinaryHeapView`], generic over the [`Storage`].
/// Base struct for [`BinaryHeap`] and [`BinaryHeapView`], generic over the [`VecStorage`].
///
/// 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<T, K, S: Storage> {
pub struct BinaryHeapInner<T, K, S: VecStorage<T> + ?Sized> {
pub(crate) _kind: PhantomData<K>,
pub(crate) data: VecInner<T, S>,
}
Expand Down Expand Up @@ -109,7 +106,7 @@ pub struct BinaryHeapInner<T, K, S: Storage> {
/// // The heap should now be empty.
/// assert!(heap.is_empty())
/// ```
pub type BinaryHeap<T, K, const N: usize> = BinaryHeapInner<T, K, OwnedStorage<N>>;
pub type BinaryHeap<T, K, const N: usize> = BinaryHeapInner<T, K, OwnedVecStorage<T, N>>;

/// A priority queue implemented with a binary heap.
///
Expand Down Expand Up @@ -158,7 +155,7 @@ pub type BinaryHeap<T, K, const N: usize> = BinaryHeapInner<T, K, OwnedStorage<N
/// // The heap should now be empty.
/// assert!(heap.is_empty())
/// ```
pub type BinaryHeapView<T, K> = BinaryHeapInner<T, K, ViewStorage>;
pub type BinaryHeapView<T, K> = BinaryHeapInner<T, K, ViewVecStorage<T>>;

impl<T, K, const N: usize> BinaryHeap<T, K, N> {
/* Constructors */
Expand Down Expand Up @@ -198,7 +195,7 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> {
}
}

impl<T, K, S: Storage> BinaryHeapInner<T, K, S>
impl<T, K, S: VecStorage<T> + ?Sized> BinaryHeapInner<T, K, S>
where
T: Ord,
K: Kind,
Expand Down Expand Up @@ -519,7 +516,7 @@ pub struct PeekMutInner<'a, T, K, S>
where
T: Ord,
K: Kind,
S: Storage,
S: VecStorage<T> + ?Sized,
{
heap: &'a mut BinaryHeapInner<T, K, S>,
sift: bool,
Expand All @@ -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<N>>;
pub type PeekMut<'a, T, K, const N: usize> = PeekMutInner<'a, T, K, OwnedVecStorage<T, N>>;

/// 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<T>>;

impl<T, K, S> Drop for PeekMutInner<'_, T, K, S>
where
T: Ord,
K: Kind,
S: Storage,
S: VecStorage<T> + ?Sized,
{
fn drop(&mut self) {
if self.sift {
Expand All @@ -556,7 +553,7 @@ impl<T, K, S> Deref for PeekMutInner<'_, T, K, S>
where
T: Ord,
K: Kind,
S: Storage,
S: VecStorage<T> + ?Sized,
{
type Target = T;
fn deref(&self) -> &T {
Expand All @@ -570,7 +567,7 @@ impl<T, K, S> DerefMut for PeekMutInner<'_, T, K, S>
where
T: Ord,
K: Kind,
S: Storage,
S: VecStorage<T> + ?Sized,
{
fn deref_mut(&mut self) -> &mut T {
debug_assert!(!self.heap.is_empty());
Expand All @@ -583,7 +580,7 @@ impl<'a, T, K, S> PeekMutInner<'a, T, K, S>
where
T: Ord,
K: Kind,
S: Storage,
S: VecStorage<T> + ?Sized,
{
/// Removes the peeked value from the heap and returns it.
pub fn pop(mut this: PeekMutInner<'a, T, K, S>) -> T {
Expand Down Expand Up @@ -631,7 +628,7 @@ impl<T, K, S> fmt::Debug for BinaryHeapInner<T, K, S>
where
K: Kind,
T: Ord + fmt::Debug,
S: Storage,
S: VecStorage<T> + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
Expand All @@ -642,7 +639,7 @@ impl<'a, T, K, S> IntoIterator for &'a BinaryHeapInner<T, K, S>
where
K: Kind,
T: Ord,
S: Storage,
S: VecStorage<T> + ?Sized,
{
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
Expand All @@ -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);
Expand Down Expand Up @@ -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
}
}
9 changes: 6 additions & 3 deletions src/defmt.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
//! Defmt implementations for heapless types

use crate::{storage::Storage, string::StringInner, vec::VecInner};
use crate::{
string::StringInner,
vec::{VecInner, VecStorage},
};
use defmt::Formatter;

impl<T, S: Storage> defmt::Format for VecInner<T, S>
impl<T, S: VecStorage<T> + ?Sized> defmt::Format for VecInner<T, S>
where
T: defmt::Format,
{
Expand All @@ -12,7 +15,7 @@ where
}
}

impl<S: Storage> defmt::Format for StringInner<S>
impl<S: VecStorage<u8> + ?Sized> defmt::Format for StringInner<S>
where
u8: defmt::Format,
{
Expand Down
35 changes: 20 additions & 15 deletions src/deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 [`DequeView`], generic over the [`Storage`].
/// Base struct for [`Deque`] and [`DequeView`], generic over the [`VecStorage`].
///
/// In most cases you should use [`Deque`] or [`DequeView`] directly. Only use this
/// struct if you want to write code that's generic over both.
pub struct DequeInner<T, S: Storage> {
pub struct DequeInner<T, S: VecStorage<T> + ?Sized> {
// This phantomdata is required because otherwise rustc thinks that `T` is not used
phantom: PhantomData<T>,
/// Front index. Always 0..=(N-1)
front: usize,
/// Back index. Always 0..=(N-1).
Expand All @@ -54,7 +56,7 @@ pub struct DequeInner<T, S: Storage> {
/// 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<MaybeUninit<T>>,
buffer: S,
}

/// A fixed capacity double-ended queue.
Expand Down Expand Up @@ -91,7 +93,7 @@ pub struct DequeInner<T, S: Storage> {
/// println!("{}", x);
/// }
/// ```
pub type Deque<T, const N: usize> = DequeInner<T, OwnedStorage<N>>;
pub type Deque<T, const N: usize> = DequeInner<T, OwnedVecStorage<T, N>>;

/// A double-ended queue with dynamic capacity.
///
Expand Down Expand Up @@ -130,7 +132,7 @@ pub type Deque<T, const N: usize> = DequeInner<T, OwnedStorage<N>>;
/// println!("{}", x);
/// }
/// ```
pub type DequeView<T> = DequeInner<T, ViewStorage>;
pub type DequeView<T> = DequeInner<T, ViewVecStorage<T>>;

impl<T, const N: usize> Deque<T, N> {
const INIT: MaybeUninit<T> = MaybeUninit::uninit();
Expand All @@ -153,7 +155,10 @@ impl<T, const N: usize> Deque<T, N> {
crate::sealed::greater_than_0::<N>();

Self {
buffer: [Self::INIT; N],
phantom: PhantomData,
buffer: VecStorageInner {
buffer: [Self::INIT; N],
},
front: 0,
back: 0,
full: false,
Expand Down Expand Up @@ -191,7 +196,7 @@ impl<T, const N: usize> Deque<T, N> {
}
}

impl<T, S: Storage> DequeInner<T, S> {
impl<T, S: VecStorage<T> + ?Sized> DequeInner<T, S> {
/// Returns the maximum number of elements the deque can hold.
pub fn storage_capacity(&self) -> usize {
self.buffer.borrow().len()
Expand Down Expand Up @@ -794,29 +799,29 @@ impl<T, const N: usize> Default for Deque<T, N> {
}
}

impl<T, S: Storage> Drop for DequeInner<T, S> {
impl<T, S: VecStorage<T> + ?Sized> Drop for DequeInner<T, S> {
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.
unsafe { self.drop_contents() }
}
}

impl<T: fmt::Debug, S: Storage> fmt::Debug for DequeInner<T, S> {
impl<T: fmt::Debug, S: VecStorage<T> + ?Sized> fmt::Debug for DequeInner<T, S> {
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<T, S: Storage> Extend<T> for DequeInner<T, S> {
impl<T, S: VecStorage<T> + ?Sized> Extend<T> for DequeInner<T, S> {
fn extend<I: IntoIterator<Item = T>>(&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<T, S> {
impl<'a, T: 'a + Copy, S: VecStorage<T> + ?Sized> Extend<&'a T> for DequeInner<T, S> {
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
self.extend(iter.into_iter().copied())
}
Expand Down Expand Up @@ -846,7 +851,7 @@ impl<T, const N: usize> IntoIterator for Deque<T, N> {
}
}

impl<'a, T, S: Storage> IntoIterator for &'a DequeInner<T, S> {
impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a DequeInner<T, S> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;

Expand All @@ -855,7 +860,7 @@ impl<'a, T, S: Storage> IntoIterator for &'a DequeInner<T, S> {
}
}

impl<'a, T, S: Storage> IntoIterator for &'a mut DequeInner<T, S> {
impl<'a, T, S: VecStorage<T> + ?Sized> IntoIterator for &'a mut DequeInner<T, S> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;

Expand Down
Loading
Loading