-
-
Couldn't load subscription status.
- Fork 4.2k
Description
What problem does this solve or what need does it fill?
There is an unsound interaction between EntityRef::get_components #13375 and declaring resource access from queries #16843 where safe code can get read access to a resource without checking for conflicts. If a QueryData requests read access to a resource, then a system like
fn system(query: Query<EntityRef>, res: ResMut<SomeResource>) {
query.single().get_components::<QueryDataUsingSomeResource>();
}will create a &SomeResource during get_components() at the same time as the &mut SomeResource from ResMut, resulting in UB.
The bad SAFETY comment is in EntityRef::get_components:
bevy/crates/bevy_ecs/src/world/entity_ref.rs
Line 294 in 6bb0473
| // - We have read-only access to all components of this entity. |
While we do have access to all components, the query may also require resource access that
EntityRef does not have.
What solution would you like?
Create a new unsafe trait for a WorldQuery that does no resource access, and bound the get_components methods by that trait.
Additional context
This is difficult to actually trigger at the moment, so may not be urgent to fix. It requires a custom QueryData impl, as the only in-engine use of a WorldQuery requesting resource access is AssetChanged<A>, a QueryFilter.
If we start expanding the cases where queries access data outside of the current entity, particularly for relations, then this may become more important.