Skip to content

Commit 73f14c8

Browse files
ottahItsDoot
authored andcommitted
Remove ExactSizeIterator from QueryCombinationIter (bevyengine#5895)
# Objective - `QueryCombinationIter` can have sizes greater than `usize::MAX`. - Fixes bevyengine#5846 ## Solution - Only the implementation of `ExactSizeIterator` has been removed. Instead of using `query_combination.len()`, you can use `query_combination.size_hint().0` to get the same value as before. --- ## Migration Guide - Switch to using other methods of getting the length.
1 parent 3dac48f commit 73f14c8

File tree

4 files changed

+102
-95
lines changed

4 files changed

+102
-95
lines changed

crates/bevy_ecs/src/query/iter.rs

-15
Original file line numberDiff line numberDiff line change
@@ -454,21 +454,6 @@ where
454454
}
455455
}
456456

457-
impl<'w, 's, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery + ArchetypeFilter, const K: usize>
458-
ExactSizeIterator for QueryCombinationIter<'w, 's, Q, F, K>
459-
where
460-
QueryFetch<'w, Q>: Clone,
461-
QueryFetch<'w, F>: Clone,
462-
{
463-
/// Returns the exact length of the iterator.
464-
///
465-
/// **NOTE**: When the iterator length overflows `usize`, this will
466-
/// return `usize::MAX`.
467-
fn len(&self) -> usize {
468-
self.size_hint().0
469-
}
470-
}
471-
472457
// This is correct as [`QueryCombinationIter`] always returns `None` once exhausted.
473458
impl<'w, 's, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery, const K: usize> FusedIterator
474459
for QueryCombinationIter<'w, 's, Q, F, K>

crates/bevy_ecs/src/query/mod.rs

+102-9
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,102 @@ mod tests {
5757

5858
#[test]
5959
fn query_filtered_exactsizeiterator_len() {
60+
fn assert_all_sizes_iterator_equal(
61+
iterator: impl ExactSizeIterator,
62+
expected_size: usize,
63+
query_type: &'static str,
64+
) {
65+
let len = iterator.len();
66+
let size_hint_0 = iterator.size_hint().0;
67+
let size_hint_1 = iterator.size_hint().1;
68+
// `count` tests that not only it is the expected value, but also
69+
// the value is accurate to what the query returns.
70+
let count = iterator.count();
71+
// This will show up when one of the asserts in this function fails
72+
println!(
73+
r#"query declared sizes:
74+
for query: {query_type}
75+
expected: {expected_size}
76+
len: {len}
77+
size_hint().0: {size_hint_0}
78+
size_hint().1: {size_hint_1:?}
79+
count(): {count}"#
80+
);
81+
assert_eq!(len, expected_size);
82+
assert_eq!(size_hint_0, expected_size);
83+
assert_eq!(size_hint_1, Some(expected_size));
84+
assert_eq!(count, expected_size);
85+
}
86+
fn assert_all_sizes_equal<Q, F>(world: &mut World, expected_size: usize)
87+
where
88+
Q: ReadOnlyWorldQuery,
89+
F: ReadOnlyWorldQuery,
90+
F::ReadOnly: ArchetypeFilter,
91+
for<'w> QueryFetch<'w, Q::ReadOnly>: Clone,
92+
for<'w> QueryFetch<'w, F::ReadOnly>: Clone,
93+
{
94+
let mut query = world.query_filtered::<Q, F>();
95+
let iter = query.iter(world);
96+
let query_type = type_name::<QueryState<Q, F>>();
97+
assert_all_sizes_iterator_equal(iter, expected_size, query_type);
98+
}
99+
100+
let mut world = World::new();
101+
world.spawn((A(1), B(1)));
102+
world.spawn((A(2),));
103+
world.spawn((A(3),));
104+
105+
assert_all_sizes_equal::<&A, With<B>>(&mut world, 1);
106+
assert_all_sizes_equal::<&A, Without<B>>(&mut world, 2);
107+
108+
let mut world = World::new();
109+
world.spawn((A(1), B(1), C(1)));
110+
world.spawn((A(2), B(2)));
111+
world.spawn((A(3), B(3)));
112+
world.spawn((A(4), C(4)));
113+
world.spawn((A(5), C(5)));
114+
world.spawn((A(6), C(6)));
115+
world.spawn((A(7),));
116+
world.spawn((A(8),));
117+
world.spawn((A(9),));
118+
world.spawn((A(10),));
119+
120+
// With/Without for B and C
121+
assert_all_sizes_equal::<&A, With<B>>(&mut world, 3);
122+
assert_all_sizes_equal::<&A, With<C>>(&mut world, 4);
123+
assert_all_sizes_equal::<&A, Without<B>>(&mut world, 7);
124+
assert_all_sizes_equal::<&A, Without<C>>(&mut world, 6);
125+
126+
// With/Without (And) combinations
127+
assert_all_sizes_equal::<&A, (With<B>, With<C>)>(&mut world, 1);
128+
assert_all_sizes_equal::<&A, (With<B>, Without<C>)>(&mut world, 2);
129+
assert_all_sizes_equal::<&A, (Without<B>, With<C>)>(&mut world, 3);
130+
assert_all_sizes_equal::<&A, (Without<B>, Without<C>)>(&mut world, 4);
131+
132+
// With/Without Or<()> combinations
133+
assert_all_sizes_equal::<&A, Or<(With<B>, With<C>)>>(&mut world, 6);
134+
assert_all_sizes_equal::<&A, Or<(With<B>, Without<C>)>>(&mut world, 7);
135+
assert_all_sizes_equal::<&A, Or<(Without<B>, With<C>)>>(&mut world, 8);
136+
assert_all_sizes_equal::<&A, Or<(Without<B>, Without<C>)>>(&mut world, 9);
137+
assert_all_sizes_equal::<&A, (Or<(With<B>,)>, Or<(With<C>,)>)>(&mut world, 1);
138+
assert_all_sizes_equal::<&A, Or<(Or<(With<B>, With<C>)>, With<D>)>>(&mut world, 6);
139+
140+
for i in 11..14 {
141+
world.spawn((A(i), D(i)));
142+
}
143+
144+
assert_all_sizes_equal::<&A, Or<(Or<(With<B>, With<C>)>, With<D>)>>(&mut world, 9);
145+
assert_all_sizes_equal::<&A, Or<(Or<(With<B>, With<C>)>, Without<D>)>>(&mut world, 10);
146+
147+
// a fair amount of entities
148+
for i in 14..20 {
149+
world.spawn((C(i), D(i)));
150+
}
151+
assert_all_sizes_equal::<Entity, (With<C>, With<D>)>(&mut world, 6);
152+
}
153+
154+
#[test]
155+
fn query_filtered_combination_size() {
60156
fn choose(n: usize, k: usize) -> usize {
61157
if n == 0 || k == 0 || n < k {
62158
return 0;
@@ -100,27 +196,24 @@ mod tests {
100196
assert_combination::<Q, F, 128>(world, choose(expected, 128));
101197
}
102198
fn assert_all_sizes_iterator_equal(
103-
iterator: impl ExactSizeIterator,
199+
iterator: impl Iterator,
104200
expected_size: usize,
105201
query_type: &'static str,
106202
) {
107203
let size_hint_0 = iterator.size_hint().0;
108204
let size_hint_1 = iterator.size_hint().1;
109-
let len = iterator.len();
110205
// `count` tests that not only it is the expected value, but also
111206
// the value is accurate to what the query returns.
112207
let count = iterator.count();
113208
// This will show up when one of the asserts in this function fails
114209
println!(
115210
r#"query declared sizes:
116-
for query: {query_type}
117-
expected: {expected_size}
118-
len(): {len}
119-
size_hint().0: {size_hint_0}
120-
size_hint().1: {size_hint_1:?}
121-
count(): {count}"#
211+
for query: {query_type}
212+
expected: {expected_size}
213+
size_hint().0: {size_hint_0}
214+
size_hint().1: {size_hint_1:?}
215+
count(): {count}"#
122216
);
123-
assert_eq!(len, expected_size);
124217
assert_eq!(size_hint_0, expected_size);
125218
assert_eq!(size_hint_1, Some(expected_size));
126219
assert_eq!(count, expected_size);

crates/bevy_ecs_compile_fail_tests/tests/ui/query_combin_exact_sized_iterator_safety.rs

-20
This file was deleted.

crates/bevy_ecs_compile_fail_tests/tests/ui/query_combin_exact_sized_iterator_safety.stderr

-51
This file was deleted.

0 commit comments

Comments
 (0)