Skip to content

Commit

Permalink
[derive] Don't support IntoBytes on repr(Rust) types (#1783)
Browse files Browse the repository at this point in the history
Closes #1764
  • Loading branch information
joshlf authored Sep 30, 2024
1 parent b0a8477 commit 005d1d3
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 112 deletions.
13 changes: 6 additions & 7 deletions zerocopy-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -769,12 +769,11 @@ fn derive_into_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> Result<Tok
// no padding unless #[repr(align)] explicitly adds padding, which we
// check for in this branch's condition.
(None, false)
} else if ast.generics.params.is_empty() {
// Since there are no generics, we can emit a padding check. This is
// more permissive than the next case, which requires that all field
// types implement `Unaligned`.
//
// TODO(#1764): This is probably unsound! Fix it.
} else if is_c && ast.generics.params.is_empty() {
// Since there are no generics, we can emit a padding check. `repr(C)`
// guarantees that fields won't overlap, so the padding check is sound.
// This is more permissive than the next case, which requires that all
// field types implement `Unaligned`.
(Some(PaddingCheck::Struct), false)
} else if is_c && !repr.is_align_gt_1() {
// We can't use a padding check since there are generic type arguments.
Expand All @@ -787,7 +786,7 @@ fn derive_into_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> Result<Tok
// structs without requiring `Unaligned`.
(None, true)
} else {
return Err(Error::new(Span::call_site(), "must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout"));
return Err(Error::new(Span::call_site(), "must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout"));
};

let field_bounds = if require_unaligned_fields {
Expand Down
2 changes: 1 addition & 1 deletion zerocopy-derive/tests/struct_to_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::IntoBytes);
// Test for the failure reported in #1182.

#[derive(imp::IntoBytes)]
#[repr(packed)]
#[repr(C, packed)]
pub struct IndexEntryFlags(u8);

#[derive(imp::IntoBytes)]
Expand Down
72 changes: 44 additions & 28 deletions zerocopy-derive/tests/ui-msrv/struct.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,94 +4,110 @@ error: this conflicts with another representation hint
133 | #[repr(C, C)] // zerocopy-derive conservatively treats these as conflicting reprs
| ^

error: must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:151:10
error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:140:10
|
151 | #[derive(IntoBytes)]
140 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:156:10
error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:150:10
|
156 | #[derive(IntoBytes)]
150 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout
error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:159:10
|
159 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:164:10
|
164 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:187:10
error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:172:10
|
172 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-msrv/struct.rs:195:10
|
187 | #[derive(IntoBytes)]
195 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: cannot derive `Unaligned` on type with alignment greater than 1
--> tests/ui-msrv/struct.rs:198:11
--> tests/ui-msrv/struct.rs:206:11
|
198 | #[repr(C, align(2))]
206 | #[repr(C, align(2))]
| ^^^^^

error: this conflicts with another representation hint
--> tests/ui-msrv/struct.rs:202:8
--> tests/ui-msrv/struct.rs:210:8
|
202 | #[repr(transparent, align(2))]
210 | #[repr(transparent, align(2))]
| ^^^^^^^^^^^

error: this conflicts with another representation hint
--> tests/ui-msrv/struct.rs:208:16
--> tests/ui-msrv/struct.rs:216:16
|
208 | #[repr(packed, align(2))]
216 | #[repr(packed, align(2))]
| ^^^^^

error: this conflicts with another representation hint
--> tests/ui-msrv/struct.rs:212:18
--> tests/ui-msrv/struct.rs:220:18
|
212 | #[repr(align(1), align(2))]
220 | #[repr(align(1), align(2))]
| ^^^^^

error: this conflicts with another representation hint
--> tests/ui-msrv/struct.rs:216:18
--> tests/ui-msrv/struct.rs:224:18
|
216 | #[repr(align(2), align(4))]
224 | #[repr(align(2), align(4))]
| ^^^^^

error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment
--> tests/ui-msrv/struct.rs:219:10
--> tests/ui-msrv/struct.rs:227:10
|
219 | #[derive(Unaligned)]
227 | #[derive(Unaligned)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment
--> tests/ui-msrv/struct.rs:222:10
--> tests/ui-msrv/struct.rs:230:10
|
222 | #[derive(Unaligned)]
230 | #[derive(Unaligned)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)

error: this conflicts with another representation hint
--> tests/ui-msrv/struct.rs:232:8
--> tests/ui-msrv/struct.rs:240:8
|
232 | #[repr(C, packed(2))]
240 | #[repr(C, packed(2))]
| ^

error[E0692]: transparent struct cannot have other repr hints
--> tests/ui-msrv/struct.rs:202:8
--> tests/ui-msrv/struct.rs:210:8
|
202 | #[repr(transparent, align(2))]
210 | #[repr(transparent, align(2))]
| ^^^^^^^^^^^ ^^^^^^^^

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
Expand Down
12 changes: 10 additions & 2 deletions zerocopy-derive/tests/ui-nightly/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,25 @@ struct IntoBytes5 {
a: u8,
}

// TODO(#1764): This currently compiles, but maybe it shouldn't.
// We don't emit a padding check unless there's a repr that can guarantee that
// fields don't overlap.
#[derive(IntoBytes)]
struct IntoBytes6 {
a: u8,
// Add a second field to avoid triggering the "repr(C) struct with one
// field" special case.
b: u8,
}

// TODO(#1764): This currently compiles, but maybe it shouldn't.
// We don't emit a padding check unless there's a repr that can guarantee that
// fields don't overlap. `repr(packed)` on its own doesn't guarantee this.
#[derive(IntoBytes)]
#[repr(packed(2))]
struct IntoBytes7 {
a: u8,
// Add a second field to avoid triggering the "repr(C) struct with one
// field" special case.
b: u8,
}

#[derive(IntoBytes)]
Expand Down
92 changes: 54 additions & 38 deletions zerocopy-derive/tests/ui-nightly/struct.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,97 +4,113 @@ error: this conflicts with another representation hint
133 | #[repr(C, C)] // zerocopy-derive conservatively treats these as conflicting reprs
| ^^^^

error: must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:151:10
error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:140:10
|
151 | #[derive(IntoBytes)]
140 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:156:10
error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:150:10
|
156 | #[derive(IntoBytes)]
150 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout
error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:159:10
|
159 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:164:10
|
164 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute or #[repr(packed)] in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:187:10
error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:172:10
|
172 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout
--> tests/ui-nightly/struct.rs:195:10
|
187 | #[derive(IntoBytes)]
195 | #[derive(IntoBytes)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)

error: cannot derive `Unaligned` on type with alignment greater than 1
--> tests/ui-nightly/struct.rs:198:11
--> tests/ui-nightly/struct.rs:206:11
|
198 | #[repr(C, align(2))]
206 | #[repr(C, align(2))]
| ^^^^^^^^

error: this conflicts with another representation hint
--> tests/ui-nightly/struct.rs:202:8
--> tests/ui-nightly/struct.rs:210:8
|
202 | #[repr(transparent, align(2))]
210 | #[repr(transparent, align(2))]
| ^^^^^^^^^^^

error: this conflicts with another representation hint
--> tests/ui-nightly/struct.rs:208:8
--> tests/ui-nightly/struct.rs:216:8
|
208 | #[repr(packed, align(2))]
216 | #[repr(packed, align(2))]
| ^^^^^^^^^^^^^^^^

error: this conflicts with another representation hint
--> tests/ui-nightly/struct.rs:212:8
--> tests/ui-nightly/struct.rs:220:8
|
212 | #[repr(align(1), align(2))]
220 | #[repr(align(1), align(2))]
| ^^^^^^^^^^^^^^^^^^

error: this conflicts with another representation hint
--> tests/ui-nightly/struct.rs:216:8
--> tests/ui-nightly/struct.rs:224:8
|
216 | #[repr(align(2), align(4))]
224 | #[repr(align(2), align(4))]
| ^^^^^^^^^^^^^^^^^^

error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment
--> tests/ui-nightly/struct.rs:219:10
--> tests/ui-nightly/struct.rs:227:10
|
219 | #[derive(Unaligned)]
227 | #[derive(Unaligned)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)

error: must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment
--> tests/ui-nightly/struct.rs:222:10
--> tests/ui-nightly/struct.rs:230:10
|
222 | #[derive(Unaligned)]
230 | #[derive(Unaligned)]
| ^^^^^^^^^
|
= note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info)

error: this conflicts with another representation hint
--> tests/ui-nightly/struct.rs:230:19
--> tests/ui-nightly/struct.rs:238:19
|
230 | #[repr(packed(2), C)]
238 | #[repr(packed(2), C)]
| ___________________^
231 | | #[derive(Unaligned)]
232 | | #[repr(C, packed(2))]
239 | | #[derive(Unaligned)]
240 | | #[repr(C, packed(2))]
| |________^

error[E0692]: transparent struct cannot have other repr hints
--> tests/ui-nightly/struct.rs:202:8
--> tests/ui-nightly/struct.rs:210:8
|
202 | #[repr(transparent, align(2))]
210 | #[repr(transparent, align(2))]
| ^^^^^^^^^^^ ^^^^^^^^

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
Expand Down Expand Up @@ -376,15 +392,15 @@ note: required by a bound in `macro_util::__size_of::size_of`
| ^^^^^ required by this bound in `size_of`

error[E0587]: type has conflicting packed and align representation hints
--> tests/ui-nightly/struct.rs:209:1
--> tests/ui-nightly/struct.rs:217:1
|
209 | struct Unaligned3;
217 | struct Unaligned3;
| ^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
--> tests/ui-nightly/struct.rs:182:28
--> tests/ui-nightly/struct.rs:190:28
|
182 | is_into_bytes_11::<IntoBytes11<AU16>>();
190 | is_into_bytes_11::<IntoBytes11<AU16>>();
| ^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16`, which is required by `IntoBytes11<AU16>: zerocopy::IntoBytes`
|
= note: Consider adding `#[derive(Unaligned)]` to `AU16`
Expand All @@ -399,13 +415,13 @@ error[E0277]: the trait bound `AU16: Unaligned` is not satisfied
I16<O>
and $N others
note: required for `IntoBytes11<AU16>` to implement `zerocopy::IntoBytes`
--> tests/ui-nightly/struct.rs:171:10
--> tests/ui-nightly/struct.rs:179:10
|
171 | #[derive(IntoBytes)]
179 | #[derive(IntoBytes)]
| ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
note: required by a bound in `is_into_bytes_11`
--> tests/ui-nightly/struct.rs:180:24
--> tests/ui-nightly/struct.rs:188:24
|
180 | fn is_into_bytes_11<T: IntoBytes>() {
188 | fn is_into_bytes_11<T: IntoBytes>() {
| ^^^^^^^^^ required by this bound in `is_into_bytes_11`
= note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
Loading

0 comments on commit 005d1d3

Please sign in to comment.