From b39a683fe7ee54cea048c1b73c15ce1c2d33c406 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:36:57 -0400 Subject: [PATCH] Simplify the implementation by ignoring *all* read access. --- crates/bevy_ecs/src/entity_disabling.rs | 29 +++---------------------- crates/bevy_ecs/src/query/access.rs | 18 ++++----------- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/crates/bevy_ecs/src/entity_disabling.rs b/crates/bevy_ecs/src/entity_disabling.rs index c0d1bde7f1..41a461b77e 100644 --- a/crates/bevy_ecs/src/entity_disabling.rs +++ b/crates/bevy_ecs/src/entity_disabling.rs @@ -207,7 +207,6 @@ mod tests { use crate::{ prelude::{EntityMut, EntityRef, World}, query::{Has, With}, - world::{EntityMutExcept, EntityRefExcept}, }; use alloc::{vec, vec::Vec}; @@ -294,24 +293,12 @@ mod tests { let mut query = world.query::(); assert_eq!(1, query.iter(&world).count()); - let mut query = world.query::>(); - assert_eq!(1, query.iter(&world).count()); - - let mut query = world.query::>(); - assert_eq!(1, query.iter(&world).count()); - let mut query = world.query_filtered::<(), With>(); assert_eq!(2, query.iter(&world).count()); let mut query = world.query::>(); assert_eq!(3, query.iter(&world).count()); - let mut query = world.query::>(); - assert_eq!(3, query.iter(&world).count()); - - let mut query = world.query::>(); - assert_eq!(3, query.iter(&world).count()); - let mut query = world.query_filtered::<(), With>(); assert_eq!(4, query.iter(&world).count()); @@ -324,19 +311,9 @@ mod tests { let mut query = world.query::<(Has, Has)>(); assert_eq!(15, query.iter(&world).count()); - // Some edge cases: - - // Ideally this would include entities with `Disabled`, - // but the access is indistinguishable from `EntityRef`. - let mut query = world.query::<(EntityRef, Option<&Disabled>)>(); + // This seems like it ought to count as a mention of `Disabled`, but it does not. + // We don't consider read access, since that would count `EntityRef` as a mention of *all* components. + let mut query = world.query::>(); assert_eq!(1, query.iter(&world).count()); - - // This is even true if the component is explicitly mentioned in `EntityMutExcept`. - let mut query = world.query::<(EntityMutExcept, Option<&Disabled>)>(); - assert_eq!(1, query.iter(&world).count()); - - // But note that without `Option`, this adds a filter and does include disabled entities. - let mut query = world.query::<(EntityRef, &Disabled)>(); - assert_eq!(2, query.iter(&world).count()); } } diff --git a/crates/bevy_ecs/src/query/access.rs b/crates/bevy_ecs/src/query/access.rs index d634d31c03..1f3291d538 100644 --- a/crates/bevy_ecs/src/query/access.rs +++ b/crates/bevy_ecs/src/query/access.rs @@ -272,13 +272,6 @@ impl Access { .contains(index.sparse_set_index()) } - /// Returns `true` if this either has bounded access including this component - /// or unbounded access not including this component. - pub(crate) fn has_component_read_exception(&self, index: T) -> bool { - self.component_read_and_writes - .contains(index.sparse_set_index()) - } - /// Returns `true` if this can access any component. pub fn has_any_component_read(&self) -> bool { self.component_read_and_writes_inverted || !self.component_read_and_writes.is_clear() @@ -1232,14 +1225,11 @@ impl FilteredAccess { .flat_map(|f| f.without.ones().map(T::get_sparse_set_index)) } - /// Returns true if the index is used by this `FilteredAccess` in any way + /// Returns true if the index is used by this `FilteredAccess` in filters or archetypal access. + /// This includes most ways to access a component, but notably excludes `EntityRef` and `EntityMut` + /// along with anything inside `Option`. pub fn contains(&self, index: T) -> bool { - // Check whether this component is an exception. - // For normal queries, we want to treat access as a use, - // but for `EntityRefExcept` and `EntityMutExcept`, - // treat the exceptions as a use since they were mentioned explicitly. - self.access().has_component_read_exception(index.clone()) - || self.access().has_archetypal(index.clone()) + self.access().has_archetypal(index.clone()) || self.filter_sets.iter().any(|f| { f.with.contains(index.sparse_set_index()) || f.without.contains(index.sparse_set_index())