bevy_ecs/entity/entity_set.rs
1use alloc::{
2 boxed::Box,
3 collections::{btree_map, btree_set},
4 rc::Rc,
5};
6use bevy_platform::collections::HashSet;
7
8use core::{
9 array,
10 fmt::{Debug, Formatter},
11 hash::{BuildHasher, Hash},
12 iter::{self, FusedIterator},
13 option, ptr, result,
14};
15
16use super::{Entity, UniqueEntityEquivalentSlice};
17
18use bevy_platform::sync::Arc;
19
20/// A trait for types that contain an [`Entity`].
21///
22/// This trait behaves similarly to `Borrow<Entity>`, but yielding `Entity` directly.
23///
24/// It should only be implemented when:
25/// - Retrieving the [`Entity`] is a simple operation.
26/// - The [`Entity`] contained by the type is unambiguous.
27pub trait ContainsEntity {
28 /// Returns the contained entity.
29 fn entity(&self) -> Entity;
30}
31
32/// A trait for types that represent an [`Entity`].
33///
34/// Comparison trait behavior between an [`EntityEquivalent`] type and its underlying entity will match.
35/// This property includes [`PartialEq`], [`Eq`], [`PartialOrd`], [`Ord`] and [`Hash`],
36/// and remains even after [`Clone`] and/or [`Borrow`] calls.
37///
38/// # Safety
39/// Any [`PartialEq`], [`Eq`], [`PartialOrd`], and [`Ord`] impls must evaluate the same for `Self` and
40/// its underlying entity.
41/// `x.entity() == y.entity()` must be equivalent to `x == y`.
42///
43/// The above equivalence must also hold through and between calls to any [`Clone`] and
44/// [`Borrow`]/[`BorrowMut`] impls in place of [`entity()`].
45///
46/// The result of [`entity()`] must be unaffected by any interior mutability.
47///
48/// The aforementioned properties imply determinism in both [`entity()`] calls
49/// and comparison trait behavior.
50///
51/// All [`Hash`] impls except that for [`Entity`] must delegate to the [`Hash`] impl of
52/// another [`EntityEquivalent`] type. All conversions to the delegatee within the [`Hash`] impl must
53/// follow [`entity()`] equivalence.
54///
55/// It should be noted that [`Hash`] is *not* a comparison trait, and with [`Hash::hash`] being forcibly
56/// generic over all [`Hasher`]s, **cannot** guarantee determinism or uniqueness of any final hash values
57/// on its own.
58/// To obtain hash values forming the same total order as [`Entity`], any [`Hasher`] used must be
59/// deterministic and concerning [`Entity`], collisionless.
60/// Standard library hash collections handle collisions with an [`Eq`] fallback, but do not account for
61/// determinism when [`BuildHasher`] is unspecified.
62///
63/// [`Hash`]: core::hash::Hash
64/// [`Hasher`]: core::hash::Hasher
65/// [`Borrow`]: core::borrow::Borrow
66/// [`BorrowMut`]: core::borrow::BorrowMut
67/// [`entity()`]: ContainsEntity::entity
68pub unsafe trait EntityEquivalent: ContainsEntity + Eq {}
69
70impl ContainsEntity for Entity {
71 fn entity(&self) -> Entity {
72 *self
73 }
74}
75
76// SAFETY:
77// The trait implementations of Entity are correct and deterministic.
78unsafe impl EntityEquivalent for Entity {}
79
80impl<T: ContainsEntity> ContainsEntity for &T {
81 fn entity(&self) -> Entity {
82 (**self).entity()
83 }
84}
85
86// SAFETY:
87// `&T` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.
88// `Clone` and `Borrow` maintain equality.
89// `&T` is `Freeze`.
90unsafe impl<T: EntityEquivalent> EntityEquivalent for &T {}
91
92impl<T: ContainsEntity> ContainsEntity for &mut T {
93 fn entity(&self) -> Entity {
94 (**self).entity()
95 }
96}
97
98// SAFETY:
99// `&mut T` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.
100// `Borrow` and `BorrowMut` maintain equality.
101// `&mut T` is `Freeze`.
102unsafe impl<T: EntityEquivalent> EntityEquivalent for &mut T {}
103
104impl<T: ContainsEntity> ContainsEntity for Box<T> {
105 fn entity(&self) -> Entity {
106 (**self).entity()
107 }
108}
109
110// SAFETY:
111// `Box<T>` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.
112// `Clone`, `Borrow` and `BorrowMut` maintain equality.
113// `Box<T>` is `Freeze`.
114unsafe impl<T: EntityEquivalent> EntityEquivalent for Box<T> {}
115
116impl<T: ContainsEntity> ContainsEntity for Rc<T> {
117 fn entity(&self) -> Entity {
118 (**self).entity()
119 }
120}
121
122// SAFETY:
123// `Rc<T>` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.
124// `Clone`, `Borrow` and `BorrowMut` maintain equality.
125// `Rc<T>` is `Freeze`.
126unsafe impl<T: EntityEquivalent> EntityEquivalent for Rc<T> {}
127
128impl<T: ContainsEntity> ContainsEntity for Arc<T> {
129 fn entity(&self) -> Entity {
130 (**self).entity()
131 }
132}
133
134// SAFETY:
135// `Arc<T>` delegates `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash` to T.
136// `Clone`, `Borrow` and `BorrowMut` maintain equality.
137// `Arc<T>` is `Freeze`.
138unsafe impl<T: EntityEquivalent> EntityEquivalent for Arc<T> {}
139
140/// A set of unique entities.
141///
142/// Any element returned by [`Self::IntoIter`] will compare non-equal to every other element in the iterator.
143/// As a consequence, [`into_iter()`] on `EntitySet` will always produce another `EntitySet`.
144///
145/// Implementing this trait allows for unique query iteration over a list of entities.
146/// See [`iter_many_unique`] and [`iter_many_unique_mut`].
147///
148/// Note that there is no guarantee of the [`IntoIterator`] impl being deterministic,
149/// it might return different iterators when called multiple times.
150/// Neither is there a guarantee that the comparison trait impls of `EntitySet` match that
151/// of the respective [`EntitySetIterator`] (or of a [`Vec`] collected from its elements).
152///
153/// [`Self::IntoIter`]: IntoIterator::IntoIter
154/// [`into_iter()`]: IntoIterator::into_iter
155/// [`iter_many_unique`]: crate::system::Query::iter_many_unique
156/// [`iter_many_unique_mut`]: crate::system::Query::iter_many_unique_mut
157/// [`Vec`]: alloc::vec::Vec
158pub trait EntitySet: IntoIterator<IntoIter: EntitySetIterator> {}
159
160impl<T: IntoIterator<IntoIter: EntitySetIterator>> EntitySet for T {}
161
162/// An iterator over a set of unique entities.
163///
164/// Every `EntitySetIterator` is also [`EntitySet`].
165///
166/// # Safety
167///
168/// `x != y` must hold for any 2 elements returned by the iterator.
169/// This is always true for iterators that cannot return more than one element.
170pub unsafe trait EntitySetIterator: Iterator<Item: EntityEquivalent> {
171 /// Transforms an `EntitySetIterator` into a collection.
172 ///
173 /// This is a specialized form of [`collect`], for collections which benefit from the uniqueness guarantee.
174 /// When present, this should always be preferred over [`collect`].
175 ///
176 /// [`collect`]: Iterator::collect
177 // FIXME: When subtrait item shadowing stabilizes, this should be renamed and shadow `Iterator::collect`
178 fn collect_set<B: FromEntitySetIterator<Self::Item>>(self) -> B
179 where
180 Self: Sized,
181 {
182 FromEntitySetIterator::from_entity_set_iter(self)
183 }
184}
185
186// SAFETY:
187// A correct `BTreeMap` contains only unique keys.
188// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeMap`.
189unsafe impl<K: EntityEquivalent, V> EntitySetIterator for btree_map::Keys<'_, K, V> {}
190
191// SAFETY:
192// A correct `BTreeMap` contains only unique keys.
193// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeMap`.
194unsafe impl<K: EntityEquivalent, V> EntitySetIterator for btree_map::IntoKeys<K, V> {}
195
196// SAFETY:
197// A correct `BTreeSet` contains only unique elements.
198// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.
199// The sub-range maintains uniqueness.
200unsafe impl<T: EntityEquivalent> EntitySetIterator for btree_set::Range<'_, T> {}
201
202// SAFETY:
203// A correct `BTreeSet` contains only unique elements.
204// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.
205// The "intersection" operation maintains uniqueness.
206unsafe impl<T: EntityEquivalent + Ord> EntitySetIterator for btree_set::Intersection<'_, T> {}
207
208// SAFETY:
209// A correct `BTreeSet` contains only unique elements.
210// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.
211// The "union" operation maintains uniqueness.
212unsafe impl<T: EntityEquivalent + Ord> EntitySetIterator for btree_set::Union<'_, T> {}
213
214// SAFETY:
215// A correct `BTreeSet` contains only unique elements.
216// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.
217// The "difference" operation maintains uniqueness.
218unsafe impl<T: EntityEquivalent + Ord> EntitySetIterator for btree_set::Difference<'_, T> {}
219
220// SAFETY:
221// A correct `BTreeSet` contains only unique elements.
222// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.
223// The "symmetric difference" operation maintains uniqueness.
224unsafe impl<T: EntityEquivalent + Ord> EntitySetIterator for btree_set::SymmetricDifference<'_, T> {}
225
226// SAFETY:
227// A correct `BTreeSet` contains only unique elements.
228// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.
229unsafe impl<T: EntityEquivalent> EntitySetIterator for btree_set::Iter<'_, T> {}
230
231// SAFETY:
232// A correct `BTreeSet` contains only unique elements.
233// EntityEquivalent guarantees a trustworthy Ord impl for T, and thus a correct `BTreeSet`.
234unsafe impl<T: EntityEquivalent> EntitySetIterator for btree_set::IntoIter<T> {}
235
236// SAFETY: This iterator only returns one element.
237unsafe impl<T: EntityEquivalent> EntitySetIterator for option::Iter<'_, T> {}
238
239// SAFETY: This iterator only returns one element.
240// unsafe impl<T: EntityEquivalent> EntitySetIterator for option::IterMut<'_, T> {}
241
242// SAFETY: This iterator only returns one element.
243unsafe impl<T: EntityEquivalent> EntitySetIterator for option::IntoIter<T> {}
244
245// SAFETY: This iterator only returns one element.
246unsafe impl<T: EntityEquivalent> EntitySetIterator for result::Iter<'_, T> {}
247
248// SAFETY: This iterator only returns one element.
249// unsafe impl<T: EntityEquivalent> EntitySetIterator for result::IterMut<'_, T> {}
250
251// SAFETY: This iterator only returns one element.
252unsafe impl<T: EntityEquivalent> EntitySetIterator for result::IntoIter<T> {}
253
254// SAFETY: This iterator only returns one element.
255unsafe impl<T: EntityEquivalent> EntitySetIterator for array::IntoIter<T, 1> {}
256
257// SAFETY: This iterator does not return any elements.
258unsafe impl<T: EntityEquivalent> EntitySetIterator for array::IntoIter<T, 0> {}
259
260// SAFETY: This iterator only returns one element.
261unsafe impl<T: EntityEquivalent, F: FnOnce() -> T> EntitySetIterator for iter::OnceWith<F> {}
262
263// SAFETY: This iterator only returns one element.
264unsafe impl<T: EntityEquivalent> EntitySetIterator for iter::Once<T> {}
265
266// SAFETY: This iterator does not return any elements.
267unsafe impl<T: EntityEquivalent> EntitySetIterator for iter::Empty<T> {}
268
269// SAFETY: Taking a mutable reference of an iterator has no effect on its elements.
270unsafe impl<I: EntitySetIterator + ?Sized> EntitySetIterator for &mut I {}
271
272// SAFETY: Boxing an iterator has no effect on its elements.
273unsafe impl<I: EntitySetIterator + ?Sized> EntitySetIterator for Box<I> {}
274
275// SAFETY: EntityEquivalent ensures that Copy does not affect equality, via its restrictions on Clone.
276unsafe impl<'a, T: 'a + EntityEquivalent + Copy, I: EntitySetIterator<Item = &'a T>>
277 EntitySetIterator for iter::Copied<I>
278{
279}
280
281// SAFETY: EntityEquivalent ensures that Clone does not affect equality.
282unsafe impl<'a, T: 'a + EntityEquivalent + Clone, I: EntitySetIterator<Item = &'a T>>
283 EntitySetIterator for iter::Cloned<I>
284{
285}
286
287// SAFETY: Discarding elements maintains uniqueness.
288unsafe impl<I: EntitySetIterator, P: FnMut(&<I as Iterator>::Item) -> bool> EntitySetIterator
289 for iter::Filter<I, P>
290{
291}
292
293// SAFETY: Yielding only `None` after yielding it once can only remove elements, which maintains uniqueness.
294unsafe impl<I: EntitySetIterator> EntitySetIterator for iter::Fuse<I> {}
295
296// SAFETY:
297// Obtaining immutable references the elements of an iterator does not affect uniqueness.
298// EntityEquivalent ensures the lack of interior mutability.
299unsafe impl<I: EntitySetIterator, F: FnMut(&<I as Iterator>::Item)> EntitySetIterator
300 for iter::Inspect<I, F>
301{
302}
303
304// SAFETY: Reversing an iterator does not affect uniqueness.
305unsafe impl<I: DoubleEndedIterator + EntitySetIterator> EntitySetIterator for iter::Rev<I> {}
306
307// SAFETY: Discarding elements maintains uniqueness.
308unsafe impl<I: EntitySetIterator> EntitySetIterator for iter::Skip<I> {}
309
310// SAFETY: Discarding elements maintains uniqueness.
311unsafe impl<I: EntitySetIterator, P: FnMut(&<I as Iterator>::Item) -> bool> EntitySetIterator
312 for iter::SkipWhile<I, P>
313{
314}
315
316// SAFETY: Discarding elements maintains uniqueness.
317unsafe impl<I: EntitySetIterator> EntitySetIterator for iter::Take<I> {}
318
319// SAFETY: Discarding elements maintains uniqueness.
320unsafe impl<I: EntitySetIterator, P: FnMut(&<I as Iterator>::Item) -> bool> EntitySetIterator
321 for iter::TakeWhile<I, P>
322{
323}
324
325// SAFETY: Discarding elements maintains uniqueness.
326unsafe impl<I: EntitySetIterator> EntitySetIterator for iter::StepBy<I> {}
327
328/// Conversion from an `EntitySetIterator`.
329///
330/// Some collections, while they can be constructed from plain iterators,
331/// benefit strongly from the additional uniqueness guarantee [`EntitySetIterator`] offers.
332/// Mirroring [`Iterator::collect`]/[`FromIterator::from_iter`], [`EntitySetIterator::collect_set`] and
333/// `FromEntitySetIterator::from_entity_set_iter` can be used for construction.
334///
335/// See also: [`EntitySet`].
336// FIXME: When subtrait item shadowing stabilizes, this should be renamed and shadow `FromIterator::from_iter`
337pub trait FromEntitySetIterator<A: EntityEquivalent>: FromIterator<A> {
338 /// Creates a value from an [`EntitySetIterator`].
339 fn from_entity_set_iter<T: EntitySet<Item = A>>(set_iter: T) -> Self;
340}
341
342impl<T: EntityEquivalent + Hash, S: BuildHasher + Default> FromEntitySetIterator<T>
343 for HashSet<T, S>
344{
345 #[inline]
346 fn from_entity_set_iter<I: EntitySet<Item = T>>(set_iter: I) -> Self {
347 let iter = set_iter.into_iter();
348 let set = HashSet::with_capacity_and_hasher(iter.size_hint().0, S::default());
349 iter.fold(set, |mut set, e| {
350 // SAFETY: Every element in self is unique.
351 unsafe {
352 set.insert_unique_unchecked(e);
353 }
354 set
355 })
356 }
357}
358
359/// An iterator that yields unique entities.
360///
361/// This wrapper can provide an [`EntitySetIterator`] implementation when an instance of `I` is known to uphold uniqueness.
362#[repr(transparent)]
363pub struct UniqueEntityIter<I: Iterator<Item: EntityEquivalent>> {
364 iter: I,
365}
366
367impl<I: EntitySetIterator> UniqueEntityIter<I> {
368 /// Constructs a `UniqueEntityIter` from an [`EntitySetIterator`].
369 #[inline]
370 pub const fn from_entity_set_iter(iter: I) -> Self {
371 // SAFETY: iter implements `EntitySetIterator`.
372 unsafe { Self::from_iter_unchecked(iter) }
373 }
374}
375
376impl<I: Iterator<Item: EntityEquivalent>> UniqueEntityIter<I> {
377 /// Constructs a [`UniqueEntityIter`] from an iterator unsafely.
378 ///
379 /// # Safety
380 /// `iter` must only yield unique elements.
381 /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`].
382 #[inline]
383 pub const unsafe fn from_iter_unchecked(iter: I) -> Self {
384 Self { iter }
385 }
386
387 /// Constructs a [`UniqueEntityIter`] from an iterator unsafely.
388 ///
389 /// # Safety
390 /// `iter` must only yield unique elements.
391 /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`].
392 #[inline]
393 pub const unsafe fn from_iter_ref_unchecked(iter: &I) -> &Self {
394 // SAFETY: UniqueEntityIter is a transparent wrapper around I.
395 unsafe { &*ptr::from_ref(iter).cast() }
396 }
397
398 /// Constructs a [`UniqueEntityIter`] from an iterator unsafely.
399 ///
400 /// # Safety
401 /// `iter` must only yield unique elements.
402 /// As in, the resulting iterator must adhere to the safety contract of [`EntitySetIterator`].
403 #[inline]
404 pub const unsafe fn from_iter_mut_unchecked(iter: &mut I) -> &mut Self {
405 // SAFETY: UniqueEntityIter is a transparent wrapper around I.
406 unsafe { &mut *ptr::from_mut(iter).cast() }
407 }
408
409 /// Returns the inner `I`.
410 pub fn into_inner(self) -> I {
411 self.iter
412 }
413
414 /// Returns a reference to the inner `I`.
415 pub const fn as_inner(&self) -> &I {
416 &self.iter
417 }
418
419 /// Returns a mutable reference to the inner `I`.
420 ///
421 /// # Safety
422 ///
423 /// `self` must always contain an iterator that yields unique elements,
424 /// even while this reference is live.
425 pub const unsafe fn as_mut_inner(&mut self) -> &mut I {
426 &mut self.iter
427 }
428}
429
430impl<I: Iterator<Item: EntityEquivalent>> Iterator for UniqueEntityIter<I> {
431 type Item = I::Item;
432
433 fn next(&mut self) -> Option<Self::Item> {
434 self.iter.next()
435 }
436
437 fn size_hint(&self) -> (usize, Option<usize>) {
438 self.iter.size_hint()
439 }
440}
441
442impl<I: ExactSizeIterator<Item: EntityEquivalent>> ExactSizeIterator for UniqueEntityIter<I> {}
443
444impl<I: DoubleEndedIterator<Item: EntityEquivalent>> DoubleEndedIterator for UniqueEntityIter<I> {
445 #[inline]
446 fn next_back(&mut self) -> Option<Self::Item> {
447 self.iter.next_back()
448 }
449}
450
451impl<I: FusedIterator<Item: EntityEquivalent>> FusedIterator for UniqueEntityIter<I> {}
452
453// SAFETY: The underlying iterator is ensured to only return unique elements by its construction.
454unsafe impl<I: Iterator<Item: EntityEquivalent>> EntitySetIterator for UniqueEntityIter<I> {}
455
456impl<T, I: Iterator<Item: EntityEquivalent> + AsRef<[T]>> AsRef<[T]> for UniqueEntityIter<I> {
457 fn as_ref(&self) -> &[T] {
458 self.iter.as_ref()
459 }
460}
461
462impl<T: EntityEquivalent, I: Iterator<Item: EntityEquivalent> + AsRef<[T]>>
463 AsRef<UniqueEntityEquivalentSlice<T>> for UniqueEntityIter<I>
464{
465 fn as_ref(&self) -> &UniqueEntityEquivalentSlice<T> {
466 // SAFETY: All elements in the original slice are unique.
467 unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked(self.iter.as_ref()) }
468 }
469}
470
471impl<T: EntityEquivalent, I: Iterator<Item: EntityEquivalent> + AsMut<[T]>>
472 AsMut<UniqueEntityEquivalentSlice<T>> for UniqueEntityIter<I>
473{
474 fn as_mut(&mut self) -> &mut UniqueEntityEquivalentSlice<T> {
475 // SAFETY: All elements in the original slice are unique.
476 unsafe { UniqueEntityEquivalentSlice::from_slice_unchecked_mut(self.iter.as_mut()) }
477 }
478}
479
480// Default does not guarantee uniqueness, meaning `I` needs to be EntitySetIterator.
481impl<I: EntitySetIterator + Default> Default for UniqueEntityIter<I> {
482 fn default() -> Self {
483 Self {
484 iter: Default::default(),
485 }
486 }
487}
488
489// Clone does not guarantee to maintain uniqueness, meaning `I` needs to be EntitySetIterator.
490impl<I: EntitySetIterator + Clone> Clone for UniqueEntityIter<I> {
491 fn clone(&self) -> Self {
492 Self {
493 iter: self.iter.clone(),
494 }
495 }
496}
497
498impl<I: Iterator<Item: EntityEquivalent> + Debug> Debug for UniqueEntityIter<I> {
499 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
500 f.debug_struct("UniqueEntityIter")
501 .field("iter", &self.iter)
502 .finish()
503 }
504}
505
506#[cfg(test)]
507mod tests {
508 use alloc::{vec, vec::Vec};
509
510 use crate::prelude::{Schedule, World};
511
512 use crate::component::Component;
513 use crate::entity::Entity;
514 use crate::query::{QueryState, With};
515 use crate::system::Query;
516 use crate::world::Mut;
517
518 use super::UniqueEntityIter;
519
520 #[derive(Component, Clone)]
521 pub struct Thing;
522
523 #[expect(
524 clippy::iter_skip_zero,
525 reason = "The `skip(0)` is used to ensure that the `Skip` iterator implements `EntitySet`, which is needed to pass the iterator as the `entities` parameter."
526 )]
527 #[test]
528 fn preserving_uniqueness() {
529 let mut world = World::new();
530
531 let mut query = QueryState::<&mut Thing>::new(&mut world);
532
533 let spawn_batch: Vec<Entity> = world.spawn_batch(vec![Thing; 1000]).collect();
534
535 // SAFETY: SpawnBatchIter is `EntitySetIterator`,
536 let mut unique_entity_iter =
537 unsafe { UniqueEntityIter::from_iter_unchecked(spawn_batch.iter()) };
538
539 let entity_set = unique_entity_iter
540 .by_ref()
541 .filter(|_| true)
542 .fuse()
543 .inspect(|_| ())
544 .rev()
545 .skip(0)
546 .skip_while(|_| false)
547 .take(1000)
548 .take_while(|_| true)
549 .step_by(2)
550 .cloned();
551
552 // With `iter_many_mut` collecting is not possible, because you need to drop each `Mut`/`&mut` before the next is retrieved.
553 let _results: Vec<Mut<Thing>> =
554 query.iter_many_unique_mut(&mut world, entity_set).collect();
555 }
556
557 #[test]
558 fn nesting_queries() {
559 let mut world = World::new();
560
561 world.spawn_batch(vec![Thing; 1000]);
562
563 pub fn system(
564 mut thing_entities: Query<Entity, With<Thing>>,
565 mut things: Query<&mut Thing>,
566 ) {
567 things.iter_many_unique(thing_entities.iter());
568 things.iter_many_unique_mut(thing_entities.iter_mut());
569 }
570
571 let mut schedule = Schedule::default();
572 schedule.add_systems(system);
573 schedule.run(&mut world);
574 }
575}