Skip to content

Commit 25cb339

Browse files
authored
Don't ignore default query filters for EntityRef or EntityMut (#20163)
# Objective Don't ignore default query filters for `EntityRef` or `EntityMut`. Currently, `Query<EntityRef>` will include entities with a `Disabled` component, even though queries like `Query<()>` or `Query<Entity>` would not. This was noticed in #19711 (comment). ## Solution Change `Access::contains` to completely ignore read access and just look at filters and archetypal access. Filters covers `With`, `Without`, `&`, and `&mut`, while archetypal covers `Has` and `Allows`. Note that `Option<&Disabled>` will no longer count as a use of `Disabled`, though.
1 parent 9e1e8bc commit 25cb339

File tree

2 files changed

+26
-13
lines changed

2 files changed

+26
-13
lines changed

crates/bevy_ecs/src/entity_disabling.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ mod tests {
205205

206206
use super::*;
207207
use crate::{
208-
prelude::World,
208+
prelude::{EntityMut, EntityRef, World},
209209
query::{Has, With},
210210
};
211211
use alloc::{vec, vec::Vec};
@@ -278,30 +278,42 @@ mod tests {
278278
let mut world = World::new();
279279
world.register_disabling_component::<CustomDisabled>();
280280

281+
// Use powers of two so we can uniquely identify the set of matching archetypes from the count.
281282
world.spawn_empty();
282-
world.spawn(Disabled);
283-
world.spawn(CustomDisabled);
284-
world.spawn((Disabled, CustomDisabled));
283+
world.spawn_batch((0..2).map(|_| Disabled));
284+
world.spawn_batch((0..4).map(|_| CustomDisabled));
285+
world.spawn_batch((0..8).map(|_| (Disabled, CustomDisabled)));
285286

286287
let mut query = world.query::<()>();
287288
assert_eq!(1, query.iter(&world).count());
288289

289-
let mut query = world.query_filtered::<(), With<Disabled>>();
290+
let mut query = world.query::<EntityRef>();
290291
assert_eq!(1, query.iter(&world).count());
291292

292-
let mut query = world.query::<Has<Disabled>>();
293+
let mut query = world.query::<EntityMut>();
294+
assert_eq!(1, query.iter(&world).count());
295+
296+
let mut query = world.query_filtered::<(), With<Disabled>>();
293297
assert_eq!(2, query.iter(&world).count());
294298

299+
let mut query = world.query::<Has<Disabled>>();
300+
assert_eq!(3, query.iter(&world).count());
301+
295302
let mut query = world.query_filtered::<(), With<CustomDisabled>>();
296-
assert_eq!(1, query.iter(&world).count());
303+
assert_eq!(4, query.iter(&world).count());
297304

298305
let mut query = world.query::<Has<CustomDisabled>>();
299-
assert_eq!(2, query.iter(&world).count());
306+
assert_eq!(5, query.iter(&world).count());
300307

301308
let mut query = world.query_filtered::<(), (With<Disabled>, With<CustomDisabled>)>();
302-
assert_eq!(1, query.iter(&world).count());
309+
assert_eq!(8, query.iter(&world).count());
303310

304311
let mut query = world.query::<(Has<Disabled>, Has<CustomDisabled>)>();
305-
assert_eq!(4, query.iter(&world).count());
312+
assert_eq!(15, query.iter(&world).count());
313+
314+
// This seems like it ought to count as a mention of `Disabled`, but it does not.
315+
// We don't consider read access, since that would count `EntityRef` as a mention of *all* components.
316+
let mut query = world.query::<Option<&Disabled>>();
317+
assert_eq!(1, query.iter(&world).count());
306318
}
307319
}

crates/bevy_ecs/src/query/access.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,10 +1225,11 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
12251225
.flat_map(|f| f.without.ones().map(T::get_sparse_set_index))
12261226
}
12271227

1228-
/// Returns true if the index is used by this `FilteredAccess` in any way
1228+
/// Returns true if the index is used by this `FilteredAccess` in filters or archetypal access.
1229+
/// This includes most ways to access a component, but notably excludes `EntityRef` and `EntityMut`
1230+
/// along with anything inside `Option<T>`.
12291231
pub fn contains(&self, index: T) -> bool {
1230-
self.access().has_component_read(index.clone())
1231-
|| self.access().has_archetypal(index.clone())
1232+
self.access().has_archetypal(index.clone())
12321233
|| self.filter_sets.iter().any(|f| {
12331234
f.with.contains(index.sparse_set_index())
12341235
|| f.without.contains(index.sparse_set_index())

0 commit comments

Comments
 (0)