Skip to content

Commit 0ca9d69

Browse files
Improve docs for WorldQuery (#17654)
# Objective While working on #17649, I found the docs for `WorldQuery` and the related traits frustratingly vague. ## Solution Clarify them and add some more tangible advice. Also fix a copy-pasted typo in related comments. --------- Co-authored-by: James O'Brien <james.obrien@drafly.net>
1 parent 29d0ef6 commit 0ca9d69

File tree

5 files changed

+41
-26
lines changed

5 files changed

+41
-26
lines changed

crates/bevy_ecs/src/query/fetch.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,7 +1760,7 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
17601760
this_run: Tick,
17611761
) -> OptionFetch<'w, T> {
17621762
OptionFetch {
1763-
// SAFETY: The invariants are uphold by the caller.
1763+
// SAFETY: The invariants are upheld by the caller.
17641764
fetch: unsafe { T::init_fetch(world, state, last_run, this_run) },
17651765
matches: false,
17661766
}
@@ -1777,7 +1777,7 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
17771777
) {
17781778
fetch.matches = T::matches_component_set(state, &|id| archetype.contains(id));
17791779
if fetch.matches {
1780-
// SAFETY: The invariants are uphold by the caller.
1780+
// SAFETY: The invariants are upheld by the caller.
17811781
unsafe {
17821782
T::set_archetype(&mut fetch.fetch, state, archetype, table);
17831783
}
@@ -1788,7 +1788,7 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
17881788
unsafe fn set_table<'w>(fetch: &mut OptionFetch<'w, T>, state: &T::State, table: &'w Table) {
17891789
fetch.matches = T::matches_component_set(state, &|id| table.has_column(id));
17901790
if fetch.matches {
1791-
// SAFETY: The invariants are uphold by the caller.
1791+
// SAFETY: The invariants are upheld by the caller.
17921792
unsafe {
17931793
T::set_table(&mut fetch.fetch, state, table);
17941794
}
@@ -1803,7 +1803,7 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
18031803
) -> Self::Item<'w> {
18041804
fetch
18051805
.matches
1806-
// SAFETY: The invariants are uphold by the caller.
1806+
// SAFETY: The invariants are upheld by the caller.
18071807
.then(|| unsafe { T::fetch(&mut fetch.fetch, entity, table_row) })
18081808
}
18091809

@@ -2073,7 +2073,7 @@ macro_rules! impl_anytuple_fetch {
20732073
#[inline]
20742074
unsafe fn init_fetch<'w>(_world: UnsafeWorldCell<'w>, state: &Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w> {
20752075
let ($($name,)*) = state;
2076-
// SAFETY: The invariants are uphold by the caller.
2076+
// SAFETY: The invariants are upheld by the caller.
20772077
($(( unsafe { $name::init_fetch(_world, $name, _last_run, _this_run) }, false),)*)
20782078
}
20792079

@@ -2091,7 +2091,7 @@ macro_rules! impl_anytuple_fetch {
20912091
$(
20922092
$name.1 = $name::matches_component_set($state, &|id| _archetype.contains(id));
20932093
if $name.1 {
2094-
// SAFETY: The invariants are uphold by the caller.
2094+
// SAFETY: The invariants are upheld by the caller.
20952095
unsafe { $name::set_archetype(&mut $name.0, $state, _archetype, _table); }
20962096
}
20972097
)*

crates/bevy_ecs/src/query/filter.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ pub unsafe trait QueryFilter: WorldQuery {
8686
///
8787
/// This enables optimizations for [`crate::query::QueryIter`] that rely on knowing exactly how
8888
/// many elements are being iterated (such as `Iterator::collect()`).
89+
///
90+
/// If this is `true`, then [`QueryFilter::filter_fetch`] must always return true.
8991
const IS_ARCHETYPAL: bool;
9092

9193
/// Returns true if the provided [`Entity`] and [`TableRow`] should be included in the query results.
@@ -94,6 +96,9 @@ pub unsafe trait QueryFilter: WorldQuery {
9496
/// Note that this is called after already restricting the matched [`Table`]s and [`Archetype`]s to the
9597
/// ones that are compatible with the Filter's access.
9698
///
99+
/// Implementors of this method will generally either have a trivial `true` body (required for archetypal filters),
100+
/// or call [`WorldQuery::fetch`] to access the raw data needed to make the final decision on filter inclusion.
101+
///
97102
/// # Safety
98103
///
99104
/// Must always be called _after_ [`WorldQuery::set_table`] or [`WorldQuery::set_archetype`]. `entity` and
@@ -426,7 +431,7 @@ macro_rules! impl_or_query_filter {
426431
unsafe fn init_fetch<'w>(world: UnsafeWorldCell<'w>, state: &Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w> {
427432
let ($($filter,)*) = state;
428433
($(OrFetch {
429-
// SAFETY: The invariants are uphold by the caller.
434+
// SAFETY: The invariants are upheld by the caller.
430435
fetch: unsafe { $filter::init_fetch(world, $filter, last_run, this_run) },
431436
matches: false,
432437
},)*)
@@ -439,7 +444,7 @@ macro_rules! impl_or_query_filter {
439444
$(
440445
$filter.matches = $filter::matches_component_set($state, &|id| table.has_column(id));
441446
if $filter.matches {
442-
// SAFETY: The invariants are uphold by the caller.
447+
// SAFETY: The invariants are upheld by the caller.
443448
unsafe { $filter::set_table(&mut $filter.fetch, $state, table); }
444449
}
445450
)*
@@ -457,7 +462,7 @@ macro_rules! impl_or_query_filter {
457462
$(
458463
$filter.matches = $filter::matches_component_set($state, &|id| archetype.contains(id));
459464
if $filter.matches {
460-
// SAFETY: The invariants are uphold by the caller.
465+
// SAFETY: The invariants are upheld by the caller.
461466
unsafe { $filter::set_archetype(&mut $filter.fetch, $state, archetype, table); }
462467
}
463468
)*
@@ -470,7 +475,7 @@ macro_rules! impl_or_query_filter {
470475
table_row: TableRow
471476
) -> Self::Item<'w> {
472477
let ($($filter,)*) = fetch;
473-
// SAFETY: The invariants are uphold by the caller.
478+
// SAFETY: The invariants are upheld by the caller.
474479
false $(|| ($filter.matches && unsafe { $filter::filter_fetch(&mut $filter.fetch, entity, table_row) }))*
475480
}
476481

@@ -521,7 +526,7 @@ macro_rules! impl_or_query_filter {
521526
entity: Entity,
522527
table_row: TableRow
523528
) -> bool {
524-
// SAFETY: The invariants are uphold by the caller.
529+
// SAFETY: The invariants are upheld by the caller.
525530
unsafe { Self::fetch(fetch, entity, table_row) }
526531
}
527532
}
@@ -554,7 +559,7 @@ macro_rules! impl_tuple_query_filter {
554559
table_row: TableRow
555560
) -> bool {
556561
let ($($name,)*) = fetch;
557-
// SAFETY: The invariants are uphold by the caller.
562+
// SAFETY: The invariants are upheld by the caller.
558563
true $(&& unsafe { $name::filter_fetch($name, entity, table_row) })*
559564
}
560565
}
@@ -805,7 +810,7 @@ unsafe impl<T: Component> QueryFilter for Added<T> {
805810
entity: Entity,
806811
table_row: TableRow,
807812
) -> bool {
808-
// SAFETY: The invariants are uphold by the caller.
813+
// SAFETY: The invariants are upheld by the caller.
809814
unsafe { Self::fetch(fetch, entity, table_row) }
810815
}
811816
}
@@ -1039,7 +1044,7 @@ unsafe impl<T: Component> QueryFilter for Changed<T> {
10391044
entity: Entity,
10401045
table_row: TableRow,
10411046
) -> bool {
1042-
// SAFETY: The invariants are uphold by the caller.
1047+
// SAFETY: The invariants are upheld by the caller.
10431048
unsafe { Self::fetch(fetch, entity, table_row) }
10441049
}
10451050
}

crates/bevy_ecs/src/query/iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
4848
// SAFETY: We only access table data that has been registered in `query_state`.
4949
tables: unsafe { &world.storages().tables },
5050
archetypes: world.archetypes(),
51-
// SAFETY: The invariants are uphold by the caller.
51+
// SAFETY: The invariants are upheld by the caller.
5252
cursor: unsafe { QueryIterationCursor::init(world, query_state, last_run, this_run) },
5353
}
5454
}

crates/bevy_ecs/src/query/world_query.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ use variadics_please::all_tuples;
4040
/// [`QueryFilter`]: crate::query::QueryFilter
4141
pub unsafe trait WorldQuery {
4242
/// The item returned by this [`WorldQuery`]
43-
/// For `QueryData` this will be the item returned by the query.
43+
/// For `QueryData` this will be the data retrieved by the query,
44+
/// and is visible to the end user when calling e.g. `Query<Self>::get`.
45+
///
4446
/// For `QueryFilter` this will be either `()`, or a `bool` indicating whether the entity should be included
4547
/// or a tuple of such things.
48+
/// Archetypal query filters (like `With`) set this to `()`,
49+
/// as the filtering is done by selecting the archetypes to iterate over via [`WorldQuery::matches_component_set`],
50+
/// while non-archetypal query filters (like `Changed`) set this to a `bool` and evaluate the filter for each entity,
51+
/// after the set of possible archetypes has been narrowed down.
4652
type Item<'a>;
4753

48-
/// Per archetype/table state used by this [`WorldQuery`] to fetch [`Self::Item`](WorldQuery::Item)
54+
/// Per archetype/table state retrieved by this [`WorldQuery`] to compute [`Self::Item`](WorldQuery::Item) for each entity.
4955
type Fetch<'a>: Clone;
5056

5157
/// State used to construct a [`Self::Fetch`](WorldQuery::Fetch). This will be cached inside [`QueryState`](crate::query::QueryState),
@@ -59,7 +65,8 @@ pub unsafe trait WorldQuery {
5965
/// This function manually implements subtyping for the query fetches.
6066
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort>;
6167

62-
/// Creates a new instance of this fetch.
68+
/// Creates a new instance of [`Self::Fetch`](WorldQuery::Fetch),
69+
/// by combining data from the [`World`] with the cached [`Self::State`](WorldQuery::State).
6370
/// Readonly accesses resources registered in [`WorldQuery::update_component_access`].
6471
///
6572
/// # Safety
@@ -76,7 +83,9 @@ pub unsafe trait WorldQuery {
7683
) -> Self::Fetch<'w>;
7784

7885
/// Returns true if (and only if) every table of every archetype matched by this fetch contains
79-
/// all of the matched components. This is used to select a more efficient "table iterator"
86+
/// all of the matched components.
87+
///
88+
/// This is used to select a more efficient "table iterator"
8089
/// for "dense" queries. If this returns true, [`WorldQuery::set_table`] must be used before
8190
/// [`WorldQuery::fetch`] can be called for iterators. If this returns false,
8291
/// [`WorldQuery::set_archetype`] must be used before [`WorldQuery::fetch`] can be called for
@@ -147,7 +156,8 @@ pub unsafe trait WorldQuery {
147156
/// Returns `true` if this query matches a set of components. Otherwise, returns `false`.
148157
///
149158
/// Used to check which [`Archetype`]s can be skipped by the query
150-
/// (if none of the [`Component`](crate::component::Component)s match)
159+
/// (if none of the [`Component`](crate::component::Component)s match).
160+
/// This is how archetypal query filters like `With` work.
151161
fn matches_component_set(
152162
state: &Self::State,
153163
set_contains_id: &impl Fn(ComponentId) -> bool,
@@ -201,7 +211,7 @@ macro_rules! impl_tuple_world_query {
201211
#[inline]
202212
unsafe fn init_fetch<'w>(world: UnsafeWorldCell<'w>, state: &Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w> {
203213
let ($($name,)*) = state;
204-
// SAFETY: The invariants are uphold by the caller.
214+
// SAFETY: The invariants are upheld by the caller.
205215
($(unsafe { $name::init_fetch(world, $name, last_run, this_run) },)*)
206216
}
207217

@@ -216,15 +226,15 @@ macro_rules! impl_tuple_world_query {
216226
) {
217227
let ($($name,)*) = fetch;
218228
let ($($state,)*) = state;
219-
// SAFETY: The invariants are uphold by the caller.
229+
// SAFETY: The invariants are upheld by the caller.
220230
$(unsafe { $name::set_archetype($name, $state, archetype, table); })*
221231
}
222232

223233
#[inline]
224234
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) {
225235
let ($($name,)*) = fetch;
226236
let ($($state,)*) = state;
227-
// SAFETY: The invariants are uphold by the caller.
237+
// SAFETY: The invariants are upheld by the caller.
228238
$(unsafe { $name::set_table($name, $state, table); })*
229239
}
230240

@@ -235,7 +245,7 @@ macro_rules! impl_tuple_world_query {
235245
table_row: TableRow
236246
) -> Self::Item<'w> {
237247
let ($($name,)*) = fetch;
238-
// SAFETY: The invariants are uphold by the caller.
248+
// SAFETY: The invariants are upheld by the caller.
239249
($(unsafe { $name::fetch($name, entity, table_row) },)*)
240250
}
241251

crates/bevy_ecs/src/system/function_system.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ impl<Param: SystemParam> SystemState<Param> {
630630
world: UnsafeWorldCell<'w>,
631631
) -> SystemParamItem<'w, 's, Param> {
632632
let change_tick = world.increment_change_tick();
633-
// SAFETY: The invariants are uphold by the caller.
633+
// SAFETY: The invariants are upheld by the caller.
634634
unsafe { self.fetch(world, change_tick) }
635635
}
636636

@@ -644,7 +644,7 @@ impl<Param: SystemParam> SystemState<Param> {
644644
world: UnsafeWorldCell<'w>,
645645
change_tick: Tick,
646646
) -> SystemParamItem<'w, 's, Param> {
647-
// SAFETY: The invariants are uphold by the caller.
647+
// SAFETY: The invariants are upheld by the caller.
648648
let param =
649649
unsafe { Param::get_param(&mut self.param_state, &self.meta, world, change_tick) };
650650
self.meta.last_run = change_tick;

0 commit comments

Comments
 (0)