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:
|
// - 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.
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 aQueryDatarequests read access to a resource, then a system likewill create a
&SomeResourceduringget_components()at the same time as the&mut SomeResourcefromResMut, resulting in UB.The bad
SAFETYcomment is inEntityRef::get_components:bevy/crates/bevy_ecs/src/world/entity_ref.rs
Line 294 in 6bb0473
While we do have access to all components, the query may also require resource access that
EntityRefdoes not have.What solution would you like?
Create a new
unsafe traitfor aWorldQuerythat does no resource access, and bound theget_componentsmethods 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
QueryDataimpl, as the only in-engine use of aWorldQueryrequesting resource access isAssetChanged<A>, aQueryFilter.If we start expanding the cases where queries access data outside of the current entity, particularly for relations, then this may become more important.