`Observer`s' underlying system state can change after they have been spawned
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## Bevy version and features
https://github.com/bevyengine/bevy/commit/69745d40e594fb34a99507e2f0be2385711e46a6 but also likely 0.16.1
## What you did
```rs
use bevy_ecs::{entity_disabling::Internal, prelude::*, system::IntoObserverSystem};
fn main() {
#[derive(EntityEvent)]
struct Ev;
struct Local1(&'static i32);
impl Default for Local1 {
fn default() -> Self {
Local1(&0)
}
}
#[derive(Default)]
struct Local2(usize);
fn bad_observer(_: On, local: Local) {
println!("{}", local.0);
}
let mut world = World::new();
world.add_observer(bad_observer);
let mut s = IntoObserverSystem::into_system(|_: On, _: Local| {});
s.initialize(&mut world);
*world
.query_filtered::<&mut Observer, With>()
.single_mut(&mut world)
.unwrap() = Observer::new(s);
world.trigger(Ev);
}
```
## What went wrong
This causes a segfault in release mode, because the original system is run with the new system's local, effectively transmuting the local's type.
In debug mode it fails the following assertion:
https://github.com/bevyengine/bevy/blob/69745d40e594fb34a99507e2f0be2385711e46a6/crates/bevy_ecs/src/observer/runner.rs#L56
This is similar to #20736 in that both are caused by the `Observer` component being replaced, however it's different in that it doesn't need the observer to be currenlty running, so a fix that just temporarily moves out the system state while running won't fix this issue too.
Contributor guide
Assessment
This issue has not been assessed yet.