Skip to content

Commit b27e74d

Browse files
committed
[derive] Support deriving NoCell
Makes progress on #251
1 parent 5d49262 commit b27e74d

File tree

18 files changed

+475
-269
lines changed

18 files changed

+475
-269
lines changed

src/byteorder.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ example of how it can be used for parsing UDP packets.
276276
[`AsBytes`]: crate::AsBytes
277277
[`Unaligned`]: crate::Unaligned"),
278278
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
279-
#[cfg_attr(any(feature = "derive", test), derive(KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned))]
279+
#[cfg_attr(any(feature = "derive", test), derive(KnownLayout, NoCell, FromZeroes, FromBytes, AsBytes, Unaligned))]
280280
#[repr(transparent)]
281281
pub struct $name<O>([u8; $bytes], PhantomData<O>);
282282
}
@@ -288,7 +288,9 @@ example of how it can be used for parsing UDP packets.
288288
/// SAFETY:
289289
/// `$name<O>` is `repr(transparent)`, and so it has the same layout
290290
/// as its only non-zero field, which is a `u8` array. `u8` arrays
291-
/// are `FromZeroes`, `FromBytes`, `AsBytes`, and `Unaligned`.
291+
/// are `NoCell`, `FromZeroes`, `FromBytes`, `AsBytes`, and
292+
/// `Unaligned`.
293+
impl_or_verify!(O => NoCell for $name<O>);
292294
impl_or_verify!(O => FromZeroes for $name<O>);
293295
impl_or_verify!(O => FromBytes for $name<O>);
294296
impl_or_verify!(O => AsBytes for $name<O>);

src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,14 @@ pub use zerocopy_derive::Unaligned;
264264
#[doc(hidden)]
265265
pub use zerocopy_derive::KnownLayout;
266266

267+
// `pub use` separately here so that we can mark it `#[doc(hidden)]`.
268+
//
269+
// TODO(#251): Remove this or add a doc comment.
270+
#[cfg(any(feature = "derive", test))]
271+
#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
272+
#[doc(hidden)]
273+
pub use zerocopy_derive::NoCell;
274+
267275
use core::{
268276
cell::{self, RefMut},
269277
cmp::Ordering,
@@ -7921,7 +7929,7 @@ mod tests {
79217929
assert_impls!(Wrapping<NotZerocopy>: KnownLayout, !NoCell, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
79227930
assert_impls!(Wrapping<UnsafeCell<()>>: KnownLayout, !NoCell, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
79237931

7924-
assert_impls!(Unalign<u8>: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !NoCell, !TryFromBytes);
7932+
assert_impls!(Unalign<u8>: KnownLayout, NoCell, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes);
79257933
assert_impls!(Unalign<NotZerocopy>: Unaligned, !NoCell, !KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes);
79267934

79277935
assert_impls!([u8]: KnownLayout, NoCell, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes);

src/util.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ pub(crate) mod testutil {
616616
// By contrast, `AU64` is guaranteed to have alignment 8.
617617
#[derive(
618618
KnownLayout,
619+
NoCell,
619620
FromZeroes,
620621
FromBytes,
621622
AsBytes,
@@ -645,7 +646,7 @@ pub(crate) mod testutil {
645646
}
646647

647648
#[derive(
648-
FromZeroes, FromBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone,
649+
NoCell, FromZeroes, FromBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone,
649650
)]
650651
#[repr(C)]
651652
pub(crate) struct Nested<T, U: ?Sized> {

src/wrappers.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use super::*;
6060
#[derive(Default, Copy)]
6161
#[cfg_attr(
6262
any(feature = "derive", test),
63-
derive(KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned)
63+
derive(NoCell, KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned)
6464
)]
6565
#[repr(C, packed)]
6666
pub struct Unalign<T>(T);
@@ -74,7 +74,10 @@ safety_comment! {
7474
/// alignment of `T`, and so we don't require that `T: Unaligned`
7575
/// - `Unalign<T>` has the same bit validity as `T`, and so it is
7676
/// `FromZeroes`, `FromBytes`, or `AsBytes` exactly when `T` is as well.
77+
/// - `NoCell`: `Unalign<T>` has the same fields as `T`, so it contains
78+
/// `UnsafeCell`s exactly when `T` does.
7779
impl_or_verify!(T => Unaligned for Unalign<T>);
80+
impl_or_verify!(T: NoCell => NoCell for Unalign<T>);
7881
impl_or_verify!(T: FromZeroes => FromZeroes for Unalign<T>);
7982
impl_or_verify!(T: FromBytes => FromBytes for Unalign<T>);
8083
impl_or_verify!(T: AsBytes => AsBytes for Unalign<T>);

zerocopy-derive/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,23 @@ pub fn derive_known_layout(ts: proc_macro::TokenStream) -> proc_macro::TokenStre
243243
.into()
244244
}
245245

246+
#[proc_macro_derive(NoCell)]
247+
pub fn derive_no_cell(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
248+
let ast = syn::parse_macro_input!(ts as DeriveInput);
249+
match &ast.data {
250+
Data::Struct(strct) => {
251+
impl_block(&ast, strct, Trait::NoCell, RequireBoundedFields::Yes, false, None, None)
252+
}
253+
Data::Enum(enm) => {
254+
impl_block(&ast, enm, Trait::NoCell, RequireBoundedFields::Yes, false, None, None)
255+
}
256+
Data::Union(unn) => {
257+
impl_block(&ast, unn, Trait::NoCell, RequireBoundedFields::Yes, false, None, None)
258+
}
259+
}
260+
.into()
261+
}
262+
246263
#[proc_macro_derive(FromZeroes)]
247264
pub fn derive_from_zeroes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
248265
let ast = syn::parse_macro_input!(ts as DeriveInput);
@@ -637,6 +654,7 @@ impl PaddingCheck {
637654
#[derive(Debug, Eq, PartialEq)]
638655
enum Trait {
639656
KnownLayout,
657+
NoCell,
640658
FromZeroes,
641659
FromBytes,
642660
AsBytes,

zerocopy-derive/tests/ui-msrv/enum.stderr

Lines changed: 67 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -31,149 +31,149 @@ error: must have a non-align #[repr(...)] attribute in order to guarantee this t
3131
= note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
3232

3333
error: only C-like enums can implement FromZeroes
34-
--> tests/ui-msrv/enum.rs:52:1
34+
--> tests/ui-msrv/enum.rs:61:1
3535
|
36-
52 | / enum FromZeroes1 {
37-
53 | | A(u8),
38-
54 | | }
36+
61 | / enum FromZeroes1 {
37+
62 | | A(u8),
38+
63 | | }
3939
| |_^
4040

4141
error: only C-like enums can implement FromZeroes
42-
--> tests/ui-msrv/enum.rs:57:1
42+
--> tests/ui-msrv/enum.rs:66:1
4343
|
44-
57 | / enum FromZeroes2 {
45-
58 | | A,
46-
59 | | B(u8),
47-
60 | | }
44+
66 | / enum FromZeroes2 {
45+
67 | | A,
46+
68 | | B(u8),
47+
69 | | }
4848
| |_^
4949

5050
error: FromZeroes only supported on enums with a variant that has a discriminant of `0`
51-
--> tests/ui-msrv/enum.rs:63:1
51+
--> tests/ui-msrv/enum.rs:72:1
5252
|
53-
63 | / enum FromZeroes3 {
54-
64 | | A = 1,
55-
65 | | B,
56-
66 | | }
53+
72 | / enum FromZeroes3 {
54+
73 | | A = 1,
55+
74 | | B,
56+
75 | | }
5757
| |_^
5858

5959
error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
60-
--> tests/ui-msrv/enum.rs:73:8
60+
--> tests/ui-msrv/enum.rs:82:8
6161
|
62-
73 | #[repr(C)]
62+
82 | #[repr(C)]
6363
| ^
6464

6565
error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
66-
--> tests/ui-msrv/enum.rs:79:8
66+
--> tests/ui-msrv/enum.rs:88:8
6767
|
68-
79 | #[repr(usize)]
68+
88 | #[repr(usize)]
6969
| ^^^^^
7070

7171
error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
72-
--> tests/ui-msrv/enum.rs:85:8
72+
--> tests/ui-msrv/enum.rs:94:8
7373
|
74-
85 | #[repr(isize)]
74+
94 | #[repr(isize)]
7575
| ^^^^^
7676

7777
error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
78-
--> tests/ui-msrv/enum.rs:91:8
79-
|
80-
91 | #[repr(u32)]
81-
| ^^^
78+
--> tests/ui-msrv/enum.rs:100:8
79+
|
80+
100 | #[repr(u32)]
81+
| ^^^
8282

8383
error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
84-
--> tests/ui-msrv/enum.rs:97:8
85-
|
86-
97 | #[repr(i32)]
87-
| ^^^
84+
--> tests/ui-msrv/enum.rs:106:8
85+
|
86+
106 | #[repr(i32)]
87+
| ^^^
8888

8989
error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
90-
--> tests/ui-msrv/enum.rs:103:8
90+
--> tests/ui-msrv/enum.rs:112:8
9191
|
92-
103 | #[repr(u64)]
92+
112 | #[repr(u64)]
9393
| ^^^
9494

9595
error: FromBytes requires repr of "u8", "u16", "i8", or "i16"
96-
--> tests/ui-msrv/enum.rs:109:8
96+
--> tests/ui-msrv/enum.rs:118:8
9797
|
98-
109 | #[repr(i64)]
98+
118 | #[repr(i64)]
9999
| ^^^
100100

101101
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
102-
--> tests/ui-msrv/enum.rs:119:8
102+
--> tests/ui-msrv/enum.rs:128:8
103103
|
104-
119 | #[repr(C)]
104+
128 | #[repr(C)]
105105
| ^
106106

107107
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
108-
--> tests/ui-msrv/enum.rs:125:8
108+
--> tests/ui-msrv/enum.rs:134:8
109109
|
110-
125 | #[repr(u16)]
110+
134 | #[repr(u16)]
111111
| ^^^
112112

113113
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
114-
--> tests/ui-msrv/enum.rs:131:8
114+
--> tests/ui-msrv/enum.rs:140:8
115115
|
116-
131 | #[repr(i16)]
116+
140 | #[repr(i16)]
117117
| ^^^
118118

119119
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
120-
--> tests/ui-msrv/enum.rs:137:8
120+
--> tests/ui-msrv/enum.rs:146:8
121121
|
122-
137 | #[repr(u32)]
122+
146 | #[repr(u32)]
123123
| ^^^
124124

125125
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
126-
--> tests/ui-msrv/enum.rs:143:8
126+
--> tests/ui-msrv/enum.rs:152:8
127127
|
128-
143 | #[repr(i32)]
128+
152 | #[repr(i32)]
129129
| ^^^
130130

131131
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
132-
--> tests/ui-msrv/enum.rs:149:8
132+
--> tests/ui-msrv/enum.rs:158:8
133133
|
134-
149 | #[repr(u64)]
134+
158 | #[repr(u64)]
135135
| ^^^
136136

137137
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
138-
--> tests/ui-msrv/enum.rs:155:8
138+
--> tests/ui-msrv/enum.rs:164:8
139139
|
140-
155 | #[repr(i64)]
140+
164 | #[repr(i64)]
141141
| ^^^
142142

143143
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
144-
--> tests/ui-msrv/enum.rs:161:8
144+
--> tests/ui-msrv/enum.rs:170:8
145145
|
146-
161 | #[repr(usize)]
146+
170 | #[repr(usize)]
147147
| ^^^^^
148148

149149
error: Unaligned requires repr of "u8" or "i8", and no alignment (i.e., repr(align(N > 1)))
150-
--> tests/ui-msrv/enum.rs:167:8
150+
--> tests/ui-msrv/enum.rs:176:8
151151
|
152-
167 | #[repr(isize)]
152+
176 | #[repr(isize)]
153153
| ^^^^^
154154

155155
error: cannot derive Unaligned with repr(align(N > 1))
156-
--> tests/ui-msrv/enum.rs:173:12
156+
--> tests/ui-msrv/enum.rs:182:12
157157
|
158-
173 | #[repr(u8, align(2))]
158+
182 | #[repr(u8, align(2))]
159159
| ^^^^^^^^
160160

161161
error: cannot derive Unaligned with repr(align(N > 1))
162-
--> tests/ui-msrv/enum.rs:179:12
162+
--> tests/ui-msrv/enum.rs:188:12
163163
|
164-
179 | #[repr(i8, align(2))]
164+
188 | #[repr(i8, align(2))]
165165
| ^^^^^^^^
166166

167167
error: cannot derive Unaligned with repr(align(N > 1))
168-
--> tests/ui-msrv/enum.rs:185:18
168+
--> tests/ui-msrv/enum.rs:194:18
169169
|
170-
185 | #[repr(align(1), align(2))]
170+
194 | #[repr(align(1), align(2))]
171171
| ^^^^^^^^
172172

173173
error: cannot derive Unaligned with repr(align(N > 1))
174-
--> tests/ui-msrv/enum.rs:191:8
174+
--> tests/ui-msrv/enum.rs:200:8
175175
|
176-
191 | #[repr(align(2), align(4))]
176+
200 | #[repr(align(2), align(4))]
177177
| ^^^^^^^^
178178

179179
error[E0565]: meta item in `repr` must be an identifier
@@ -197,3 +197,12 @@ error[E0566]: conflicting representation hints
197197
= note: `#[deny(conflicting_repr_hints)]` on by default
198198
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
199199
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
200+
201+
error[E0277]: the trait bound `UnsafeCell<()>: NoCell` is not satisfied
202+
--> tests/ui-msrv/enum.rs:51:10
203+
|
204+
51 | #[derive(NoCell)]
205+
| ^^^^^^ the trait `NoCell` is not implemented for `UnsafeCell<()>`
206+
|
207+
= help: see issue #48214
208+
= note: this error originates in the derive macro `NoCell` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)