Skip to content

Commit 3fba34c

Browse files
authored
Require read-only queries in QueryState::par_iter (#8832)
# Objective The method `QueryState::par_iter` does not currently force the query to be read-only. This means you can unsoundly mutate a world through an immutable reference in safe code. ```rust fn bad_system(world: &World, mut query: Local<QueryState<&mut T>>) { query.par_iter(world).for_each_mut(|mut x| *x = unsoundness); } ``` ## Solution Use read-only versions of the `WorldQuery` types. --- ## Migration Guide The function `QueryState::par_iter` now forces any world accesses to be read-only, similar to how `QueryState::iter` works. Any code that previously mutated the world using this method was *unsound*. If you need to mutate the world, use `par_iter_mut` instead.
1 parent c475e27 commit 3fba34c

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

crates/bevy_ecs/src/query/state.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,11 +865,14 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
865865
///
866866
/// [`par_iter_mut`]: Self::par_iter_mut
867867
#[inline]
868-
pub fn par_iter<'w, 's>(&'s mut self, world: &'w World) -> QueryParIter<'w, 's, Q, F> {
868+
pub fn par_iter<'w, 's>(
869+
&'s mut self,
870+
world: &'w World,
871+
) -> QueryParIter<'w, 's, Q::ReadOnly, F::ReadOnly> {
869872
self.update_archetypes(world);
870873
QueryParIter {
871874
world,
872-
state: self,
875+
state: self.as_readonly(),
873876
last_run: world.last_change_tick(),
874877
this_run: world.read_change_tick(),
875878
batching_strategy: BatchingStrategy::new(),

0 commit comments

Comments
 (0)