Skip to content

Streaming iteration for non-IterQueryData#23218

Merged
alice-i-cecile merged 6 commits intobevyengine:mainfrom
chescock:IterQueryData
Mar 11, 2026
Merged

Streaming iteration for non-IterQueryData#23218
alice-i-cecile merged 6 commits intobevyengine:mainfrom
chescock:IterQueryData

Conversation

@chescock
Copy link
Copy Markdown
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
Copy link
Copy Markdown
Contributor

@kfc35 kfc35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sat with this pull request for a while to understand what’s going on, probably for an embarrassingly long time. That being said, I can at least approve on the grounds that

  • The safety comments are an improvement and are correct from what I can understand of Queries and by looking at the unsafe functions called
  • The code changes reflect the intention in the PR description and what is stated in the migration guide, except for maybe one thing I commented on (I may be incorrect). The PR description was very helpful in describing the complete picture of iterators.

That being said, my approval may have blindspots if something else should be considered in the world of query iterators.

I’ll let my learnings of IterQueryData simmer a bit more in my brain.

Copy link
Copy Markdown
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM, and I'm happy to get this in, but I think we can do a little better on docs to help users who stumble over the edge cases.

@chescock
Copy link
Copy Markdown
Contributor Author

Changes LGTM, and I'm happy to get this in, but I think we can do a little better on docs to help users who stumble over the edge cases.

I updated the docs some more. I think everything is covered now, but it's always hard to be sure, so let me know if you think of anything else I missed!

@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 11, 2026
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 11, 2026
Merged via the queue into bevyengine:main with commit 22d7c65 Mar 11, 2026
40 checks passed
@github-project-automation github-project-automation bot moved this from Needs SME Triage to Done in ECS Mar 11, 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-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants