From 593b92ae39d95cec1900d8481287627907b60be4 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Tue, 31 Oct 2023 17:33:26 -0700 Subject: [PATCH] Fix constant assertions --- CHANGELOG.md | 1 + src/deque.rs | 10 +++++-- src/histbuf.rs | 10 +++++-- src/indexmap.rs | 35 +++++++++++++++++------ src/lib.rs | 2 -- src/mpmc.rs | 18 +++++++++--- src/sealed.rs | 58 --------------------------------------- src/sorted_linked_list.rs | 7 +++-- src/spsc.rs | 10 +++++-- src/vec.rs | 3 -- 10 files changed, 68 insertions(+), 86 deletions(-) delete mode 100644 src/sealed.rs 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..740cef533a 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -53,6 +53,11 @@ pub struct Deque { impl Deque { const INIT: MaybeUninit = MaybeUninit::uninit(); + /// ```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` /// @@ -67,10 +72,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..47200ca602 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,27 @@ impl IndexMap, N> { } impl IndexMap { + /// ```compile_fail + /// use heapless::FnvIndexMap; + /// let _: FnvIndexMap = FnvIndexMap::new(); + /// ``` + /// + /// ```compile_fail + /// use heapless::FnvIndexMap; + /// let _: FnvIndexMap = FnvIndexMap::default(); + /// ``` + const _ASSERT1: () = assert!(N > 1); + /// ```compile_fail + /// use heapless::FnvIndexMap; + /// let _: FnvIndexMap = FnvIndexMap::new(); + /// ``` + /// + /// ```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 +1040,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..4c1cde0120 100644 --- a/src/mpmc.rs +++ b/src/mpmc.rs @@ -138,14 +138,24 @@ impl MpMcQueue { const ASSERT: [(); 1] = [()]; + /// ```compile_fail + /// use heapless::mpmc::MpMcQueue; + /// let q: MpMcQueue = MpMcQueue::new(); + /// ``` + const _ASSERT1: () = assert!(N > 1); + /// ```compile_fail + /// use heapless::mpmc::MpMcQueue; + /// let q: 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..4b180d16c7 100644 --- a/src/spsc.rs +++ b/src/spsc.rs @@ -125,10 +125,16 @@ impl Queue { (val + 1) % N } + /// ```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,