Improve Query-related traits for developers
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
Query has great doc for users but the docs for the developer-facing query traits (WorldQuery, QueryData, QueryFilter) are more lacking.
There is currently an explanation of what each method does, but what is missing is an explanation of how they all fit together:
- why do we have these methods?
- in which order are they called?
Everytime I look at them again, I have to search for these answers again.
Ideally there would be something that follows a bit more the 'lifecycle' of a Query or System
- a System gets created (usually a FunctionSystem)
- for each param, it calls `Param::init_state`. For query, that calls `WorldQuery::init_state` on D/F.
To create the State, we want to store the FilteredAccess used by the Query, which is computed using
`WorldQuery::update_component_access`
- `Param::init_access` is called to check if the new param doesn't conflict with existing SystemParams.
The other methods are used while iterating:
- `matches_component_set` is used when we try to find which archetypes match the query.
You could think that we could simply use the QueryState's component_access to figure that out, and that is true for archetypal query data. However it is useful: for example with `Option<&T>`, we don't include T in the `with` filter of the FilteredAccess (so every archetype matches the query). But when we iterate through tables, we want to only set the tables if `T::matches_component_tables` is True, i.e. if the component T is actually present in the table.
- we go through all archetypes that match the query (as identified by `matches_component_set`)
For each table/archetype that matches, we use `WorldQuery::fetch_table/archetype` to update the Fetch/Filter to be ready to fetch data from the table/archetype currently being iterated
- For each row, we call `QueryFilter::filter_fetch` to see if the row should be skipped because of the filters
- We then call `QueryData::fetch` to actually get the data from the table/archetype
Then there's extras:
- `WorldQuery::get_state` seems to be used for cases like creating a Query from `&World` instead of `&mut World`, or some transmute/join functions
- shrink fetches shrinks the lifetime of the Fetch, but i'm unsure of why/when it's used
This guide-level doc should also maybe explain some of the gotchas/subtleties around some tricky WorldQuery, such as `Option` or `Changed` (non-archetypal)
Contributor guide
Research direction
Start with the developer-facing WorldQuery, QueryData, and QueryFilter traits and trace the FunctionSystem and Param::init_state/init_access lifecycle described in the issue. Document the initialization and iteration order, including matches_component_set, fetch_table/archetype, filter_fetch, fetch, get_state, shrink fetches, and the Option and Changed subtleties; done means developers can follow how the methods fit together without repeated source searches.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100