Skip to content

Commit

Permalink
[derive] Simplify code, remove obsolete features
Browse files Browse the repository at this point in the history
Clean up the implementation, especially in `fn impl_block`. Make the
following notable changes:
- Previously, `syn` didn't support parsing macro invocations in const
  generics without the `full` feature enabled. To avoid the compile-time
  overhead of that feature, we worked around it by constructing AST
  nodes manually. `syn` has since added support for this without
  requiring the `full` feature, so we make use of it.
- We used to need to split types into those that transatively depended
  upon type generics (like `[T; 2]`) and those that didn't (like
  `[u8; 2]`). We made a change in #119 that made this distinction
  irrelevant, but we never removed the code to perform the split. In
  this commit, we remove that code. That code was the only reason we
  needed to enable `syn`'s `visit` feature, so we are also able to
  remove that feature dependency.
  • Loading branch information
joshlf committed Sep 9, 2023
1 parent 0ff2dd1 commit 160c34f
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 200 deletions.
107 changes: 107 additions & 0 deletions tests/ui-stable/invalid-impls/invalid-impls.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied
--> tests/ui-stable/invalid-impls/invalid-impls.rs:22:37
|
22 | impl_or_verify!(T => FromZeroes for Foo<T>);
| ^^^^^^ the trait `zerocopy::FromZeroes` is not implemented for `T`
|
note: required for `Foo<T>` to implement `zerocopy::FromZeroes`
--> tests/ui-stable/invalid-impls/invalid-impls.rs:18:10
|
18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
| ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
note: required by a bound in `_::Subtrait`
--> tests/ui-stable/invalid-impls/../../../src/macros.rs
|
| trait Subtrait: $trait {}
| ^^^^^^ required by this bound in `Subtrait`
|
::: tests/ui-stable/invalid-impls/invalid-impls.rs:22:1
|
22 | impl_or_verify!(T => FromZeroes for Foo<T>);
| ------------------------------------------- in this macro invocation
= note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
22 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo<T>);
| ++++++++++++++++++++++

error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied
--> tests/ui-stable/invalid-impls/invalid-impls.rs:23:36
|
23 | impl_or_verify!(T => FromBytes for Foo<T>);
| ^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T`
|
note: required for `Foo<T>` to implement `zerocopy::FromBytes`
--> tests/ui-stable/invalid-impls/invalid-impls.rs:18:22
|
18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
| ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
note: required by a bound in `_::Subtrait`
--> tests/ui-stable/invalid-impls/../../../src/macros.rs
|
| trait Subtrait: $trait {}
| ^^^^^^ required by this bound in `Subtrait`
|
::: tests/ui-stable/invalid-impls/invalid-impls.rs:23:1
|
23 | impl_or_verify!(T => FromBytes for Foo<T>);
| ------------------------------------------ in this macro invocation
= note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
23 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo<T>);
| +++++++++++++++++++++

error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied
--> tests/ui-stable/invalid-impls/invalid-impls.rs:24:34
|
24 | impl_or_verify!(T => AsBytes for Foo<T>);
| ^^^^^^ the trait `zerocopy::AsBytes` is not implemented for `T`
|
note: required for `Foo<T>` to implement `zerocopy::AsBytes`
--> tests/ui-stable/invalid-impls/invalid-impls.rs:18:33
|
18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
| ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
note: required by a bound in `_::Subtrait`
--> tests/ui-stable/invalid-impls/../../../src/macros.rs
|
| trait Subtrait: $trait {}
| ^^^^^^ required by this bound in `Subtrait`
|
::: tests/ui-stable/invalid-impls/invalid-impls.rs:24:1
|
24 | impl_or_verify!(T => AsBytes for Foo<T>);
| ---------------------------------------- in this macro invocation
= note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
24 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo<T>);
| +++++++++++++++++++

error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied
--> tests/ui-stable/invalid-impls/invalid-impls.rs:25:36
|
25 | impl_or_verify!(T => Unaligned for Foo<T>);
| ^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T`
|
note: required for `Foo<T>` to implement `zerocopy::Unaligned`
--> tests/ui-stable/invalid-impls/invalid-impls.rs:18:42
|
18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)]
| ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
note: required by a bound in `_::Subtrait`
--> tests/ui-stable/invalid-impls/../../../src/macros.rs
|
| trait Subtrait: $trait {}
| ^^^^^^ required by this bound in `Subtrait`
|
::: tests/ui-stable/invalid-impls/invalid-impls.rs:25:1
|
25 | impl_or_verify!(T => Unaligned for Foo<T>);
| ------------------------------------------ in this macro invocation
= note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
25 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo<T>);
| +++++++++++++++++++++
2 changes: 1 addition & 1 deletion zerocopy-derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ proc-macro = true
[dependencies]
proc-macro2 = "1.0.1"
quote = "1.0.10"
syn = { version = "2", features = ["visit"] }
syn = "2.0.31"

[dev-dependencies]
rustversion = "1.0"
Expand Down
51 changes: 19 additions & 32 deletions zerocopy-derive/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use syn::{Data, DataEnum, DataStruct, DataUnion, Field, Fields, Type};
use syn::{Data, DataEnum, DataStruct, DataUnion, Type};

pub trait DataExt {
fn nested_types(&self) -> Vec<&Type>;
/// Extract the types of all fields. For enums, extract the types of fields
/// from each variant.
fn field_types(&self) -> Vec<&Type>;
}

impl DataExt for Data {
fn nested_types(&self) -> Vec<&Type> {
fn field_types(&self) -> Vec<&Type> {
match self {
Data::Struct(strc) => strc.nested_types(),
Data::Enum(enm) => enm.nested_types(),
Data::Union(un) => un.nested_types(),
Data::Struct(strc) => strc.field_types(),
Data::Enum(enm) => enm.field_types(),
Data::Union(un) => un.field_types(),
}
}
}

impl DataExt for DataStruct {
fn nested_types(&self) -> Vec<&Type> {
fields_to_types(&self.fields)
fn field_types(&self) -> Vec<&Type> {
self.fields.iter().map(|f| &f.ty).collect()
}
}

impl DataExt for DataEnum {
fn nested_types(&self) -> Vec<&Type> {
self.variants.iter().map(|var| fields_to_types(&var.fields)).fold(Vec::new(), |mut a, b| {
a.extend(b);
a
})
fn field_types(&self) -> Vec<&Type> {
self.variants.iter().map(|var| &var.fields).flatten().map(|f| &f.ty).collect()
}
}

impl DataExt for DataUnion {
fn field_types(&self) -> Vec<&Type> {
self.fields.named.iter().map(|f| &f.ty).collect()
}
}

Expand All @@ -39,24 +44,6 @@ pub trait EnumExt {

impl EnumExt for DataEnum {
fn is_c_like(&self) -> bool {
self.nested_types().is_empty()
self.field_types().is_empty()
}
}

impl DataExt for DataUnion {
fn nested_types(&self) -> Vec<&Type> {
field_iter_to_types(&self.fields.named)
}
}

fn fields_to_types(fields: &Fields) -> Vec<&Type> {
match fields {
Fields::Named(named) => field_iter_to_types(&named.named),
Fields::Unnamed(unnamed) => field_iter_to_types(&unnamed.unnamed),
Fields::Unit => Vec::new(),
}
}

fn field_iter_to_types<'a, I: IntoIterator<Item = &'a Field>>(fields: I) -> Vec<&'a Type> {
fields.into_iter().map(|f| &f.ty).collect()
}
Loading

0 comments on commit 160c34f

Please sign in to comment.