Skip to content

Commit f2b5450

Browse files
committed
Implement FusedIterator for eligible Iterator types (#4942)
# Objective Most of our `Iterator` impls satisfy the requirements of `std::iter::FusedIterator`, which has internal specialization that optimizes `Interator::fuse`. The std lib iterator combinators do have a few that rely on `fuse`, so this could optimize those use cases. I don't think we're using any of them in the engine itself, but beyond a light increase in compile time, it doesn't hurt to implement the trait. ## Solution Implement the trait for all eligible iterators in first party crates. Also add a missing `ExactSizeIterator` on an iterator that could use it.
1 parent 012ae07 commit f2b5450

File tree

6 files changed

+40
-4
lines changed

6 files changed

+40
-4
lines changed

crates/bevy_ecs/src/entity/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ impl<'a> Iterator for ReserveEntitiesIterator<'a> {
196196
}
197197

198198
impl<'a> core::iter::ExactSizeIterator for ReserveEntitiesIterator<'a> {}
199+
impl<'a> core::iter::FusedIterator for ReserveEntitiesIterator<'a> {}
199200

200201
#[derive(Debug, Default)]
201202
pub struct Entities {

crates/bevy_ecs/src/query/iter.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
query::{Fetch, QueryState, WorldQuery},
66
storage::{TableId, Tables},
77
};
8-
use std::{borrow::Borrow, marker::PhantomData, mem::MaybeUninit};
8+
use std::{borrow::Borrow, iter::FusedIterator, marker::PhantomData, mem::MaybeUninit};
99

1010
use super::{QueryFetch, QueryItem, ReadOnlyFetch};
1111

@@ -72,6 +72,12 @@ where
7272
}
7373
}
7474

75+
// This is correct as [`QueryIter`] always returns `None` once exhausted.
76+
impl<'w, 's, Q: WorldQuery, QF, F: WorldQuery> FusedIterator for QueryIter<'w, 's, Q, QF, F> where
77+
QF: Fetch<'w, State = Q::State>
78+
{
79+
}
80+
7581
/// An [`Iterator`] over query results of a [`Query`](crate::system::Query).
7682
///
7783
/// This struct is created by the [`Query::iter_many`](crate::system::Query::iter_many) method.
@@ -359,6 +365,15 @@ where
359365
}
360366
}
361367

368+
// This is correct as [`QueryCombinationIter`] always returns `None` once exhausted.
369+
impl<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize> FusedIterator
370+
for QueryCombinationIter<'w, 's, Q, F, K>
371+
where
372+
QueryFetch<'w, Q>: Clone + ReadOnlyFetch,
373+
QueryFetch<'w, F>: Clone + ReadOnlyFetch,
374+
{
375+
}
376+
362377
struct QueryIterationCursor<'w, 's, Q: WorldQuery, QF: Fetch<'w, State = Q::State>, F: WorldQuery> {
363378
table_id_iter: std::slice::Iter<'s, TableId>,
364379
archetype_id_iter: std::slice::Iter<'s, ArchetypeId>,

crates/bevy_ecs/src/world/spawn_batch.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::{
33
entity::Entity,
44
world::World,
55
};
6+
use std::iter::FusedIterator;
67

78
pub struct SpawnBatchIter<'w, I>
89
where
@@ -84,3 +85,10 @@ where
8485
self.inner.len()
8586
}
8687
}
88+
89+
impl<I, T> FusedIterator for SpawnBatchIter<'_, I>
90+
where
91+
I: FusedIterator<Item = T>,
92+
T: Bundle,
93+
{
94+
}

crates/bevy_reflect/src/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{serde::Serializable, Reflect, ReflectMut, ReflectRef};
2-
use std::fmt::Debug;
32
use std::{
43
any::Any,
4+
fmt::Debug,
55
hash::{Hash, Hasher},
66
};
77

crates/bevy_render/src/mesh/mesh/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem};
1414
use bevy_math::*;
1515
use bevy_reflect::TypeUuid;
1616
use bevy_utils::Hashed;
17-
use std::{collections::BTreeMap, hash::Hash};
17+
use std::{collections::BTreeMap, hash::Hash, iter::FusedIterator};
1818
use thiserror::Error;
1919
use wgpu::{
2020
util::BufferInitDescriptor, BufferUsages, IndexFormat, VertexAttribute, VertexFormat,
@@ -749,8 +749,18 @@ impl Iterator for IndicesIter<'_> {
749749
IndicesIter::U32(iter) => iter.next().map(|val| *val as usize),
750750
}
751751
}
752+
753+
fn size_hint(&self) -> (usize, Option<usize>) {
754+
match self {
755+
IndicesIter::U16(iter) => iter.size_hint(),
756+
IndicesIter::U32(iter) => iter.size_hint(),
757+
}
758+
}
752759
}
753760

761+
impl<'a> ExactSizeIterator for IndicesIter<'a> {}
762+
impl<'a> FusedIterator for IndicesIter<'a> {}
763+
754764
impl From<&Indices> for IndexFormat {
755765
fn from(indices: &Indices) -> Self {
756766
match indices {

crates/bevy_render/src/render_resource/pipeline_cache.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use bevy_asset::{AssetEvent, Assets, Handle};
1313
use bevy_ecs::event::EventReader;
1414
use bevy_ecs::system::{Res, ResMut};
1515
use bevy_utils::{default, tracing::error, Entry, HashMap, HashSet};
16-
use std::{hash::Hash, mem, ops::Deref, sync::Arc};
16+
use std::{hash::Hash, iter::FusedIterator, mem, ops::Deref, sync::Arc};
1717
use thiserror::Error;
1818
use wgpu::{PipelineLayoutDescriptor, ShaderModule, VertexBufferLayout as RawVertexBufferLayout};
1919

@@ -672,3 +672,5 @@ impl<'a> Iterator for ErrorSources<'a> {
672672
current
673673
}
674674
}
675+
676+
impl<'a> FusedIterator for ErrorSources<'a> {}

0 commit comments

Comments
 (0)