Skip to content

Commit aee0817

Browse files
authored
Merge pull request #199 from kpp/const_generics
Fix several issues in const generics
2 parents 3de878b + 5bde47c commit aee0817

File tree

10 files changed

+85
-112
lines changed

10 files changed

+85
-112
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ jobs:
105105
toolchain:
106106
- stable
107107
- nightly
108-
- 1.36.0
108+
- 1.51.0
109109
features:
110110
- serde
111111
buildtype:
@@ -242,7 +242,7 @@ jobs:
242242
- name: Install Rust
243243
uses: actions-rs/toolchain@v1
244244
with:
245-
toolchain: 1.36.0
245+
toolchain: 1.51.0
246246
target: x86_64-unknown-linux-gnu
247247
override: true
248248

cfail/ui/freeze.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use heapless::{consts, spsc::Queue};
1+
use heapless::{spsc::Queue};
22

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

66
let (_p, mut _c) = q.split();
77
q.enqueue(0).unwrap();

cfail/ui/not-send.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use core::marker::PhantomData;
44

55
use heapless::{
6-
consts,
76
spsc::{Consumer, Producer, Queue},
87
};
98

@@ -16,8 +15,8 @@ where
1615
}
1716

1817
fn main() {
19-
is_send::<Consumer<NotSend, consts::U4>>();
20-
is_send::<Producer<NotSend, consts::U4>>();
21-
is_send::<Queue<NotSend, consts::U4>>();
22-
is_send::<heapless::Vec<NotSend, consts::U4>>();
18+
is_send::<Consumer<NotSend, _, _, 4>>();
19+
is_send::<Producer<NotSend, _, _, 4>>();
20+
is_send::<Queue<NotSend, _, _, 4>>();
21+
is_send::<heapless::Vec<NotSend, 4>>();
2322
}

cfail/ui/not-send.stderr

Lines changed: 54 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,69 @@
11
error[E0277]: `*const ()` cannot be sent between threads safely
2-
--> $DIR/not-send.rs:19:5
3-
|
4-
19 | is_send::<Consumer<NotSend, consts::U4>>();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
2+
--> $DIR/not-send.rs:18:5
63
|
7-
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
8-
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
9-
= 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>>`
10-
note: required by `is_send`
11-
--> $DIR/not-send.rs:12:1
4+
11 | fn is_send<T>()
5+
| ------- required by a bound in this
6+
12 | where
7+
13 | T: Send,
8+
| ---- required by this bound in `is_send`
9+
...
10+
18 | is_send::<Consumer<NotSend, _, _, 4>>();
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
1212
|
13-
12 | / fn is_send<T>()
14-
13 | | where
15-
14 | | T: Send,
16-
15 | | {
17-
16 | | }
18-
| |_^
13+
= help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()`
14+
= note: required because it appears within the type `PhantomData<*const ()>`
15+
= note: required because of the requirements on the impl of `Send` for `Consumer<'_, PhantomData<*const ()>, _, _, 4_usize>`
1916

2017
error[E0277]: `*const ()` cannot be sent between threads safely
21-
--> $DIR/not-send.rs:20:5
22-
|
23-
20 | is_send::<Producer<NotSend, consts::U4>>();
24-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
18+
--> $DIR/not-send.rs:19:5
2519
|
26-
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
27-
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
28-
= 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>>`
29-
note: required by `is_send`
30-
--> $DIR/not-send.rs:12:1
20+
11 | fn is_send<T>()
21+
| ------- required by a bound in this
22+
12 | where
23+
13 | T: Send,
24+
| ---- required by this bound in `is_send`
25+
...
26+
19 | is_send::<Producer<NotSend, _, _, 4>>();
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
3128
|
32-
12 | / fn is_send<T>()
33-
13 | | where
34-
14 | | T: Send,
35-
15 | | {
36-
16 | | }
37-
| |_^
29+
= help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()`
30+
= note: required because it appears within the type `PhantomData<*const ()>`
31+
= note: required because of the requirements on the impl of `Send` for `Producer<'_, PhantomData<*const ()>, _, _, 4_usize>`
3832

3933
error[E0277]: `*const ()` cannot be sent between threads safely
40-
--> $DIR/not-send.rs:21:5
41-
|
42-
21 | is_send::<Queue<NotSend, consts::U4>>();
43-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
34+
--> $DIR/not-send.rs:20:5
4435
|
45-
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
46-
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
47-
= 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>>`
48-
= 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>>>`
49-
= 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>>>`
50-
= 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>>>`
51-
= 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>>`
52-
note: required by `is_send`
53-
--> $DIR/not-send.rs:12:1
36+
11 | fn is_send<T>()
37+
| ------- required by a bound in this
38+
12 | where
39+
13 | T: Send,
40+
| ---- required by this bound in `is_send`
41+
...
42+
20 | is_send::<Queue<NotSend, _, _, 4>>();
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
5444
|
55-
12 | / fn is_send<T>()
56-
13 | | where
57-
14 | | T: Send,
58-
15 | | {
59-
16 | | }
60-
| |_^
45+
= help: within `Queue<PhantomData<*const ()>, _, _, 4_usize>`, the trait `Send` is not implemented for `*const ()`
46+
= note: required because it appears within the type `PhantomData<*const ()>`
47+
= note: required because it appears within the type `[PhantomData<*const ()>; 4]`
48+
= note: required because it appears within the type `ManuallyDrop<[PhantomData<*const ()>; 4]>`
49+
= note: required because it appears within the type `MaybeUninit<[PhantomData<*const ()>; 4]>`
50+
= note: required because it appears within the type `Queue<PhantomData<*const ()>, _, _, 4_usize>`
6151

6252
error[E0277]: `*const ()` cannot be sent between threads safely
63-
--> $DIR/not-send.rs:22:5
64-
|
65-
22 | is_send::<heapless::Vec<NotSend, consts::U4>>();
66-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
53+
--> $DIR/not-send.rs:21:5
6754
|
68-
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
69-
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
70-
= 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>>`
71-
= 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>>>`
72-
= 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>>>`
73-
= 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>>>`
74-
= 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>>`
75-
note: required by `is_send`
76-
--> $DIR/not-send.rs:12:1
55+
11 | fn is_send<T>()
56+
| ------- required by a bound in this
57+
12 | where
58+
13 | T: Send,
59+
| ---- required by this bound in `is_send`
60+
...
61+
21 | is_send::<heapless::Vec<NotSend, 4>>();
62+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
7763
|
78-
12 | / fn is_send<T>()
79-
13 | | where
80-
14 | | T: Send,
81-
15 | | {
82-
16 | | }
83-
| |_^
64+
= help: within `heapless::Vec<PhantomData<*const ()>, 4_usize>`, the trait `Send` is not implemented for `*const ()`
65+
= note: required because it appears within the type `PhantomData<*const ()>`
66+
= note: required because it appears within the type `[PhantomData<*const ()>; 4]`
67+
= note: required because it appears within the type `ManuallyDrop<[PhantomData<*const ()>; 4]>`
68+
= note: required because it appears within the type `MaybeUninit<[PhantomData<*const ()>; 4]>`
69+
= note: required because it appears within the type `heapless::Vec<PhantomData<*const ()>, 4_usize>`

src/de.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
use crate::{
2+
sealed::binary_heap::Kind as BinaryHeapKind, BinaryHeap, IndexMap, IndexSet, LinearMap, String,
3+
Vec,
4+
};
15
use core::{fmt, marker::PhantomData};
26
use hash32::{BuildHasherDefault, Hash, Hasher};
37
use serde::de::{self, Deserialize, Deserializer, Error, MapAccess, SeqAccess};
4-
use crate::{
5-
sealed::binary_heap::Kind as BinaryHeapKind,
6-
BinaryHeap, IndexMap, IndexSet, LinearMap, String, Vec,
7-
};
88

99
// Sequential containers
1010

@@ -142,9 +142,9 @@ where
142142
where
143143
D: Deserializer<'de>,
144144
{
145-
struct ValueVisitor<'de, K, V, S, const N:usize>(PhantomData<(&'de (), K, V, S)>);
145+
struct ValueVisitor<'de, K, V, S, const N: usize>(PhantomData<(&'de (), K, V, S)>);
146146

147-
impl<'de, K, V, S, const N:usize> de::Visitor<'de> for ValueVisitor<'de, K, V, S, N>
147+
impl<'de, K, V, S, const N: usize> de::Visitor<'de> for ValueVisitor<'de, K, V, S, N>
148148
where
149149
K: Eq + Hash + Deserialize<'de>,
150150
V: Deserialize<'de>,
@@ -175,7 +175,7 @@ where
175175
}
176176
}
177177

178-
impl<'de, K, V, const N:usize> Deserialize<'de> for LinearMap<K, V, N>
178+
impl<'de, K, V, const N: usize> Deserialize<'de> for LinearMap<K, V, N>
179179
where
180180
K: Eq + Deserialize<'de>,
181181
V: Deserialize<'de>,
@@ -184,9 +184,9 @@ where
184184
where
185185
D: Deserializer<'de>,
186186
{
187-
struct ValueVisitor<'de, K, V, const N:usize>(PhantomData<(&'de (), K, V)>);
187+
struct ValueVisitor<'de, K, V, const N: usize>(PhantomData<(&'de (), K, V)>);
188188

189-
impl<'de, K, V, const N:usize> de::Visitor<'de> for ValueVisitor<'de, K, V, N>
189+
impl<'de, K, V, const N: usize> de::Visitor<'de> for ValueVisitor<'de, K, V, N>
190190
where
191191
K: Eq + Deserialize<'de>,
192192
V: Deserialize<'de>,
@@ -218,24 +218,18 @@ where
218218

219219
// String containers
220220

221-
impl<'de, const N:usize> Deserialize<'de> for String<N>
222-
{
221+
impl<'de, const N: usize> Deserialize<'de> for String<N> {
223222
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
224223
where
225224
D: Deserializer<'de>,
226225
{
227-
struct ValueVisitor<'de, const N:usize>(PhantomData<&'de ()>);
226+
struct ValueVisitor<'de, const N: usize>(PhantomData<&'de ()>);
228227

229-
impl<'de, const N:usize > de::Visitor<'de> for ValueVisitor<'de, N>
230-
{
228+
impl<'de, const N: usize> de::Visitor<'de> for ValueVisitor<'de, N> {
231229
type Value = String<N>;
232230

233231
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
234-
write!(
235-
formatter,
236-
"a string no more than {} bytes long",
237-
N as u64
238-
)
232+
write!(formatter, "a string no more than {} bytes long", N as u64)
239233
}
240234

241235
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>

src/indexmap.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
use core::{
2-
borrow::Borrow,
3-
fmt,
4-
iter::FromIterator,
5-
mem::{self, MaybeUninit},
6-
num::NonZeroU32,
7-
ops, slice,
8-
};
1+
use core::{borrow::Borrow, fmt, iter::FromIterator, mem, num::NonZeroU32, ops, slice};
92

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

@@ -126,14 +119,12 @@ macro_rules! probe_loop {
126119
}
127120
}
128121

129-
struct CoreMap<K, V, const N: usize>
130-
{
122+
struct CoreMap<K, V, const N: usize> {
131123
entries: Vec<Bucket<K, V>, N>,
132124
indices: [Option<Pos>; N],
133125
}
134126

135-
impl<K, V, const N: usize> CoreMap<K, V, N>
136-
{
127+
impl<K, V, const N: usize> CoreMap<K, V, N> {
137128
const fn new() -> Self {
138129
const INIT: Option<Pos> = None;
139130

src/pool/singleton.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ use as_slice::{AsMutSlice, AsSlice};
1515
use super::{Init, Node, Uninit};
1616

1717
/// Instantiates a pool as a global singleton
18+
// NOTE(any(test)) makes testing easier (no need to enable Cargo features for testing)
1819
#[cfg(any(
1920
armv7a,
2021
armv7r,
2122
armv7m,
2223
armv8m_main,
2324
all(target_arch = "x86_64", feature = "x86-sync-pool"),
25+
test
2426
))]
2527
#[macro_export]
2628
macro_rules! pool {

src/ufmt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use ufmt_write::uWrite;
21
use crate::{string::String, vec::Vec};
2+
use ufmt_write::uWrite;
33

44
impl<const N: usize> uWrite for String<N> {
55
type Error = ();

tests/cpass.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Collections of `Send`-able things are `Send`
22
33
use heapless::{
4-
spsc::{Consumer, Producer, Queue, MultiCore},
4+
spsc::{Consumer, MultiCore, Producer, Queue},
55
HistoryBuffer, Vec,
66
};
77

tests/tsan.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ fn unchecked() {
188188
scope.execute(move || {
189189
let mut sum: usize = 0;
190190

191-
for _ in 0..N/ 2 {
191+
for _ in 0..N / 2 {
192192
sum = sum.wrapping_add(usize::from(unsafe { c.dequeue_unchecked() }));
193193
}
194194

@@ -197,7 +197,7 @@ fn unchecked() {
197197
});
198198
}
199199

200-
assert_eq!(rb.len(), N/ 2);
200+
assert_eq!(rb.len(), N / 2);
201201
}
202202

203203
#[test]
@@ -235,6 +235,7 @@ fn iterator_properly_wraps() {
235235
assert_eq!(expected, actual)
236236
}
237237

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

0 commit comments

Comments
 (0)