Skip to content

Streaming iteration for non-IterQueryData#23218

Open
chescock wants to merge 5 commits intobevyengine:mainfrom
chescock:IterQueryData
Open

Streaming iteration for non-IterQueryData#23218
chescock wants to merge 5 commits intobevyengine:mainfrom
chescock:IterQueryData

Conversation

@chescock
Copy link
Contributor

@chescock chescock commented Mar 4, 2026

Objective

Follow-up to #21557

Support streaming iteration (a.k.a. lending iteration) for QueryIter and QuerySortedIter so that it's possible to iterate Query<Parent<&mut T>>.

Double-check that all the IterQueryData bounds are correct and that the safety comments are correct. A few were not!

Solution

Offer a fetch_next method on QueryIter and QuerySortedIter that borrows the entire iterator to prevent aliasing, similar to QueryManyIter::QueryManyIter.

Offer a Query::iter_inner method to produce QueryIter even when it is not an Iterator. We cannot rely on IntoIterator in that case, and Clippy objects to an inherent method called into_iter() that is not the standard trait method. This supersedes the existing iter_inner method that only worked on ReadOnlyQueryData.

Add a missing IterQueryData bound to iter_combinations_mut. It yields multiple entities concurrently, so is never sound to use with non-IterQueryData. I think the reason I missed this originally is that it already has a fetch_next method and conditional Iterator impl. But even fetch_next yields multiple entities at once for QueryCombinationIter!

Add a ContiguousQueryData: IterQueryData supertrait bound. QueryContiguousIter also yields multiple entities concurrently, so it does not make sense on non-iterable data. This was not actually unsound, though, as QueryContiguousIter does not call fetch.

Finally, update some missing or incorrect safety comments.

Verify bounds on the other iterator types

To verify I didn't miss any bounds on iterator types, here is a list of every Query*Iter type, and whether they support non-IterQueryData:

Type Supports non-Iter?
CombinationIter No, added missing bound
ContiguousIter No, added missing bound
Iter Yes, added support
ManyIter Yes, existing support
ManyUniqueIter No, and existing bound*
ParIter No, and existing bound
ParManyIter No, and existing bound
ParManyUniqueIter No, and existing bound
SortedIter Yes, added support
SortedManyIter Yes, existing support

Iter and SortedIter were changed in this PR to support streaming iteration for all QueryData, while only implementing Iterator for IterQueryData.

ManyIter and SortedManyIter already had streaming iteration, and only implement Iterator with a stricter ReadOnlyQueryData bound, since they may yield the same entity multiple times.

ManyUniqueIter could theoretically be used with non-IterQueryData... but if you need to do streaming iteration anyway then you can call iter_many_mut() instead of iter_many_unique_mut().

CombinationIter, ContiguousIter, and the Par*Iter types are all fundamentally about accessing multiple entities concurrently, and should always require IterQueryData. CombinationIter and ContiguousIter did not have IterQueryData bounds, so fix that!

Showcase

This is cheating a bit because we don't yet have Parent<&mut T>, but once we do it would look like:

fn system(query: Query<Parent<&mut Component>>) {
    let mut iter = query.iter_mut();
    while let Some(mut parent_component) = iter.fetch_next() {
        // Use `parent_component` here
    }
}

@chescock chescock added A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Unsafe Touches with unsafe code in some way S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 4, 2026
@github-project-automation github-project-automation bot moved this to Needs SME Triage in ECS Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Unsafe Touches with unsafe code in some way S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

1 participant