From 6dbefb4a5ce33e2f7a47dc4f36acab71f87f9f79 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 19 Feb 2024 09:43:04 +0100 Subject: [PATCH 1/2] Fix CI. --- cfail/ui/not-send.stderr | 38 +++++++++++++++++++++++++++++++++++++- src/binary_heap.rs | 8 ++++++-- src/indexmap.rs | 1 - src/indexset.rs | 1 - src/linear_map.rs | 2 +- src/string.rs | 1 - src/vec.rs | 1 - 7 files changed, 44 insertions(+), 8 deletions(-) diff --git a/cfail/ui/not-send.stderr b/cfail/ui/not-send.stderr index 058e28e8f5..c4985b8b50 100644 --- a/cfail/ui/not-send.stderr +++ b/cfail/ui/not-send.stderr @@ -7,6 +7,9 @@ error[E0277]: `*const ()` cannot be sent between threads safely = help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()` note: required because it appears within the type `PhantomData<*const ()>` --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ = note: required for `Consumer<'_, PhantomData<*const ()>, 4>` to implement `Send` note: required by a bound in `is_send` --> ui/not-send.rs:14:8 @@ -26,6 +29,9 @@ error[E0277]: `*const ()` cannot be sent between threads safely = help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()` note: required because it appears within the type `PhantomData<*const ()>` --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ = note: required for `Producer<'_, PhantomData<*const ()>, 4>` to implement `Send` note: required by a bound in `is_send` --> ui/not-send.rs:14:8 @@ -45,12 +51,24 @@ error[E0277]: `*const ()` cannot be sent between threads safely = help: within `Queue, 4>`, the trait `Send` is not implemented for `*const ()` note: required because it appears within the type `PhantomData<*const ()>` --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `ManuallyDrop>` --> $RUST/core/src/mem/manually_drop.rs + | + | pub struct ManuallyDrop { + | ^^^^^^^^^^^^ note: required because it appears within the type `MaybeUninit>` --> $RUST/core/src/mem/maybe_uninit.rs + | + | pub union MaybeUninit { + | ^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>>` --> $RUST/core/src/cell.rs + | + | pub struct UnsafeCell { + | ^^^^^^^^^^ = note: required because it appears within the type `[UnsafeCell>>; 4]` note: required because it appears within the type `Queue, 4>` --> $HEAPLESS/src/spsc.rs @@ -75,12 +93,21 @@ error[E0277]: `*const ()` cannot be sent between threads safely = help: within `heapless::vec::VecInner<[MaybeUninit>; 4]>`, the trait `Send` is not implemented for `*const ()` note: required because it appears within the type `PhantomData<*const ()>` --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `ManuallyDrop>` --> $RUST/core/src/mem/manually_drop.rs + | + | pub struct ManuallyDrop { + | ^^^^^^^^^^^^ note: required because it appears within the type `MaybeUninit>` --> $RUST/core/src/mem/maybe_uninit.rs + | + | pub union MaybeUninit { + | ^^^^^^^^^^^ = note: required because it appears within the type `[MaybeUninit>; 4]` -note: required because it appears within the type `VecInner<[MaybeUninit>; 4]>` +note: required because it appears within the type `heapless::vec::VecInner<[MaybeUninit>; 4]>` --> $HEAPLESS/src/vec.rs | | pub struct VecInner { @@ -103,10 +130,19 @@ error[E0277]: `*const ()` cannot be sent between threads safely = help: within `HistoryBuffer, 4>`, the trait `Send` is not implemented for `*const ()` note: required because it appears within the type `PhantomData<*const ()>` --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `ManuallyDrop>` --> $RUST/core/src/mem/manually_drop.rs + | + | pub struct ManuallyDrop { + | ^^^^^^^^^^^^ note: required because it appears within the type `MaybeUninit>` --> $RUST/core/src/mem/maybe_uninit.rs + | + | pub union MaybeUninit { + | ^^^^^^^^^^^ = note: required because it appears within the type `[MaybeUninit>; 4]` note: required because it appears within the type `HistoryBuffer, 4>` --> $HEAPLESS/src/histbuf.rs diff --git a/src/binary_heap.rs b/src/binary_heap.rs index d114f41863..8bd740845e 100644 --- a/src/binary_heap.rs +++ b/src/binary_heap.rs @@ -564,9 +564,13 @@ where #[cfg(test)] mod tests { - use std::vec::Vec; + use static_assertions::assert_not_impl_any; - use crate::binary_heap::{BinaryHeap, Max, Min}; + use super::{BinaryHeap, Max, Min}; + + // Ensure a `BinaryHeap` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(BinaryHeap<*const (), Max, 4>: Send); + assert_not_impl_any!(BinaryHeap<*const (), Min, 4>: Send); #[test] fn static_new() { diff --git a/src/indexmap.rs b/src/indexmap.rs index a6f736cbd2..bd07a56e9d 100644 --- a/src/indexmap.rs +++ b/src/indexmap.rs @@ -2,7 +2,6 @@ use core::{ borrow::Borrow, fmt, hash::{BuildHasher, Hash}, - iter::FromIterator, mem, num::NonZeroU32, ops, slice, diff --git a/src/indexset.rs b/src/indexset.rs index 404f7e1109..04607e682c 100644 --- a/src/indexset.rs +++ b/src/indexset.rs @@ -3,7 +3,6 @@ use core::{ borrow::Borrow, fmt, hash::{BuildHasher, Hash}, - iter::FromIterator, }; use hash32::{BuildHasherDefault, FnvHasher}; diff --git a/src/linear_map.rs b/src/linear_map.rs index 445bce2c0b..efdfe4f417 100644 --- a/src/linear_map.rs +++ b/src/linear_map.rs @@ -1,5 +1,5 @@ use crate::Vec; -use core::{borrow::Borrow, fmt, iter::FromIterator, mem, ops, slice}; +use core::{borrow::Borrow, fmt, mem, ops, slice}; /// A fixed capacity map/dictionary that performs lookups via linear search. /// diff --git a/src/string.rs b/src/string.rs index ed378a17b7..dce6394d2d 100644 --- a/src/string.rs +++ b/src/string.rs @@ -733,7 +733,6 @@ impl_try_from_num!(u64, 20); #[cfg(test)] mod tests { use crate::{String, Vec}; - use core::convert::TryFrom; #[test] fn static_new() { diff --git a/src/vec.rs b/src/vec.rs index be7aaf30a9..0588f4d182 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -1,7 +1,6 @@ use core::{ cmp::Ordering, fmt, hash, - iter::FromIterator, mem, mem::{ManuallyDrop, MaybeUninit}, ops, ptr, slice, From 7bb2f71b5510494ba061f1bd6805a425769522fd Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 19 Feb 2024 10:09:37 +0100 Subject: [PATCH 2/2] Use `static_assertions` instead of `trybuild`. --- Cargo.toml | 1 + cfail/ui/not-send.rs | 24 ------ cfail/ui/not-send.stderr | 159 -------------------------------------- src/deque.rs | 7 +- src/histbuf.rs | 8 +- src/indexmap.rs | 11 ++- src/indexset.rs | 14 +++- src/linear_map.rs | 12 ++- src/mpmc.rs | 7 +- src/sorted_linked_list.rs | 5 ++ src/spsc.rs | 13 +++- src/vec.rs | 11 ++- 12 files changed, 77 insertions(+), 195 deletions(-) delete mode 100644 cfail/ui/not-send.rs delete mode 100644 cfail/ui/not-send.stderr diff --git a/Cargo.toml b/Cargo.toml index 0c45a6d0c3..3a1d1d8b1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ stable_deref_trait = { version = "1", default-features = false } [dev-dependencies] ufmt = "0.2" +static_assertions = "1.1.0" [package.metadata.docs.rs] features = ["ufmt", "serde", "defmt-03", "mpmc_large", "portable-atomic-critical-section"] diff --git a/cfail/ui/not-send.rs b/cfail/ui/not-send.rs deleted file mode 100644 index 0c8559d9d3..0000000000 --- a/cfail/ui/not-send.rs +++ /dev/null @@ -1,24 +0,0 @@ -//! Collections of non-`Send`-able things are *not* `Send` - -use core::marker::PhantomData; - -use heapless::{ - spsc::{Consumer, Producer, Queue}, - HistoryBuffer, Vec, -}; - -type NotSend = PhantomData<*const ()>; - -fn is_send() -where - T: Send, -{ -} - -fn main() { - is_send::>(); - is_send::>(); - is_send::>(); - is_send::>(); - is_send::>(); -} diff --git a/cfail/ui/not-send.stderr b/cfail/ui/not-send.stderr deleted file mode 100644 index c4985b8b50..0000000000 --- a/cfail/ui/not-send.stderr +++ /dev/null @@ -1,159 +0,0 @@ -error[E0277]: `*const ()` cannot be sent between threads safely - --> ui/not-send.rs:19:15 - | -19 | is_send::>(); - | ^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely - | - = help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()` -note: required because it appears within the type `PhantomData<*const ()>` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ - = note: required for `Consumer<'_, PhantomData<*const ()>, 4>` to implement `Send` -note: required by a bound in `is_send` - --> ui/not-send.rs:14:8 - | -12 | fn is_send() - | ------- required by a bound in this function -13 | where -14 | T: Send, - | ^^^^ required by this bound in `is_send` - -error[E0277]: `*const ()` cannot be sent between threads safely - --> ui/not-send.rs:20:15 - | -20 | is_send::>(); - | ^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely - | - = help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()` -note: required because it appears within the type `PhantomData<*const ()>` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ - = note: required for `Producer<'_, PhantomData<*const ()>, 4>` to implement `Send` -note: required by a bound in `is_send` - --> ui/not-send.rs:14:8 - | -12 | fn is_send() - | ------- required by a bound in this function -13 | where -14 | T: Send, - | ^^^^ required by this bound in `is_send` - -error[E0277]: `*const ()` cannot be sent between threads safely - --> ui/not-send.rs:21:15 - | -21 | is_send::>(); - | ^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely - | - = help: within `Queue, 4>`, the trait `Send` is not implemented for `*const ()` -note: required because it appears within the type `PhantomData<*const ()>` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ -note: required because it appears within the type `ManuallyDrop>` - --> $RUST/core/src/mem/manually_drop.rs - | - | pub struct ManuallyDrop { - | ^^^^^^^^^^^^ -note: required because it appears within the type `MaybeUninit>` - --> $RUST/core/src/mem/maybe_uninit.rs - | - | pub union MaybeUninit { - | ^^^^^^^^^^^ -note: required because it appears within the type `UnsafeCell>>` - --> $RUST/core/src/cell.rs - | - | pub struct UnsafeCell { - | ^^^^^^^^^^ - = note: required because it appears within the type `[UnsafeCell>>; 4]` -note: required because it appears within the type `Queue, 4>` - --> $HEAPLESS/src/spsc.rs - | - | pub struct Queue { - | ^^^^^ -note: required by a bound in `is_send` - --> ui/not-send.rs:14:8 - | -12 | fn is_send() - | ------- required by a bound in this function -13 | where -14 | T: Send, - | ^^^^ required by this bound in `is_send` - -error[E0277]: `*const ()` cannot be sent between threads safely - --> ui/not-send.rs:22:15 - | -22 | is_send::>(); - | ^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely - | - = help: within `heapless::vec::VecInner<[MaybeUninit>; 4]>`, the trait `Send` is not implemented for `*const ()` -note: required because it appears within the type `PhantomData<*const ()>` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ -note: required because it appears within the type `ManuallyDrop>` - --> $RUST/core/src/mem/manually_drop.rs - | - | pub struct ManuallyDrop { - | ^^^^^^^^^^^^ -note: required because it appears within the type `MaybeUninit>` - --> $RUST/core/src/mem/maybe_uninit.rs - | - | pub union MaybeUninit { - | ^^^^^^^^^^^ - = note: required because it appears within the type `[MaybeUninit>; 4]` -note: required because it appears within the type `heapless::vec::VecInner<[MaybeUninit>; 4]>` - --> $HEAPLESS/src/vec.rs - | - | pub struct VecInner { - | ^^^^^^^^ -note: required by a bound in `is_send` - --> ui/not-send.rs:14:8 - | -12 | fn is_send() - | ------- required by a bound in this function -13 | where -14 | T: Send, - | ^^^^ required by this bound in `is_send` - -error[E0277]: `*const ()` cannot be sent between threads safely - --> ui/not-send.rs:23:15 - | -23 | is_send::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely - | - = help: within `HistoryBuffer, 4>`, the trait `Send` is not implemented for `*const ()` -note: required because it appears within the type `PhantomData<*const ()>` - --> $RUST/core/src/marker.rs - | - | pub struct PhantomData; - | ^^^^^^^^^^^ -note: required because it appears within the type `ManuallyDrop>` - --> $RUST/core/src/mem/manually_drop.rs - | - | pub struct ManuallyDrop { - | ^^^^^^^^^^^^ -note: required because it appears within the type `MaybeUninit>` - --> $RUST/core/src/mem/maybe_uninit.rs - | - | pub union MaybeUninit { - | ^^^^^^^^^^^ - = note: required because it appears within the type `[MaybeUninit>; 4]` -note: required because it appears within the type `HistoryBuffer, 4>` - --> $HEAPLESS/src/histbuf.rs - | - | pub struct HistoryBuffer { - | ^^^^^^^^^^^^^ -note: required by a bound in `is_send` - --> ui/not-send.rs:14:8 - | -12 | fn is_send() - | ------- required by a bound in this function -13 | where -14 | T: Send, - | ^^^^ required by this bound in `is_send` diff --git a/src/deque.rs b/src/deque.rs index c19369b2f6..9e923539f9 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -745,7 +745,12 @@ where #[cfg(test)] mod tests { - use crate::Deque; + use static_assertions::assert_not_impl_any; + + use super::Deque; + + // Ensure a `Deque` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(Deque<*const (), 4>: Send); #[test] fn static_new() { diff --git a/src/histbuf.rs b/src/histbuf.rs index 45d9462260..98f7556181 100644 --- a/src/histbuf.rs +++ b/src/histbuf.rs @@ -433,10 +433,16 @@ impl<'a, T, const N: usize> Iterator for OldestOrdered<'a, T, N> { #[cfg(test)] mod tests { - use crate::HistoryBuffer; use core::fmt::Debug; use core::sync::atomic::{AtomicUsize, Ordering}; + use static_assertions::assert_not_impl_any; + + use super::HistoryBuffer; + + // Ensure a `HistoryBuffer` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(HistoryBuffer<*const (), 4>: Send); + #[test] fn new() { let x: HistoryBuffer = HistoryBuffer::new_with(1); diff --git a/src/indexmap.rs b/src/indexmap.rs index bd07a56e9d..957d81c5df 100644 --- a/src/indexmap.rs +++ b/src/indexmap.rs @@ -1262,10 +1262,17 @@ where #[cfg(test)] mod tests { - use crate::{indexmap::Entry, FnvIndexMap}; - use core::mem; + use static_assertions::assert_not_impl_any; + + use super::{BuildHasherDefault, Entry, FnvIndexMap, IndexMap}; + + // Ensure a `IndexMap` containing `!Send` keys stays `!Send` itself. + assert_not_impl_any!(IndexMap<*const (), (), BuildHasherDefault<()>, 4>: Send); + // Ensure a `IndexMap` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(IndexMap<(), *const (), BuildHasherDefault<()>, 4>: Send); + #[test] fn size() { const CAP: usize = 4; diff --git a/src/indexset.rs b/src/indexset.rs index 04607e682c..17b970ab57 100644 --- a/src/indexset.rs +++ b/src/indexset.rs @@ -1,11 +1,13 @@ -use crate::indexmap::{self, IndexMap}; use core::{ borrow::Borrow, fmt, hash::{BuildHasher, Hash}, }; + use hash32::{BuildHasherDefault, FnvHasher}; +use crate::indexmap::{self, IndexMap}; + /// An [`IndexSet`] using the default FNV hasher. /// /// A list of all Methods and Traits available for `FnvIndexSet` can be found in @@ -659,3 +661,13 @@ where } } } + +#[cfg(test)] +mod tests { + use static_assertions::assert_not_impl_any; + + use super::{BuildHasherDefault, IndexSet}; + + // Ensure a `IndexSet` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(IndexSet<*const (), BuildHasherDefault<()>, 4>: Send); +} diff --git a/src/linear_map.rs b/src/linear_map.rs index efdfe4f417..a7a07198af 100644 --- a/src/linear_map.rs +++ b/src/linear_map.rs @@ -1,6 +1,7 @@ -use crate::Vec; use core::{borrow::Borrow, fmt, mem, ops, slice}; +use crate::Vec; + /// 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). @@ -492,7 +493,14 @@ where #[cfg(test)] mod test { - use crate::LinearMap; + use static_assertions::assert_not_impl_any; + + use super::LinearMap; + + // Ensure a `LinearMap` containing `!Send` keys stays `!Send` itself. + assert_not_impl_any!(LinearMap<*const (), (), 4>: Send); + // Ensure a `LinearMap` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(LinearMap<(), *const (), 4>: Send); #[test] fn static_new() { diff --git a/src/mpmc.rs b/src/mpmc.rs index 578a6698b2..9b0b6feb18 100644 --- a/src/mpmc.rs +++ b/src/mpmc.rs @@ -294,7 +294,12 @@ unsafe fn enqueue( #[cfg(test)] mod tests { - use super::Q2; + use static_assertions::assert_not_impl_any; + + use super::{MpMcQueue, Q2}; + + // Ensure a `MpMcQueue` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(MpMcQueue<*const (), 4>: Send); #[test] fn sanity() { diff --git a/src/sorted_linked_list.rs b/src/sorted_linked_list.rs index f4102bd065..64bcdd6bf0 100644 --- a/src/sorted_linked_list.rs +++ b/src/sorted_linked_list.rs @@ -743,8 +743,13 @@ where #[cfg(test)] mod tests { + use static_assertions::assert_not_impl_any; + use super::*; + // Ensure a `SortedLinkedList` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(SortedLinkedList<*const (), LinkedIndexU8, (), 4>: Send); + #[test] fn const_new() { static mut _V1: SortedLinkedList = SortedLinkedList::new_u8(); diff --git a/src/spsc.rs b/src/spsc.rs index 3b9db75f6b..1b7ab0354b 100644 --- a/src/spsc.rs +++ b/src/spsc.rs @@ -632,7 +632,18 @@ impl<'a, T, const N: usize> Producer<'a, T, N> { mod tests { use std::hash::{Hash, Hasher}; - use crate::spsc::Queue; + use super::{Consumer, Producer, Queue}; + + use static_assertions::assert_not_impl_any; + + // Ensure a `Queue` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(Queue<*const (), 4>: Send); + + // Ensure a `Producer` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(Producer<*const (), 4>: Send); + + // Ensure a `Consumer` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(Consumer<*const (), 4>: Send); #[test] fn full() { diff --git a/src/vec.rs b/src/vec.rs index 0588f4d182..0361d41c56 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -1,7 +1,6 @@ use core::{ cmp::Ordering, - fmt, hash, - mem, + fmt, hash, mem, mem::{ManuallyDrop, MaybeUninit}, ops, ptr, slice, }; @@ -2079,9 +2078,15 @@ where #[cfg(test)] mod tests { - use crate::Vec; use core::fmt::Write; + use static_assertions::assert_not_impl_any; + + use crate::Vec; + + // Ensure a `Vec` containing `!Send` values stays `!Send` itself. + assert_not_impl_any!(Vec<*const (), 4>: Send); + #[test] fn static_new() { static mut _V: Vec = Vec::new();