mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 22:20:20 +00:00
Make Observer::with_event (and other variants) unsafe (#13954)
# Objective `with_event` will result in unsafe casting of event data of the given type to the type expected by the Observer system. This is inherently unsafe. ## Solution Flag `Observer::with_event` and `ObserverDescriptor::with_events` as unsafe. This will not affect normal workflows as `with_event` is intended for very specific (largely internal) use cases. This _should_ be backported to 0.14 before release. --- ## Changelog - `Observer::with_event` is now unsafe. - Rename `ObserverDescriptor::with_triggers` to `ObserverDescriptor::with_events` and make it unsafe.
This commit is contained in:
parent
841df150cc
commit
0daa6c510b
2 changed files with 18 additions and 8 deletions
|
@ -72,9 +72,12 @@ pub struct ObserverDescriptor {
|
|||
}
|
||||
|
||||
impl ObserverDescriptor {
|
||||
/// Add the given `triggers` to the descriptor.
|
||||
pub fn with_triggers(mut self, triggers: Vec<ComponentId>) -> Self {
|
||||
self.events = triggers;
|
||||
/// Add the given `events` to the descriptor.
|
||||
/// # Safety
|
||||
/// The type of each [`ComponentId`] in `events` _must_ match the actual value
|
||||
/// of the event passed into the observer.
|
||||
pub unsafe fn with_events(mut self, events: Vec<ComponentId>) -> Self {
|
||||
self.events = events;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -518,8 +521,11 @@ mod tests {
|
|||
world.init_resource::<R>();
|
||||
let on_remove = world.init_component::<OnRemove>();
|
||||
world.spawn(
|
||||
Observer::new(|_: Trigger<OnAdd, A>, mut res: ResMut<R>| res.0 += 1)
|
||||
.with_event(on_remove),
|
||||
// SAFETY: OnAdd and OnRemove are both unit types, so this is safe
|
||||
unsafe {
|
||||
Observer::new(|_: Trigger<OnAdd, A>, mut res: ResMut<R>| res.0 += 1)
|
||||
.with_event(on_remove)
|
||||
},
|
||||
);
|
||||
|
||||
let entity = world.spawn(A).id();
|
||||
|
@ -641,7 +647,8 @@ mod tests {
|
|||
let event_a = world.init_component::<EventA>();
|
||||
|
||||
world.spawn(ObserverState {
|
||||
descriptor: ObserverDescriptor::default().with_triggers(vec![event_a]),
|
||||
// SAFETY: we registered `event_a` above and it matches the type of TriggerA
|
||||
descriptor: unsafe { ObserverDescriptor::default().with_events(vec![event_a]) },
|
||||
runner: |mut world, _trigger, _ptr| {
|
||||
world.resource_mut::<R>().0 += 1;
|
||||
},
|
||||
|
@ -649,7 +656,7 @@ mod tests {
|
|||
});
|
||||
|
||||
world.commands().add(
|
||||
// SAFETY: we registered `trigger` above and it matches the type of TriggerA
|
||||
// SAFETY: we registered `event_a` above and it matches the type of TriggerA
|
||||
unsafe { EmitDynamicTrigger::new_with_id(event_a, EventA, ()) },
|
||||
);
|
||||
world.flush();
|
||||
|
|
|
@ -298,7 +298,10 @@ impl<E: Event, B: Bundle> Observer<E, B> {
|
|||
|
||||
/// Observe the given `event`. This will cause the [`Observer`] to run whenever an event with the given [`ComponentId`]
|
||||
/// is triggered.
|
||||
pub fn with_event(mut self, event: ComponentId) -> Self {
|
||||
/// # Safety
|
||||
/// The type of the `event` [`ComponentId`] _must_ match the actual value
|
||||
/// of the event passed into the observer system.
|
||||
pub unsafe fn with_event(mut self, event: ComponentId) -> Self {
|
||||
self.descriptor.events.push(event);
|
||||
self
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue