diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ad88f8ba2..71e6e99754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/deque.rs b/src/deque.rs index 1d3987080d..7666bca6ee 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -54,6 +54,13 @@ pub struct Deque { impl Deque { const INIT: MaybeUninit = MaybeUninit::uninit(); + #[cfg_attr(miri, doc = "```ignore")] + #[cfg_attr(not(miri), doc = "```compile_fail")] + /// use heapless::Deque; + /// let _: Deque = Deque::new(); + /// ``` + const _ASSERT: () = assert!(N > 0); + /// Constructs a new, empty deque with a fixed capacity of `N` /// /// # Examples @@ -67,10 +74,9 @@ impl Deque { /// // allocate the deque in a static variable /// static mut X: Deque = Deque::new(); /// ``` + #[allow(path_statements)] pub const fn new() -> Self { - // Const assert N > 0 - crate::sealed::greater_than_0::(); - + Self::_ASSERT; Self { buffer: [Self::INIT; N], front: 0, diff --git a/src/histbuf.rs b/src/histbuf.rs index 4ccd83b774..ce3b5d4b34 100644 --- a/src/histbuf.rs +++ b/src/histbuf.rs @@ -42,6 +42,11 @@ pub struct HistoryBuffer { impl HistoryBuffer { const INIT: MaybeUninit = MaybeUninit::uninit(); + /// ```compile_failure + /// use heapless::HistoryBuffer; + /// let _: HistoryBuffer = HistoryBuffer::new(); + /// ``` + const _ASSERT: () = assert!(N > 0); /// Constructs a new history buffer. /// @@ -57,10 +62,9 @@ impl HistoryBuffer { /// assert_eq!(x.len(), 0); /// ``` #[inline] + #[allow(path_statements)] pub const fn new() -> Self { - // Const assert - crate::sealed::greater_than_0::(); - + Self::_ASSERT; Self { data: [Self::INIT; N], write_at: 0, diff --git a/src/indexmap.rs b/src/indexmap.rs index 8e14ce9c42..5796f42377 100644 --- a/src/indexmap.rs +++ b/src/indexmap.rs @@ -532,11 +532,10 @@ pub struct IndexMap { impl IndexMap, N> { /// Creates an empty `IndexMap`. + #[allow(path_statements)] pub const fn new() -> Self { - // Const assert - crate::sealed::greater_than_1::(); - crate::sealed::power_of_two::(); - + Self::_ASSERT1; + Self::_ASSERT2; IndexMap { build_hasher: BuildHasherDefault::new(), core: CoreMap::new(), @@ -545,6 +544,31 @@ impl IndexMap, N> { } impl IndexMap { + #[cfg_attr(miri, doc = "```ignore")] + #[cfg_attr(not(miri), doc = "```compile_fail")] + /// use heapless::FnvIndexMap; + /// let _: FnvIndexMap = FnvIndexMap::new(); + /// ``` + /// + #[cfg_attr(miri, doc = "```ignore")] + #[cfg_attr(not(miri), doc = "```compile_fail")] + /// use heapless::FnvIndexMap; + /// let _: FnvIndexMap = FnvIndexMap::default(); + /// ``` + const _ASSERT1: () = assert!(N > 1); + #[cfg_attr(miri, doc = "```ignore")] + #[cfg_attr(not(miri), doc = "```compile_fail")] + /// use heapless::FnvIndexMap; + /// let _: FnvIndexMap = FnvIndexMap::new(); + /// ``` + /// + #[cfg_attr(miri, doc = "```ignore")] + #[cfg_attr(not(miri), doc = "```compile_fail")] + /// use heapless::FnvIndexMap; + /// let _: FnvIndexMap = 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 @@ -1020,11 +1044,10 @@ impl Default for IndexMap where S: Default, { + #[allow(path_statements)] fn default() -> Self { - // Const assert - crate::sealed::greater_than_1::(); - crate::sealed::power_of_two::(); - + Self::_ASSERT1; + Self::_ASSERT2; IndexMap { build_hasher: <_>::default(), core: CoreMap::new(), diff --git a/src/lib.rs b/src/lib.rs index 130120908d..52517c39c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,5 +134,3 @@ pub mod spsc; #[cfg(feature = "ufmt")] mod ufmt; - -mod sealed; diff --git a/src/mpmc.rs b/src/mpmc.rs index db38934b66..e1222b7ddf 100644 --- a/src/mpmc.rs +++ b/src/mpmc.rs @@ -138,14 +138,26 @@ impl MpMcQueue { const ASSERT: [(); 1] = [()]; + #[cfg_attr(miri, doc = "```ignore")] + #[cfg_attr(not(miri), doc = "```compile_fail")] + /// use heapless::mpmc::MpMcQueue; + /// let _: MpMcQueue = 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 = 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::(); - crate::sealed::power_of_two::(); - // Const assert on size. Self::ASSERT[!(N < (IntSize::MAX as usize)) as usize]; + Self::_ASSERT1; + Self::_ASSERT2; let mut cell_count = 0; diff --git a/src/sealed.rs b/src/sealed.rs deleted file mode 100644 index cb5ad840ad..0000000000 --- a/src/sealed.rs +++ /dev/null @@ -1,58 +0,0 @@ -#[allow(dead_code)] -#[allow(path_statements)] -pub(crate) const fn smaller_than() { - Assert::::LESS; -} - -#[allow(dead_code)] -#[allow(path_statements)] -pub(crate) const fn greater_than_eq_0() { - Assert::::GREATER_EQ; -} - -#[allow(dead_code)] -#[allow(path_statements)] -pub(crate) const fn greater_than_0() { - Assert::::GREATER; -} - -#[allow(dead_code)] -#[allow(path_statements)] -pub(crate) const fn greater_than_1() { - Assert::::GREATER; -} - -#[allow(dead_code)] -#[allow(path_statements)] -pub(crate) const fn power_of_two() { - Assert::::GREATER; - Assert::::POWER_OF_TWO; -} - -#[allow(dead_code)] -/// Const assert hack -pub struct Assert; - -#[allow(dead_code)] -impl Assert { - /// Const assert hack - pub const GREATER_EQ: usize = L - R; - - /// Const assert hack - pub const LESS_EQ: usize = R - L; - - /// Const assert hack - pub const NOT_EQ: isize = 0 / (R as isize - L as isize); - - /// Const assert hack - pub const EQ: usize = (R - L) + (L - R); - - /// Const assert hack - pub const GREATER: usize = L - R - 1; - - /// Const assert hack - pub const LESS: usize = R - L - 1; - - /// Const assert hack - pub const POWER_OF_TWO: usize = 0 - (L & (L - 1)); -} diff --git a/src/sorted_linked_list.rs b/src/sorted_linked_list.rs index 041895cd3e..135a25b844 100644 --- a/src/sorted_linked_list.rs +++ b/src/sorted_linked_list.rs @@ -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::(); - + Self::_ASSERT; let mut list = SortedLinkedList { list: [Self::UNINIT; N], head: $name::none(), diff --git a/src/spsc.rs b/src/spsc.rs index c8085720e7..abe00f09e2 100644 --- a/src/spsc.rs +++ b/src/spsc.rs @@ -125,10 +125,17 @@ impl Queue { (val + 1) % N } + #[cfg_attr(miri, doc = "```ignore")] + #[cfg_attr(not(miri), doc = "```compile_fail")] + /// use heapless::spsc::Queue; + /// let q: Queue = 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::(); + Self::_ASSERT; Queue { head: AtomicUsize::new(0), diff --git a/src/vec.rs b/src/vec.rs index 0dc25f1dd1..1bbd924ce5 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -58,9 +58,6 @@ impl Vec { /// ``` /// `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::(); - Self { len: 0, buffer: Self::INIT,