You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Objective
For #17647, we want to create a `QueryData` that can follow a relation
and query data from an entity's parent. If the parent does not have the
queried data, the child entity should be skipped in the query. However,
there is no way to tell from the child's archetype whether the parent
will match! So, we need to support *non-archetypal* `QueryData`, just as
we support non-archetypal `QueryFilter`s for `Added` and `Changed`.
That is, if `Query<Parent<&T>>` yields `&T`, and we do:
```rust
let parent1 = world.spawn(T).id();
let child1 = world.spawn(ChildOf(parent1));
let parent2 = world.spawn(()).id();
let child2 = world.spawn(ChildOf(parent2));
let query = world.query::<Parent<&T>>();
```
then `query` must yield a row for `child1` but not for `child2`, even
though they have the same archetype.
## Solution
Change `QueryData::fetch` to return `Option` so that entities can be
filtered during fetching by returning `None`.
To support `ExactSizeIterator`, introduce an `ArchetypeQueryData` trait
and an `QueryData::IS_ARCHETYPAL` associated constant, similar to
`ArchetypeFilter` and `QueryFilter::IS_ARCHETYPAL`. Implement this trait
on existing `QueryData` types. Modify `ExactSizeIterator`
implementations to require `D: ArchetypeQueryData`, and the
`size_hint()` methods to return a minimum size of `0` if
`!D::IS_ARCHETYPAL`.
## Alternatives
We could do nothing here, and have `Query<Parent<&T>>` yield
`Option<&T>`. That makes the API less convenient, though. Note that if
one *wants* to query for `Option`, they can use either
`Query<Option<Parent<&T>>` or `Query<Parent<Option<&T>>`, depending on
whether they want to include entities with no parent.
Another option is to re-use the `ArchetypeFilter` trait instead of
introducing a new one. There are no places where we want to abstract
over both, however, and it would require writing bounds like `D:
QueryData + ArchetypeFilter, F: QueryFilter + ArchetypeFilter` instead
of simply `D: ArchetypeQueryData, F: ArchetypeFilter`.
---------
Co-authored-by: Periwink <charlesbour@gmail.com>
0 commit comments