From c6ba3d31cf0611eaeb227326753c503a2c7123da Mon Sep 17 00:00:00 2001 From: SpecificProtagonist Date: Tue, 1 Jul 2025 05:20:54 +0200 Subject: [PATCH] EntityEvent derive: Fix silent error (#19894) # Objective The `EntityEvent` derive macro only parsed the first `entity_event` attr, resulting in the following event having auto propagation silently turned off: ```rust #[derive(Event, EntityEvent)] #[entity_event(traversal = &'static ChildOf)] #[entity_event(auto_propagate)] struct MyEvent; ``` This should either fail to compile or be parsed correctly. ## Solution Parse all `entity_event`. ## Testing Cargo expand the snippet above. I haven't added an extra test for this. --- crates/bevy_ecs/macros/src/component.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/macros/src/component.rs b/crates/bevy_ecs/macros/src/component.rs index 040c1b26b6..8a78355a60 100644 --- a/crates/bevy_ecs/macros/src/component.rs +++ b/crates/bevy_ecs/macros/src/component.rs @@ -40,19 +40,26 @@ pub fn derive_entity_event(input: TokenStream) -> TokenStream { let mut traversal: Type = parse_quote!(()); let bevy_ecs_path: Path = crate::bevy_ecs_path(); + let mut processed_attrs = Vec::new(); + ast.generics .make_where_clause() .predicates .push(parse_quote! { Self: Send + Sync + 'static }); - if let Some(attr) = ast.attrs.iter().find(|attr| attr.path().is_ident(EVENT)) { + for attr in ast.attrs.iter().filter(|attr| attr.path().is_ident(EVENT)) { if let Err(e) = attr.parse_nested_meta(|meta| match meta.path.get_ident() { + Some(ident) if processed_attrs.iter().any(|i| ident == i) => { + Err(meta.error(format!("duplicate attribute: {ident}"))) + } Some(ident) if ident == AUTO_PROPAGATE => { auto_propagate = true; + processed_attrs.push(AUTO_PROPAGATE); Ok(()) } Some(ident) if ident == TRAVERSAL => { traversal = meta.value()?.parse()?; + processed_attrs.push(TRAVERSAL); Ok(()) } Some(ident) => Err(meta.error(format!("unsupported attribute: {ident}"))),