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

Fix constant assertions #403

Closed
wants to merge 1 commit into from
Closed
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- Fixed a `dropping_references` warning in `LinearMap`.
- Fixed IndexMap entry API returning wrong slot after an insert on vacant entry. (#360)
- Fixed constant asserts not asserting at compile time.

### Removed

Expand Down
12 changes: 9 additions & 3 deletions src/deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ pub struct Deque<T, const N: usize> {
impl<T, const N: usize> Deque<T, N> {
const INIT: MaybeUninit<T> = MaybeUninit::uninit();

#[cfg_attr(miri, doc = "```ignore")]
#[cfg_attr(not(miri), doc = "```compile_fail")]
/// use heapless::Deque;
/// let _: Deque<u8, 0> = Deque::new();
/// ```
const _ASSERT: () = assert!(N > 0);

/// Constructs a new, empty deque with a fixed capacity of `N`
///
/// # Examples
Expand All @@ -67,10 +74,9 @@ impl<T, const N: usize> Deque<T, N> {
/// // allocate the deque in a static variable
/// static mut X: Deque<u8, 16> = Deque::new();
/// ```
#[allow(path_statements)]
pub const fn new() -> Self {
// Const assert N > 0
crate::sealed::greater_than_0::<N>();

Self::_ASSERT;
Self {
buffer: [Self::INIT; N],
front: 0,
Expand Down
10 changes: 7 additions & 3 deletions src/histbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ pub struct HistoryBuffer<T, const N: usize> {

impl<T, const N: usize> HistoryBuffer<T, N> {
const INIT: MaybeUninit<T> = MaybeUninit::uninit();
/// ```compile_failure
/// use heapless::HistoryBuffer;
/// let _: HistoryBuffer<u8, 0> = HistoryBuffer::new();
/// ```
const _ASSERT: () = assert!(N > 0);

/// Constructs a new history buffer.
///
Expand All @@ -57,10 +62,9 @@ impl<T, const N: usize> HistoryBuffer<T, N> {
/// assert_eq!(x.len(), 0);
/// ```
#[inline]
#[allow(path_statements)]
pub const fn new() -> Self {
// Const assert
crate::sealed::greater_than_0::<N>();

Self::_ASSERT;
Self {
data: [Self::INIT; N],
write_at: 0,
Expand Down
39 changes: 31 additions & 8 deletions src/indexmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,11 +532,10 @@ pub struct IndexMap<K, V, S, const N: usize> {

impl<K, V, S, const N: usize> IndexMap<K, V, BuildHasherDefault<S>, N> {
/// Creates an empty `IndexMap`.
#[allow(path_statements)]
pub const fn new() -> Self {
// Const assert
crate::sealed::greater_than_1::<N>();
crate::sealed::power_of_two::<N>();

Self::_ASSERT1;
Self::_ASSERT2;
IndexMap {
build_hasher: BuildHasherDefault::new(),
core: CoreMap::new(),
Expand All @@ -545,6 +544,31 @@ impl<K, V, S, const N: usize> IndexMap<K, V, BuildHasherDefault<S>, N> {
}

impl<K, V, S, const N: usize> IndexMap<K, V, S, N> {
#[cfg_attr(miri, doc = "```ignore")]
#[cfg_attr(not(miri), doc = "```compile_fail")]
/// use heapless::FnvIndexMap;
/// let _: FnvIndexMap<u8, u8, 0> = FnvIndexMap::new();
/// ```
///
#[cfg_attr(miri, doc = "```ignore")]
#[cfg_attr(not(miri), doc = "```compile_fail")]
/// use heapless::FnvIndexMap;
/// let _: FnvIndexMap<u8, u8, 0> = FnvIndexMap::default();
/// ```
const _ASSERT1: () = assert!(N > 1);
#[cfg_attr(miri, doc = "```ignore")]
#[cfg_attr(not(miri), doc = "```compile_fail")]
/// use heapless::FnvIndexMap;
/// let _: FnvIndexMap<u8, u8, 3> = FnvIndexMap::new();
/// ```
///
#[cfg_attr(miri, doc = "```ignore")]
#[cfg_attr(not(miri), doc = "```compile_fail")]
/// use heapless::FnvIndexMap;
/// let _: FnvIndexMap<u8, u8, 3> = FnvIndexMap::default();
/// ```
const _ASSERT2: () = assert!(N.is_power_of_two());

/// Returns the number of elements the map can hold
pub fn capacity(&self) -> usize {
N
Expand Down Expand Up @@ -1020,11 +1044,10 @@ impl<K, V, S, const N: usize> Default for IndexMap<K, V, S, N>
where
S: Default,
{
#[allow(path_statements)]
fn default() -> Self {
// Const assert
crate::sealed::greater_than_1::<N>();
crate::sealed::power_of_two::<N>();

Self::_ASSERT1;
Self::_ASSERT2;
IndexMap {
build_hasher: <_>::default(),
core: CoreMap::new(),
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,3 @@ pub mod spsc;

#[cfg(feature = "ufmt")]
mod ufmt;

mod sealed;
20 changes: 16 additions & 4 deletions src/mpmc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,26 @@ impl<T, const N: usize> MpMcQueue<T, N> {

const ASSERT: [(); 1] = [()];

#[cfg_attr(miri, doc = "```ignore")]
#[cfg_attr(not(miri), doc = "```compile_fail")]
/// use heapless::mpmc::MpMcQueue;
/// let _: MpMcQueue<i32, 1> = MpMcQueue::new();
/// ```
const _ASSERT1: () = assert!(N > 1);
#[cfg_attr(miri, doc = "```ignore")]
#[cfg_attr(not(miri), doc = "```compile_fail")]
/// use heapless::mpmc::MpMcQueue;
/// let _: MpMcQueue<i32, 3> = MpMcQueue::new();
/// ```
const _ASSERT2: () = assert!(N.is_power_of_two());

/// Creates an empty queue
#[allow(path_statements)]
pub const fn new() -> Self {
// Const assert
crate::sealed::greater_than_1::<N>();
crate::sealed::power_of_two::<N>();

// Const assert on size.
Self::ASSERT[!(N < (IntSize::MAX as usize)) as usize];
Self::_ASSERT1;
Self::_ASSERT2;

let mut cell_count = 0;

Expand Down
58 changes: 0 additions & 58 deletions src/sealed.rs

This file was deleted.

7 changes: 4 additions & 3 deletions src/sorted_linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,12 @@ macro_rules! impl_index_and_const_new {
next: $name::none(),
};

const _ASSERT: () = assert!(N < $max_val);

/// Create a new linked list.
#[allow(path_statements)]
pub const fn $new_name() -> Self {
// Const assert N < MAX
crate::sealed::smaller_than::<N, $max_val>();

Self::_ASSERT;
let mut list = SortedLinkedList {
list: [Self::UNINIT; N],
head: $name::none(),
Expand Down
11 changes: 9 additions & 2 deletions src/spsc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,17 @@ impl<T, const N: usize> Queue<T, N> {
(val + 1) % N
}

#[cfg_attr(miri, doc = "```ignore")]
#[cfg_attr(not(miri), doc = "```compile_fail")]
/// use heapless::spsc::Queue;
/// let q: Queue<i32, 0> = Queue::new();
/// ```
const _ASSERT: () = assert!(N > 1);

/// Creates an empty queue with a fixed capacity of `N - 1`
#[allow(path_statements)]
pub const fn new() -> Self {
// Const assert N > 1
crate::sealed::greater_than_1::<N>();
Self::_ASSERT;

Queue {
head: AtomicUsize::new(0),
Expand Down
3 changes: 0 additions & 3 deletions src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ impl<T, const N: usize> Vec<T, N> {
/// ```
/// `Vec` `const` constructor; wrap the returned value in [`Vec`](../struct.Vec.html)
pub const fn new() -> Self {
// Const assert N >= 0
crate::sealed::greater_than_eq_0::<N>();

Self {
len: 0,
buffer: Self::INIT,
Expand Down