Skip to content

Commit

Permalink
Merge pull request #199 from kpp/const_generics
Browse files Browse the repository at this point in the history
Fix several issues in const generics
  • Loading branch information
korken89 authored Mar 30, 2021
2 parents 3de878b + 5bde47c commit aee0817
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 112 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ jobs:
toolchain:
- stable
- nightly
- 1.36.0
- 1.51.0
features:
- serde
buildtype:
Expand Down Expand Up @@ -242,7 +242,7 @@ jobs:
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: 1.36.0
toolchain: 1.51.0
target: x86_64-unknown-linux-gnu
override: true

Expand Down
4 changes: 2 additions & 2 deletions cfail/ui/freeze.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use heapless::{consts, spsc::Queue};
use heapless::{spsc::Queue};

fn main() {
let mut q: Queue<u8, consts::U4> = Queue::new();
let mut q: Queue<u8, _, _, 4> = Queue::new();

let (_p, mut _c) = q.split();
q.enqueue(0).unwrap();
Expand Down
9 changes: 4 additions & 5 deletions cfail/ui/not-send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use core::marker::PhantomData;

use heapless::{
consts,
spsc::{Consumer, Producer, Queue},
};

Expand All @@ -16,8 +15,8 @@ where
}

fn main() {
is_send::<Consumer<NotSend, consts::U4>>();
is_send::<Producer<NotSend, consts::U4>>();
is_send::<Queue<NotSend, consts::U4>>();
is_send::<heapless::Vec<NotSend, consts::U4>>();
is_send::<Consumer<NotSend, _, _, 4>>();
is_send::<Producer<NotSend, _, _, 4>>();
is_send::<Queue<NotSend, _, _, 4>>();
is_send::<heapless::Vec<NotSend, 4>>();
}
122 changes: 54 additions & 68 deletions cfail/ui/not-send.stderr
Original file line number Diff line number Diff line change
@@ -1,83 +1,69 @@
error[E0277]: `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:19:5
|
19 | is_send::<Consumer<NotSend, consts::U4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:18:5
|
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
= note: required because of the requirements on the impl of `std::marker::Send` for `heapless::spsc::split::Consumer<'_, std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
note: required by `is_send`
--> $DIR/not-send.rs:12:1
11 | fn is_send<T>()
| ------- required by a bound in this
12 | where
13 | T: Send,
| ---- required by this bound in `is_send`
...
18 | is_send::<Consumer<NotSend, _, _, 4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
|
12 | / fn is_send<T>()
13 | | where
14 | | T: Send,
15 | | {
16 | | }
| |_^
= help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()`
= note: required because it appears within the type `PhantomData<*const ()>`
= note: required because of the requirements on the impl of `Send` for `Consumer<'_, PhantomData<*const ()>, _, _, 4_usize>`

error[E0277]: `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:20:5
|
20 | is_send::<Producer<NotSend, consts::U4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:19:5
|
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
= note: required because of the requirements on the impl of `std::marker::Send` for `heapless::spsc::split::Producer<'_, std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
note: required by `is_send`
--> $DIR/not-send.rs:12:1
11 | fn is_send<T>()
| ------- required by a bound in this
12 | where
13 | T: Send,
| ---- required by this bound in `is_send`
...
19 | is_send::<Producer<NotSend, _, _, 4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
|
12 | / fn is_send<T>()
13 | | where
14 | | T: Send,
15 | | {
16 | | }
| |_^
= help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()`
= note: required because it appears within the type `PhantomData<*const ()>`
= note: required because of the requirements on the impl of `Send` for `Producer<'_, PhantomData<*const ()>, _, _, 4_usize>`

error[E0277]: `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:21:5
|
21 | is_send::<Queue<NotSend, consts::U4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:20:5
|
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
= note: required because of the requirements on the impl of `std::marker::Send` for `generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
= note: required because it appears within the type `std::mem::ManuallyDrop<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `std::mem::MaybeUninit<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `heapless::i::Queue<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `heapless::spsc::Queue<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
note: required by `is_send`
--> $DIR/not-send.rs:12:1
11 | fn is_send<T>()
| ------- required by a bound in this
12 | where
13 | T: Send,
| ---- required by this bound in `is_send`
...
20 | is_send::<Queue<NotSend, _, _, 4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
|
12 | / fn is_send<T>()
13 | | where
14 | | T: Send,
15 | | {
16 | | }
| |_^
= help: within `Queue<PhantomData<*const ()>, _, _, 4_usize>`, the trait `Send` is not implemented for `*const ()`
= note: required because it appears within the type `PhantomData<*const ()>`
= note: required because it appears within the type `[PhantomData<*const ()>; 4]`
= note: required because it appears within the type `ManuallyDrop<[PhantomData<*const ()>; 4]>`
= note: required because it appears within the type `MaybeUninit<[PhantomData<*const ()>; 4]>`
= note: required because it appears within the type `Queue<PhantomData<*const ()>, _, _, 4_usize>`

error[E0277]: `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:22:5
|
22 | is_send::<heapless::Vec<NotSend, consts::U4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:21:5
|
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
= note: required because of the requirements on the impl of `std::marker::Send` for `generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
= note: required because it appears within the type `std::mem::ManuallyDrop<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `std::mem::MaybeUninit<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `heapless::i::Vec<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `heapless::vec::Vec<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
note: required by `is_send`
--> $DIR/not-send.rs:12:1
11 | fn is_send<T>()
| ------- required by a bound in this
12 | where
13 | T: Send,
| ---- required by this bound in `is_send`
...
21 | is_send::<heapless::Vec<NotSend, 4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
|
12 | / fn is_send<T>()
13 | | where
14 | | T: Send,
15 | | {
16 | | }
| |_^
= help: within `heapless::Vec<PhantomData<*const ()>, 4_usize>`, the trait `Send` is not implemented for `*const ()`
= note: required because it appears within the type `PhantomData<*const ()>`
= note: required because it appears within the type `[PhantomData<*const ()>; 4]`
= note: required because it appears within the type `ManuallyDrop<[PhantomData<*const ()>; 4]>`
= note: required because it appears within the type `MaybeUninit<[PhantomData<*const ()>; 4]>`
= note: required because it appears within the type `heapless::Vec<PhantomData<*const ()>, 4_usize>`
32 changes: 13 additions & 19 deletions src/de.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{
sealed::binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String,
Vec,
};
use core::{fmt, marker::PhantomData};
use hash32::{BuildHasherDefault, Hash, Hasher};
use serde::de::{self, Deserialize, Deserializer, Error, MapAccess, SeqAccess};
use crate::{
sealed::binary_heap::Kind as BinaryHeapKind,
BinaryHeap, IndexMap, IndexSet, LinearMap, String, Vec,
};

// Sequential containers

Expand Down Expand Up @@ -142,9 +142,9 @@ where
where
D: Deserializer<'de>,
{
struct ValueVisitor<'de, K, V, S, const N:usize>(PhantomData<(&'de (), K, V, S)>);
struct ValueVisitor<'de, K, V, S, const N: usize>(PhantomData<(&'de (), K, V, S)>);

impl<'de, K, V, S, const N:usize> de::Visitor<'de> for ValueVisitor<'de, K, V, S, N>
impl<'de, K, V, S, const N: usize> de::Visitor<'de> for ValueVisitor<'de, K, V, S, N>
where
K: Eq + Hash + Deserialize<'de>,
V: Deserialize<'de>,
Expand Down Expand Up @@ -175,7 +175,7 @@ where
}
}

impl<'de, K, V, const N:usize> Deserialize<'de> for LinearMap<K, V, N>
impl<'de, K, V, const N: usize> Deserialize<'de> for LinearMap<K, V, N>
where
K: Eq + Deserialize<'de>,
V: Deserialize<'de>,
Expand All @@ -184,9 +184,9 @@ where
where
D: Deserializer<'de>,
{
struct ValueVisitor<'de, K, V, const N:usize>(PhantomData<(&'de (), K, V)>);
struct ValueVisitor<'de, K, V, const N: usize>(PhantomData<(&'de (), K, V)>);

impl<'de, K, V, const N:usize> de::Visitor<'de> for ValueVisitor<'de, K, V, N>
impl<'de, K, V, const N: usize> de::Visitor<'de> for ValueVisitor<'de, K, V, N>
where
K: Eq + Deserialize<'de>,
V: Deserialize<'de>,
Expand Down Expand Up @@ -218,24 +218,18 @@ where

// String containers

impl<'de, const N:usize> Deserialize<'de> for String<N>
{
impl<'de, const N: usize> Deserialize<'de> for String<N> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct ValueVisitor<'de, const N:usize>(PhantomData<&'de ()>);
struct ValueVisitor<'de, const N: usize>(PhantomData<&'de ()>);

impl<'de, const N:usize > de::Visitor<'de> for ValueVisitor<'de, N>
{
impl<'de, const N: usize> de::Visitor<'de> for ValueVisitor<'de, N> {
type Value = String<N>;

fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
formatter,
"a string no more than {} bytes long",
N as u64
)
write!(formatter, "a string no more than {} bytes long", N as u64)
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
Expand Down
15 changes: 3 additions & 12 deletions src/indexmap.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
use core::{
borrow::Borrow,
fmt,
iter::FromIterator,
mem::{self, MaybeUninit},
num::NonZeroU32,
ops, slice,
};
use core::{borrow::Borrow, fmt, iter::FromIterator, mem, num::NonZeroU32, ops, slice};

use hash32::{BuildHasher, BuildHasherDefault, FnvHasher, Hash, Hasher};

Expand Down Expand Up @@ -126,14 +119,12 @@ macro_rules! probe_loop {
}
}

struct CoreMap<K, V, const N: usize>
{
struct CoreMap<K, V, const N: usize> {
entries: Vec<Bucket<K, V>, N>,
indices: [Option<Pos>; N],
}

impl<K, V, const N: usize> CoreMap<K, V, N>
{
impl<K, V, const N: usize> CoreMap<K, V, N> {
const fn new() -> Self {
const INIT: Option<Pos> = None;

Expand Down
2 changes: 2 additions & 0 deletions src/pool/singleton.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ use as_slice::{AsMutSlice, AsSlice};
use super::{Init, Node, Uninit};

/// Instantiates a pool as a global singleton
// NOTE(any(test)) makes testing easier (no need to enable Cargo features for testing)
#[cfg(any(
armv7a,
armv7r,
armv7m,
armv8m_main,
all(target_arch = "x86_64", feature = "x86-sync-pool"),
test
))]
#[macro_export]
macro_rules! pool {
Expand Down
2 changes: 1 addition & 1 deletion src/ufmt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ufmt_write::uWrite;
use crate::{string::String, vec::Vec};
use ufmt_write::uWrite;

impl<const N: usize> uWrite for String<N> {
type Error = ();
Expand Down
2 changes: 1 addition & 1 deletion tests/cpass.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Collections of `Send`-able things are `Send`

use heapless::{
spsc::{Consumer, Producer, Queue, MultiCore},
spsc::{Consumer, MultiCore, Producer, Queue},
HistoryBuffer, Vec,
};

Expand Down
5 changes: 3 additions & 2 deletions tests/tsan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ fn unchecked() {
scope.execute(move || {
let mut sum: usize = 0;

for _ in 0..N/ 2 {
for _ in 0..N / 2 {
sum = sum.wrapping_add(usize::from(unsafe { c.dequeue_unchecked() }));
}

Expand All @@ -197,7 +197,7 @@ fn unchecked() {
});
}

assert_eq!(rb.len(), N/ 2);
assert_eq!(rb.len(), N / 2);
}

#[test]
Expand Down Expand Up @@ -235,6 +235,7 @@ fn iterator_properly_wraps() {
assert_eq!(expected, actual)
}

#[cfg(all(target_arch = "x86_64", feature = "x86-sync-pool"))]
#[test]
fn pool() {
use heapless::pool::singleton::Pool as _;
Expand Down

0 comments on commit aee0817

Please sign in to comment.