Skip to main content

WorldQuery

Trait WorldQuery 

Source
pub trait WorldQuery {
    type Item<'w>;
    type State: QueryState;

    // Required methods
    fn init_state(world: &World) -> Self::State;
    fn component_access(state: &Self::State) -> BTreeSet<ComponentId>;
    fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool;
    fn fetch<'w>(
        state: &Self::State,
        world: &'w World,
        entity: Entity,
    ) -> Option<Self::Item<'w>>;

    // Provided method
    fn fetch_mut<'w>(
        state: &Self::State,
        world: &'w mut World,
        entity: Entity,
    ) -> Option<Self::Item<'w>> { ... }
}
Expand description

Trait for types that can be queried from a World.

WorldQuery is the foundational trait of the ECS query system. It defines:

  1. What type of data the query produces (Item)
  2. What state the query caches (State)
  3. How to match archetypes (matches_archetype)
  4. How to fetch data from the world (fetch)

§Generic Associated Type

The Item<'w> associated type uses a Generic Associated Type (GAT) to express that the fetched item has a lifetime tied to the world borrow. This enables returning references to component data.

§State Caching

The State type caches information needed for efficient queries, typically:

  • Component IDs (avoids repeated TypeId lookups)
  • Cached archetype matches (avoids repeated set operations)

§Safety

Implementors must ensure:

  1. matches_archetype accurately reflects what entities can be fetched
  2. fetch returns None for entities that don’t match
  3. Mutable queries conflict with other queries on the same component

§Built-in Implementations

The following types implement WorldQuery:

  • &T where T: Component - Fetches immutable component reference
  • &mut T where T: Component - Fetches mutable component reference
  • Entity - Fetches the entity ID itself
  • Tuples (A, B, ...) - Combines multiple queries
  • Option<Q> - Optional query, always matches
  • With<T> - Filter for entities that have T (no data)
  • Without<T> - Filter for entities that don’t have T (no data)

§Example

use goud_engine::ecs::{Component, Entity, World};
use goud_engine::ecs::query::WorldQuery;

#[derive(Debug)]
struct Health(f32);
impl Component for Health {}

// The trait bounds ensure type safety:
fn query_requires_world_query<Q: WorldQuery>() {}

// Entity always implements WorldQuery
query_requires_world_query::<Entity>();

Required Associated Types§

Source

type Item<'w>

The type of data this query fetches.

This is a Generic Associated Type (GAT) that takes a lifetime parameter 'w representing the world borrow lifetime. This allows the item to contain references to data stored in the world.

Examples:

  • For &T: Item<'w> = &'w T
  • For &mut T: Item<'w> = &'w mut T
  • For Entity: Item<'w> = Entity (no reference needed)
Source

type State: QueryState

The cached state for this query.

State is initialized once via init_state and reused for subsequent queries. This avoids repeated lookups of component IDs and other metadata.

Examples:

  • For &T: State = ComponentId
  • For tuples: State = (A::State, B::State, ...)

Required Methods§

Source

fn init_state(world: &World) -> Self::State

Initializes the query state from the world.

This is called once when a query is first created. The returned state is cached and reused for all subsequent operations.

§Arguments
  • world - Reference to the world (may be used for resource lookups)
§Returns

The initialized state for this query.

Source

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Returns the set of component IDs this query reads.

Used for access conflict detection. Two queries conflict if one writes a component that the other reads or writes.

§Arguments
  • state - The query state
§Returns

Set of component IDs accessed for reading (includes mutable access).

Source

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Checks whether this query matches the given archetype.

Returns true if entities in the archetype can produce a valid Item. This is used to filter archetypes during query iteration.

§Arguments
  • state - The cached query state
  • archetype - The archetype to check
§Returns

true if entities in this archetype match the query.

Source

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Fetches data for a specific entity from the world.

Returns Some(Item) if the entity has all required components, None otherwise.

§Arguments
  • state - The cached query state
  • world - Reference to the world containing component data
  • entity - The entity to fetch data for
§Returns

Some(Item) if the entity matches the query, None otherwise.

§Safety Note

This method takes an immutable world reference but may return mutable component references. The caller must ensure aliasing rules are maintained (typically enforced by the query iterator).

Provided Methods§

Source

fn fetch_mut<'w>( state: &Self::State, world: &'w mut World, entity: Entity, ) -> Option<Self::Item<'w>>

Fetches data for a specific entity from a mutable world reference.

This variant is used when mutable component access is needed. The default implementation calls fetch with an immutable borrow, but mutable query implementations override this.

§Arguments
  • state - The cached query state
  • world - Mutable reference to the world
  • entity - The entity to fetch data for
§Returns

Some(Item) if the entity matches the query, None otherwise.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl WorldQuery for ()

Unit type () represents an empty query.

This is useful as a base case for tuple queries and for queries that only use filters without fetching any data.

Source§

type Item<'w> = ()

Source§

type State = ()

Source§

fn init_state(_world: &World) -> Self::State

Source§

fn component_access(_state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(_state: &Self::State, _archetype: &Archetype) -> bool

Source§

fn fetch<'w>( _state: &Self::State, _world: &'w World, _entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<A: WorldQuery> WorldQuery for (A,)

Source§

type Item<'w> = (<A as WorldQuery>::Item<'w>,)

Source§

type State = (<A as WorldQuery>::State,)

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<A: WorldQuery, B: WorldQuery> WorldQuery for (A, B)

Source§

type Item<'w> = (<A as WorldQuery>::Item<'w>, <B as WorldQuery>::Item<'w>)

Source§

type State = (<A as WorldQuery>::State, <B as WorldQuery>::State)

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<A: WorldQuery, B: WorldQuery, C: WorldQuery> WorldQuery for (A, B, C)

Source§

type Item<'w> = (<A as WorldQuery>::Item<'w>, <B as WorldQuery>::Item<'w>, <C as WorldQuery>::Item<'w>)

Source§

type State = (<A as WorldQuery>::State, <B as WorldQuery>::State, <C as WorldQuery>::State)

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<A: WorldQuery, B: WorldQuery, C: WorldQuery, D: WorldQuery> WorldQuery for (A, B, C, D)

Source§

type Item<'w> = (<A as WorldQuery>::Item<'w>, <B as WorldQuery>::Item<'w>, <C as WorldQuery>::Item<'w>, <D as WorldQuery>::Item<'w>)

Source§

type State = (<A as WorldQuery>::State, <B as WorldQuery>::State, <C as WorldQuery>::State, <D as WorldQuery>::State)

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<A: WorldQuery, B: WorldQuery, C: WorldQuery, D: WorldQuery, E: WorldQuery> WorldQuery for (A, B, C, D, E)

Source§

type Item<'w> = (<A as WorldQuery>::Item<'w>, <B as WorldQuery>::Item<'w>, <C as WorldQuery>::Item<'w>, <D as WorldQuery>::Item<'w>, <E as WorldQuery>::Item<'w>)

Source§

type State = (<A as WorldQuery>::State, <B as WorldQuery>::State, <C as WorldQuery>::State, <D as WorldQuery>::State, <E as WorldQuery>::State)

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<A: WorldQuery, B: WorldQuery, C: WorldQuery, D: WorldQuery, E: WorldQuery, F: WorldQuery> WorldQuery for (A, B, C, D, E, F)

Source§

type Item<'w> = (<A as WorldQuery>::Item<'w>, <B as WorldQuery>::Item<'w>, <C as WorldQuery>::Item<'w>, <D as WorldQuery>::Item<'w>, <E as WorldQuery>::Item<'w>, <F as WorldQuery>::Item<'w>)

Source§

type State = (<A as WorldQuery>::State, <B as WorldQuery>::State, <C as WorldQuery>::State, <D as WorldQuery>::State, <E as WorldQuery>::State, <F as WorldQuery>::State)

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<A: WorldQuery, B: WorldQuery, C: WorldQuery, D: WorldQuery, E: WorldQuery, F: WorldQuery, G: WorldQuery> WorldQuery for (A, B, C, D, E, F, G)

Source§

type Item<'w> = (<A as WorldQuery>::Item<'w>, <B as WorldQuery>::Item<'w>, <C as WorldQuery>::Item<'w>, <D as WorldQuery>::Item<'w>, <E as WorldQuery>::Item<'w>, <F as WorldQuery>::Item<'w>, <G as WorldQuery>::Item<'w>)

Source§

type State = (<A as WorldQuery>::State, <B as WorldQuery>::State, <C as WorldQuery>::State, <D as WorldQuery>::State, <E as WorldQuery>::State, <F as WorldQuery>::State, <G as WorldQuery>::State)

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<A: WorldQuery, B: WorldQuery, C: WorldQuery, D: WorldQuery, E: WorldQuery, F: WorldQuery, G: WorldQuery, H: WorldQuery> WorldQuery for (A, B, C, D, E, F, G, H)

Source§

type Item<'w> = (<A as WorldQuery>::Item<'w>, <B as WorldQuery>::Item<'w>, <C as WorldQuery>::Item<'w>, <D as WorldQuery>::Item<'w>, <E as WorldQuery>::Item<'w>, <F as WorldQuery>::Item<'w>, <G as WorldQuery>::Item<'w>, <H as WorldQuery>::Item<'w>)

Source§

type State = (<A as WorldQuery>::State, <B as WorldQuery>::State, <C as WorldQuery>::State, <D as WorldQuery>::State, <E as WorldQuery>::State, <F as WorldQuery>::State, <G as WorldQuery>::State, <H as WorldQuery>::State)

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<Q: WorldQuery> WorldQuery for Option<Q>

Optional query wrapper.

Option<Q> always matches every archetype. When the inner query Q can fetch data for an entity, the result is Some(Q::Item). When it cannot, the result is None. In both cases, the outer fetch returns Some(...), so the entity is never skipped by the query system.

§Use Cases

  • Querying for a component that only some entities have
  • Avoiding the need for separate queries when a component is optional
  • Combining required and optional components in tuple queries

§Example

// Query all entities with Position, optionally fetching Velocity
// (&Position, Option<&Velocity>)
// - Entities with both: (pos, Some(vel))
// - Entities with only Position: (pos, None)
Source§

type Item<'w> = Option<<Q as WorldQuery>::Item<'w>>

Source§

type State = <Q as WorldQuery>::State

Source§

fn init_state(world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(_state: &Self::State, _archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

fn fetch_mut<'w>( state: &Self::State, world: &'w mut World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<T: Component> WorldQuery for &T

Query for an immutable component reference.

&T queries fetch a reference to component T for each matching entity. This is one of the most common query types.

§Archetype Matching

An archetype matches &T if it contains component T. The query returns None for entities that don’t have the component.

§Parallel Safety

&T is a read-only query and implements ReadOnlyWorldQuery. Multiple &T queries for the same component can run in parallel, and &T can run alongside &U for different components.

§Example

use goud_engine::ecs::{World, Component, Entity};
use goud_engine::ecs::query::WorldQuery;

#[derive(Debug, Clone, Copy, PartialEq)]
struct Position { x: f32, y: f32 }
impl Component for Position {}

let mut world = World::new();
let entity = world.spawn_empty();
world.insert(entity, Position { x: 1.0, y: 2.0 });

// Initialize query state
let state = <&Position>::init_state(&world);

// Fetch component reference
let pos = <&Position>::fetch(&state, &world, entity);
assert!(pos.is_some());
assert_eq!(pos.unwrap(), &Position { x: 1.0, y: 2.0 });

§Access Conflicts

  • &T conflicts with &mut T (read-write conflict)
  • &T does NOT conflict with &T (multiple readers allowed)
  • &T does NOT conflict with &U where U ≠ T
Source§

type Item<'w> = &'w T

Source§

type State = ComponentId

Source§

fn init_state(_world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch<'w>( state: &Self::State, world: &'w World, entity: Entity, ) -> Option<Self::Item<'w>>

Source§

impl<T: Component> WorldQuery for &mut T

Query for a mutable component reference.

&mut T queries fetch a mutable reference to component T for each matching entity. This allows modifying component data in place.

§Archetype Matching

An archetype matches &mut T if it contains component T. The query returns None for entities that don’t have the component.

§Access Conflicts

Mutable queries have strict access requirements:

  • &mut T conflicts with &T (write-read conflict)
  • &mut T conflicts with &mut T (write-write conflict)
  • &mut T does NOT conflict with &U or &mut U where U ≠ T

The scheduler uses this information to prevent parallel execution of conflicting systems.

§Thread Safety

&mut T does NOT implement ReadOnlyWorldQuery. This means:

  1. Systems using &mut T cannot run in parallel with other systems accessing T
  2. The query iterator enforces exclusive access at runtime

§Example

use goud_engine::ecs::{World, Component, Entity};
use goud_engine::ecs::query::WorldQuery;

#[derive(Debug, Clone, Copy, PartialEq)]
struct Health(f32);
impl Component for Health {}

let mut world = World::new();
let entity = world.spawn_empty();
world.insert(entity, Health(100.0));

// Initialize query state
let state = <&mut Health>::init_state(&world);

// Fetch mutable component reference
if let Some(health) = <&mut Health>::fetch_mut(&state, &mut world, entity) {
    health.0 -= 10.0; // Modify in place
}

// Verify modification
assert_eq!(world.get::<Health>(entity), Some(&Health(90.0)));

§Important Notes

  • The fetch method returns None because mutable access requires a mutable world reference. Use fetch_mut for mutable queries.
  • The query system enforces that only one mutable access to a component exists at any time, preventing aliasing issues.
Source§

fn fetch<'w>( _state: &Self::State, _world: &'w World, _entity: Entity, ) -> Option<Self::Item<'w>>

Returns None because mutable access requires fetch_mut.

This is intentional - the immutable world reference cannot provide mutable component access without violating Rust’s aliasing rules.

Source§

type Item<'w> = &'w mut T

Source§

type State = MutState

Source§

fn init_state(_world: &World) -> Self::State

Source§

fn component_access(state: &Self::State) -> BTreeSet<ComponentId>

Source§

fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool

Source§

fn fetch_mut<'w>( state: &Self::State, world: &'w mut World, entity: Entity, ) -> Option<Self::Item<'w>>

Implementors§

Source§

impl WorldQuery for Entity

Entity can be queried to get the entity ID itself.

This is useful when you need the entity ID along with component data, or when iterating over all entities in an archetype.

Source§

impl<T: Component> WorldQuery for Added<T>

Source§

impl<T: Component> WorldQuery for Changed<T>

Source§

impl<T: Component> WorldQuery for With<T>

Source§

impl<T: Component> WorldQuery for Without<T>