swarm-derive/: Remove support for ignoring fields on struct (#2842)

With the removal of `NetworkBehaviourEventProcess` there is no more need for
ignoring fields.
This commit is contained in:
Max Inden
2022-08-29 07:39:47 +02:00
committed by GitHub
parent 247b5536d4
commit 6855ab943b
5 changed files with 40 additions and 135 deletions

View File

@ -85,11 +85,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
struct MyBehaviour { struct MyBehaviour {
floodsub: Floodsub, floodsub: Floodsub,
mdns: Mdns, mdns: Mdns,
// Struct fields which do not implement NetworkBehaviour need to be ignored
#[behaviour(ignore)]
#[allow(dead_code)]
ignored_member: bool,
} }
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
@ -117,7 +112,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
let mut behaviour = MyBehaviour { let mut behaviour = MyBehaviour {
floodsub: Floodsub::new(local_peer_id), floodsub: Floodsub::new(local_peer_id),
mdns, mdns,
ignored_member: false,
}; };
behaviour.floodsub.subscribe(floodsub_topic.clone()); behaviour.floodsub.subscribe(floodsub_topic.clone());

View File

@ -8,6 +8,11 @@
[PR 2840]: https://github.com/libp2p/rust-libp2p/pull/2840 [PR 2840]: https://github.com/libp2p/rust-libp2p/pull/2840
[PR 2841]: https://github.com/libp2p/rust-libp2p/pull/2841 [PR 2841]: https://github.com/libp2p/rust-libp2p/pull/2841
- Remove support for non-`NetworkBehaviour` fields on main `struct` via `#[behaviour(ignore)]`. See
[PR 2842].
[PR 2842]: https://github.com/libp2p/rust-libp2p/pull/2842
# 0.29.0 # 0.29.0
- Generate `NetworkBehaviour::OutEvent` if not provided through `#[behaviour(out_event = - Generate `NetworkBehaviour::OutEvent` if not provided through `#[behaviour(out_event =

View File

@ -70,13 +70,6 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
quote! {<#(#lf,)* #(#tp,)* #(#cst,)*>} quote! {<#(#lf,)* #(#tp,)* #(#cst,)*>}
}; };
// The fields of the struct we are interested in (no ignored fields).
let data_struct_fields = data_struct
.fields
.iter()
.filter(|f| !is_ignored(f))
.collect::<Vec<_>>();
let (out_event_name, out_event_definition, out_event_from_clauses) = { let (out_event_name, out_event_definition, out_event_from_clauses) = {
// If we find a `#[behaviour(out_event = "Foo")]` attribute on the // If we find a `#[behaviour(out_event = "Foo")]` attribute on the
// struct, we set `Foo` as the out event. If not, the `OutEvent` is // struct, we set `Foo` as the out event. If not, the `OutEvent` is
@ -102,7 +95,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// User provided `OutEvent`. // User provided `OutEvent`.
Some(name) => { Some(name) => {
let definition = None; let definition = None;
let from_clauses = data_struct_fields let from_clauses = data_struct
.fields
.iter() .iter()
.map(|field| { .map(|field| {
let ty = &field.ty; let ty = &field.ty;
@ -115,7 +109,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
None => { None => {
let name: syn::Type = syn::parse_str(&(ast.ident.to_string() + "Event")).unwrap(); let name: syn::Type = syn::parse_str(&(ast.ident.to_string() + "Event")).unwrap();
let definition = { let definition = {
let fields = data_struct_fields let fields = data_struct
.fields
.iter() .iter()
.map(|field| { .map(|field| {
let variant: syn::Variant = syn::parse_str( let variant: syn::Variant = syn::parse_str(
@ -152,7 +147,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the `where ...` clause of the trait implementation. // Build the `where ...` clause of the trait implementation.
let where_clause = { let where_clause = {
let additional = data_struct_fields let additional = data_struct
.fields
.iter() .iter()
.map(|field| { .map(|field| {
let ty = &field.ty; let ty = &field.ty;
@ -174,7 +170,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `addresses_of_peer()`. // Build the list of statements to put in the body of `addresses_of_peer()`.
let addresses_of_peer_stmts = { let addresses_of_peer_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
.map(move |(field_n, field)| match field.ident { .map(move |(field_n, field)| match field.ident {
@ -185,7 +182,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_connection_established()`. // Build the list of statements to put in the body of `inject_connection_established()`.
let inject_connection_established_stmts = { let inject_connection_established_stmts = {
data_struct_fields.iter().enumerate().map(move |(field_n, field)| { data_struct.fields.iter().enumerate().map(move |(field_n, field)| {
match field.ident { match field.ident {
Some(ref i) => quote!{ self.#i.inject_connection_established(peer_id, connection_id, endpoint, errors, other_established); }, Some(ref i) => quote!{ self.#i.inject_connection_established(peer_id, connection_id, endpoint, errors, other_established); },
None => quote!{ self.#field_n.inject_connection_established(peer_id, connection_id, endpoint, errors, other_established); }, None => quote!{ self.#field_n.inject_connection_established(peer_id, connection_id, endpoint, errors, other_established); },
@ -195,7 +192,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_address_change()`. // Build the list of statements to put in the body of `inject_address_change()`.
let inject_address_change_stmts = { let inject_address_change_stmts = {
data_struct_fields.iter().enumerate().map(move |(field_n, field)| { data_struct.fields.iter().enumerate().map(move |(field_n, field)| {
match field.ident { match field.ident {
Some(ref i) => quote!{ self.#i.inject_address_change(peer_id, connection_id, old, new); }, Some(ref i) => quote!{ self.#i.inject_address_change(peer_id, connection_id, old, new); },
None => quote!{ self.#field_n.inject_address_change(peer_id, connection_id, old, new); }, None => quote!{ self.#field_n.inject_address_change(peer_id, connection_id, old, new); },
@ -205,7 +202,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_connection_closed()`. // Build the list of statements to put in the body of `inject_connection_closed()`.
let inject_connection_closed_stmts = { let inject_connection_closed_stmts = {
data_struct_fields data_struct.fields
.iter() .iter()
.enumerate() .enumerate()
// The outmost handler belongs to the last behaviour. // The outmost handler belongs to the last behaviour.
@ -234,7 +231,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_dial_failure()`. // Build the list of statements to put in the body of `inject_dial_failure()`.
let inject_dial_failure_stmts = { let inject_dial_failure_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
// The outmost handler belongs to the last behaviour. // The outmost handler belongs to the last behaviour.
@ -268,7 +266,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_listen_failure()`. // Build the list of statements to put in the body of `inject_listen_failure()`.
let inject_listen_failure_stmts = { let inject_listen_failure_stmts = {
data_struct_fields data_struct.fields
.iter() .iter()
.enumerate() .enumerate()
.rev() .rev()
@ -296,7 +294,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_new_listener()`. // Build the list of statements to put in the body of `inject_new_listener()`.
let inject_new_listener_stmts = { let inject_new_listener_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
.map(move |(field_n, field)| match field.ident { .map(move |(field_n, field)| match field.ident {
@ -307,7 +306,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_new_listen_addr()`. // Build the list of statements to put in the body of `inject_new_listen_addr()`.
let inject_new_listen_addr_stmts = { let inject_new_listen_addr_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
.map(move |(field_n, field)| match field.ident { .map(move |(field_n, field)| match field.ident {
@ -318,7 +318,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_expired_listen_addr()`. // Build the list of statements to put in the body of `inject_expired_listen_addr()`.
let inject_expired_listen_addr_stmts = { let inject_expired_listen_addr_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
.map(move |(field_n, field)| match field.ident { .map(move |(field_n, field)| match field.ident {
@ -329,7 +330,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_new_external_addr()`. // Build the list of statements to put in the body of `inject_new_external_addr()`.
let inject_new_external_addr_stmts = { let inject_new_external_addr_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
.map(move |(field_n, field)| match field.ident { .map(move |(field_n, field)| match field.ident {
@ -340,7 +342,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_expired_external_addr()`. // Build the list of statements to put in the body of `inject_expired_external_addr()`.
let inject_expired_external_addr_stmts = { let inject_expired_external_addr_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
.map(move |(field_n, field)| match field.ident { .map(move |(field_n, field)| match field.ident {
@ -351,7 +354,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_listener_error()`. // Build the list of statements to put in the body of `inject_listener_error()`.
let inject_listener_error_stmts = { let inject_listener_error_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
.map(move |(field_n, field)| match field.ident { .map(move |(field_n, field)| match field.ident {
@ -362,7 +366,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Build the list of statements to put in the body of `inject_listener_closed()`. // Build the list of statements to put in the body of `inject_listener_closed()`.
let inject_listener_closed_stmts = { let inject_listener_closed_stmts = {
data_struct_fields data_struct
.fields
.iter() .iter()
.enumerate() .enumerate()
.map(move |(field_n, field)| match field.ident { .map(move |(field_n, field)| match field.ident {
@ -375,14 +380,14 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// //
// The event type is a construction of nested `#either_ident`s of the events of the children. // The event type is a construction of nested `#either_ident`s of the events of the children.
// We call `inject_event` on the corresponding child. // We call `inject_event` on the corresponding child.
let inject_node_event_stmts = data_struct_fields.iter().enumerate().enumerate().map(|(enum_n, (field_n, field))| { let inject_node_event_stmts = data_struct.fields.iter().enumerate().enumerate().map(|(enum_n, (field_n, field))| {
let mut elem = if enum_n != 0 { let mut elem = if enum_n != 0 {
quote!{ #either_ident::Second(ev) } quote!{ #either_ident::Second(ev) }
} else { } else {
quote!{ ev } quote!{ ev }
}; };
for _ in 0 .. data_struct_fields.len() - 1 - enum_n { for _ in 0 .. data_struct.fields.len() - 1 - enum_n {
elem = quote!{ #either_ident::First(#elem) }; elem = quote!{ #either_ident::First(#elem) };
} }
@ -395,7 +400,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// The [`ConnectionHandler`] associated type. // The [`ConnectionHandler`] associated type.
let connection_handler_ty = { let connection_handler_ty = {
let mut ph_ty = None; let mut ph_ty = None;
for field in data_struct_fields.iter() { for field in data_struct.fields.iter() {
let ty = &field.ty; let ty = &field.ty;
let field_info = quote! { <#ty as #trait_to_impl>::ConnectionHandler }; let field_info = quote! { <#ty as #trait_to_impl>::ConnectionHandler };
match ph_ty { match ph_ty {
@ -412,7 +417,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
let new_handler = { let new_handler = {
let mut out_handler = None; let mut out_handler = None;
for (field_n, field) in data_struct_fields.iter().enumerate() { for (field_n, field) in data_struct.fields.iter().enumerate() {
let field_name = match field.ident { let field_name = match field.ident {
Some(ref i) => quote! { self.#i }, Some(ref i) => quote! { self.#i },
None => quote! { self.#field_n }, None => quote! { self.#field_n },
@ -436,7 +441,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// List of statements to put in `poll()`. // List of statements to put in `poll()`.
// //
// We poll each child one by one and wrap around the output. // We poll each child one by one and wrap around the output.
let poll_stmts = data_struct_fields.iter().enumerate().map(|(field_n, field)| { let poll_stmts = data_struct.fields.iter().enumerate().map(|(field_n, field)| {
let field = field let field = field
.ident .ident
.clone() .clone()
@ -447,7 +452,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
} else { } else {
quote!{ event } quote!{ event }
}; };
for _ in 0 .. data_struct_fields.len() - 1 - field_n { for _ in 0 .. data_struct.fields.len() - 1 - field_n {
wrapped_event = quote!{ #either_ident::First(#wrapped_event) }; wrapped_event = quote!{ #either_ident::First(#wrapped_event) };
} }
@ -458,7 +463,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
let provided_handler_and_new_handlers = { let provided_handler_and_new_handlers = {
let mut out_handler = None; let mut out_handler = None;
for (f_n, f) in data_struct_fields.iter().enumerate() { for (f_n, f) in data_struct.fields.iter().enumerate() {
let f_name = match f.ident { let f_name = match f.ident {
Some(ref i) => quote! { self.#i }, Some(ref i) => quote! { self.#i },
None => quote! { self.#f_n }, None => quote! { self.#f_n },
@ -637,19 +642,3 @@ fn get_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::NestedMeta>> {
None None
} }
} }
/// Returns true if a field is marked as ignored by the user.
fn is_ignored(field: &syn::Field) -> bool {
for meta_items in field.attrs.iter().filter_map(get_meta_items) {
for meta_item in meta_items {
match meta_item {
syn::NestedMeta::Meta(syn::Meta::Path(ref m)) if m.is_ident("ignore") => {
return true;
}
_ => (),
}
}
}
false
}

View File

@ -83,8 +83,6 @@ fn three_fields() {
ping: libp2p::ping::Ping, ping: libp2p::ping::Ping,
identify: libp2p::identify::Identify, identify: libp2p::identify::Identify,
kad: libp2p::kad::Kademlia<libp2p::kad::record::store::MemoryStore>, kad: libp2p::kad::Kademlia<libp2p::kad::record::store::MemoryStore>,
#[behaviour(ignore)]
foo: String,
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -103,30 +101,6 @@ fn three_fields() {
} }
} }
#[test]
fn three_fields_non_last_ignored() {
#[allow(dead_code)]
#[derive(NetworkBehaviour)]
struct Foo {
ping: libp2p::ping::Ping,
#[behaviour(ignore)]
identify: String,
kad: libp2p::kad::Kademlia<libp2p::kad::record::store::MemoryStore>,
}
#[allow(dead_code)]
#[allow(unreachable_code)]
fn foo() {
let _out_event: <Foo as NetworkBehaviour>::OutEvent = unimplemented!();
match _out_event {
FooEvent::Ping(libp2p::ping::Event { .. }) => {}
FooEvent::Kad(event) => {
let _: libp2p::kad::KademliaEvent = event;
}
}
}
}
#[test] #[test]
fn custom_event() { fn custom_event() {
#[allow(dead_code)] #[allow(dead_code)]
@ -359,28 +333,6 @@ fn custom_event_with_either() {
} }
} }
#[test]
fn mixed_field_order() {
struct Foo {}
#[derive(NetworkBehaviour)]
pub struct Behaviour {
#[behaviour(ignore)]
_foo: Foo,
_ping: libp2p::ping::Ping,
#[behaviour(ignore)]
_foo2: Foo,
_identify: libp2p::identify::Identify,
#[behaviour(ignore)]
_foo3: Foo,
}
#[allow(dead_code)]
fn behaviour() {
require_net_behaviour::<Behaviour>();
}
}
#[test] #[test]
fn generated_out_event_derive_debug() { fn generated_out_event_derive_debug() {
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -117,41 +117,6 @@ pub(crate) type THandlerOutEvent<THandler> =
/// } /// }
/// } /// }
/// ``` /// ```
///
/// Struct members that don't implement [`NetworkBehaviour`] must be annotated with
/// `#[behaviour(ignore)]`.
///
/// ``` rust
/// # use libp2p::identify::{Identify, IdentifyEvent};
/// # use libp2p::ping::{Ping, PingEvent};
/// # use libp2p::NetworkBehaviour;
/// #[derive(NetworkBehaviour)]
/// #[behaviour(out_event = "Event")]
/// struct MyBehaviour {
/// identify: Identify,
/// ping: Ping,
///
/// #[behaviour(ignore)]
/// some_string: String,
/// }
/// #
/// # enum Event {
/// # Identify(IdentifyEvent),
/// # Ping(PingEvent),
/// # }
/// #
/// # impl From<IdentifyEvent> for Event {
/// # fn from(event: IdentifyEvent) -> Self {
/// # Self::Identify(event)
/// # }
/// # }
/// #
/// # impl From<PingEvent> for Event {
/// # fn from(event: PingEvent) -> Self {
/// # Self::Ping(event)
/// # }
/// # }
/// ```
pub trait NetworkBehaviour: 'static { pub trait NetworkBehaviour: 'static {
/// Handler for all the protocols the network behaviour supports. /// Handler for all the protocols the network behaviour supports.
type ConnectionHandler: IntoConnectionHandler; type ConnectionHandler: IntoConnectionHandler;