From 6250698b56bcd81d1d8898ec205ea3be3c0593fc Mon Sep 17 00:00:00 2001 From: Zachary Harrold Date: Mon, 26 Aug 2024 00:15:49 +1000 Subject: [PATCH] Added `on_unimplemented` Diagnostic for `IntoObserverSystem` (#14840) # Objective - Fixes #14658. ## Solution - Added `on_unimplemented` Diagnostic for `IntoObserverSystem` calling out argument ordering in a `note` - Added an example to the documentation on `App::observe` to provide some explanation to users. ## Testing - Ran CI locally - Deliberately introduced a parameter order error in the `ecs/observers.rs` example as a test. --- ## Showcase
Error Before ``` error[E0277]: the trait bound `{closure@examples/ecs/observers.rs:19:13: 22:37}: IntoObserverSystem<_, _, _>` is not satisfied --> examples/ecs/observers.rs:19:13 | 18 | .observe( | ------- required by a bound introduced by this call 19 | / |mines: Query<&Mine>, 20 | | trigger: Trigger, 21 | | index: Res, 22 | | mut commands: Commands| { ... | 34 | | } 35 | | }, | |_____________^ the trait `bevy::prelude::IntoSystem, (), _>` is not implemented for closure `{closure@examples/ecs/observers.rs:19:13: 22:37}`, which is required by `{closure@examples/ecs/observers.rs:19:13: 22:37}: IntoObserverSystem<_, _, _>` | = note: required for `{closure@examples/ecs/observers.rs:19:13: 22:37}` to implement `IntoObserverSystem<_, _, _>` note: required by a bound in `bevy::prelude::App::observe` --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:995:24 | 993 | pub fn observe( | ------- required by a bound in this associated function 994 | &mut self, 995 | observer: impl IntoObserverSystem, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::observe` For more information about this error, try `rustc --explain E0277`. error: could not compile `bevy` (example "observers") due to 1 previous error ```
Error After ``` error[E0277]: `{closure@examples/ecs/observers.rs:19:13: 22:37}` cannot become an `ObserverSystem` --> examples/ecs/observers.rs:19:13 | 18 | .observe( | ------- required by a bound introduced by this call 19 | / |mines: Query<&Mine>, 20 | | trigger: Trigger, 21 | | index: Res, 22 | | mut commands: Commands| { ... | 34 | | } 35 | | }, | |_____________^ the trait `IntoObserverSystem` is not implemented | = help: the trait `bevy::prelude::IntoSystem, (), _>` is not implemented for closure `{closure@examples/ecs/observers.rs:19:13: 22:37}`, which is required by `{closure@examples/ecs/observers.rs:19:13: 22:37}: IntoObserverSystem<_, _, _>` = note: for function `ObserverSystem`s, ensure the first argument is a `Trigger` and any subsequent ones are `SystemParam` = note: required for `{closure@examples/ecs/observers.rs:19:13: 22:37}` to implement `IntoObserverSystem<_, _, _>` note: required by a bound in `bevy::prelude::App::observe` --> C:\Users\Zac\Documents\GitHub\bevy\crates\bevy_app\src\app.rs:1025:24 | 1023 | pub fn observe( | ------- required by a bound in this associated function 1024 | &mut self, 1025 | observer: impl IntoObserverSystem, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::observe` For more information about this error, try `rustc --explain E0277`. error: could not compile `bevy` (example "observers") due to 1 previous error ```
--- crates/bevy_app/src/app.rs | 30 +++++++++++++++++++ crates/bevy_ecs/src/system/observer_system.rs | 5 ++++ 2 files changed, 35 insertions(+) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index f79bc6d52a55e..07a29800f93df 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -990,6 +990,36 @@ impl App { } /// Spawns an [`Observer`] entity, which will watch for and respond to the given event. + /// + /// # Examples + /// + /// ```rust + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # use bevy_utils::default; + /// # + /// # let mut app = App::new(); + /// # + /// # #[derive(Event)] + /// # struct Party { + /// # friends_allowed: bool, + /// # }; + /// # + /// # #[derive(Event)] + /// # struct Invite; + /// # + /// # #[derive(Component)] + /// # struct Friend; + /// # + /// // An observer system can be any system where the first parameter is a trigger + /// app.observe(|trigger: Trigger, friends: Query>, mut commands: Commands| { + /// if trigger.event().friends_allowed { + /// for friend in friends.iter() { + /// commands.trigger_targets(Invite, friend); + /// } + /// } + /// }); + /// ``` pub fn observe( &mut self, observer: impl IntoObserverSystem, diff --git a/crates/bevy_ecs/src/system/observer_system.rs b/crates/bevy_ecs/src/system/observer_system.rs index c5a04f25dd4eb..28ea902b1aa4d 100644 --- a/crates/bevy_ecs/src/system/observer_system.rs +++ b/crates/bevy_ecs/src/system/observer_system.rs @@ -25,6 +25,11 @@ impl< } /// Implemented for systems that convert into [`ObserverSystem`]. +#[diagnostic::on_unimplemented( + message = "`{Self}` cannot become an `ObserverSystem`", + label = "the trait `IntoObserverSystem` is not implemented", + note = "for function `ObserverSystem`s, ensure the first argument is a `Trigger` and any subsequent ones are `SystemParam`" +)] pub trait IntoObserverSystem: Send + 'static { /// The type of [`System`] that this instance converts into. type System: ObserverSystem;