bevy_ecs/
change_detection.rs

1//! Types that detect when their internal data mutate.
2
3use crate::{
4    component::{Tick, TickCells},
5    ptr::PtrMut,
6    system::Resource,
7};
8use bevy_ptr::{Ptr, UnsafeCellDeref};
9use core::{
10    mem,
11    ops::{Deref, DerefMut},
12};
13#[cfg(feature = "track_change_detection")]
14use {
15    bevy_ptr::ThinSlicePtr,
16    core::{cell::UnsafeCell, panic::Location},
17};
18
19/// The (arbitrarily chosen) minimum number of world tick increments between `check_tick` scans.
20///
21/// Change ticks can only be scanned when systems aren't running. Thus, if the threshold is `N`,
22/// the maximum is `2 * N - 1` (i.e. the world ticks `N - 1` times, then `N` times).
23///
24/// If no change is older than `u32::MAX - (2 * N - 1)` following a scan, none of their ages can
25/// overflow and cause false positives.
26// (518,400,000 = 1000 ticks per frame * 144 frames per second * 3600 seconds per hour)
27pub const CHECK_TICK_THRESHOLD: u32 = 518_400_000;
28
29/// The maximum change tick difference that won't overflow before the next `check_tick` scan.
30///
31/// Changes stop being detected once they become this old.
32pub const MAX_CHANGE_AGE: u32 = u32::MAX - (2 * CHECK_TICK_THRESHOLD - 1);
33
34/// Types that can read change detection information.
35/// This change detection is controlled by [`DetectChangesMut`] types such as [`ResMut`].
36///
37/// ## Example
38/// Using types that implement [`DetectChanges`], such as [`Res`], provide
39/// a way to query if a value has been mutated in another system.
40///
41/// ```
42/// use bevy_ecs::prelude::*;
43///
44/// #[derive(Resource)]
45/// struct MyResource(u32);
46///
47/// fn my_system(mut resource: Res<MyResource>) {
48///     if resource.is_changed() {
49///         println!("My component was mutated!");
50///     }
51/// }
52/// ```
53pub trait DetectChanges {
54    /// Returns `true` if this value was added after the system last ran.
55    fn is_added(&self) -> bool;
56
57    /// Returns `true` if this value was added or mutably dereferenced
58    /// either since the last time the system ran or, if the system never ran,
59    /// since the beginning of the program.
60    ///
61    /// To check if the value was mutably dereferenced only,
62    /// use `this.is_changed() && !this.is_added()`.
63    fn is_changed(&self) -> bool;
64
65    /// Returns the change tick recording the time this data was most recently changed.
66    ///
67    /// Note that components and resources are also marked as changed upon insertion.
68    ///
69    /// For comparison, the previous change tick of a system can be read using the
70    /// [`SystemChangeTick`](crate::system::SystemChangeTick)
71    /// [`SystemParam`](crate::system::SystemParam).
72    fn last_changed(&self) -> Tick;
73
74    /// The location that last caused this to change.
75    #[cfg(feature = "track_change_detection")]
76    fn changed_by(&self) -> &'static Location<'static>;
77}
78
79/// Types that implement reliable change detection.
80///
81/// ## Example
82/// Using types that implement [`DetectChangesMut`], such as [`ResMut`], provide
83/// a way to query if a value has been mutated in another system.
84/// Normally change detection is triggered by either [`DerefMut`] or [`AsMut`], however
85/// it can be manually triggered via [`set_changed`](DetectChangesMut::set_changed).
86///
87/// To ensure that changes are only triggered when the value actually differs,
88/// check if the value would change before assignment, such as by checking that `new != old`.
89/// You must be *sure* that you are not mutably dereferencing in this process.
90///
91/// [`set_if_neq`](DetectChangesMut::set_if_neq) is a helper
92/// method for this common functionality.
93///
94/// ```
95/// use bevy_ecs::prelude::*;
96///
97/// #[derive(Resource)]
98/// struct MyResource(u32);
99///
100/// fn my_system(mut resource: ResMut<MyResource>) {
101///     if resource.is_changed() {
102///         println!("My resource was mutated!");
103///     }
104///
105///    resource.0 = 42; // triggers change detection via [`DerefMut`]
106/// }
107/// ```
108pub trait DetectChangesMut: DetectChanges {
109    /// The type contained within this smart pointer
110    ///
111    /// For example, for `ResMut<T>` this would be `T`.
112    type Inner: ?Sized;
113
114    /// Flags this value as having been changed.
115    ///
116    /// Mutably accessing this smart pointer will automatically flag this value as having been changed.
117    /// However, mutation through interior mutability requires manual reporting.
118    ///
119    /// **Note**: This operation cannot be undone.
120    fn set_changed(&mut self);
121
122    /// Manually sets the change tick recording the time when this data was last mutated.
123    ///
124    /// # Warning
125    /// This is a complex and error-prone operation, primarily intended for use with rollback networking strategies.
126    /// If you merely want to flag this data as changed, use [`set_changed`](DetectChangesMut::set_changed) instead.
127    /// If you want to avoid triggering change detection, use [`bypass_change_detection`](DetectChangesMut::bypass_change_detection) instead.
128    fn set_last_changed(&mut self, last_changed: Tick);
129
130    /// Manually bypasses change detection, allowing you to mutate the underlying value without updating the change tick.
131    ///
132    /// # Warning
133    /// This is a risky operation, that can have unexpected consequences on any system relying on this code.
134    /// However, it can be an essential escape hatch when, for example,
135    /// you are trying to synchronize representations using change detection and need to avoid infinite recursion.
136    fn bypass_change_detection(&mut self) -> &mut Self::Inner;
137
138    /// Overwrites this smart pointer with the given value, if and only if `*self != value`.
139    /// Returns `true` if the value was overwritten, and returns `false` if it was not.
140    ///
141    /// This is useful to ensure change detection is only triggered when the underlying value
142    /// changes, instead of every time it is mutably accessed.
143    ///
144    /// If you're dealing with non-trivial structs which have multiple fields of non-trivial size,
145    /// then consider applying a `map_unchanged` beforehand to allow changing only the relevant
146    /// field and prevent unnecessary copying and cloning.
147    /// See the docs of [`Mut::map_unchanged`], [`MutUntyped::map_unchanged`],
148    /// [`ResMut::map_unchanged`] or [`NonSendMut::map_unchanged`] for an example
149    ///
150    /// If you need the previous value, use [`replace_if_neq`](DetectChangesMut::replace_if_neq).
151    ///
152    /// # Examples
153    ///
154    /// ```
155    /// # use bevy_ecs::{prelude::*, schedule::common_conditions::resource_changed};
156    /// #[derive(Resource, PartialEq, Eq)]
157    /// pub struct Score(u32);
158    ///
159    /// fn reset_score(mut score: ResMut<Score>) {
160    ///     // Set the score to zero, unless it is already zero.
161    ///     score.set_if_neq(Score(0));
162    /// }
163    /// # let mut world = World::new();
164    /// # world.insert_resource(Score(1));
165    /// # let mut score_changed = IntoSystem::into_system(resource_changed::<Score>);
166    /// # score_changed.initialize(&mut world);
167    /// # score_changed.run((), &mut world);
168    /// #
169    /// # let mut schedule = Schedule::default();
170    /// # schedule.add_systems(reset_score);
171    /// #
172    /// # // first time `reset_score` runs, the score is changed.
173    /// # schedule.run(&mut world);
174    /// # assert!(score_changed.run((), &mut world));
175    /// # // second time `reset_score` runs, the score is not changed.
176    /// # schedule.run(&mut world);
177    /// # assert!(!score_changed.run((), &mut world));
178    /// ```
179    #[inline]
180    #[track_caller]
181    fn set_if_neq(&mut self, value: Self::Inner) -> bool
182    where
183        Self::Inner: Sized + PartialEq,
184    {
185        let old = self.bypass_change_detection();
186        if *old != value {
187            *old = value;
188            self.set_changed();
189            true
190        } else {
191            false
192        }
193    }
194
195    /// Overwrites this smart pointer with the given value, if and only if `*self != value`,
196    /// returning the previous value if this occurs.
197    ///
198    /// This is useful to ensure change detection is only triggered when the underlying value
199    /// changes, instead of every time it is mutably accessed.
200    ///
201    /// If you're dealing with non-trivial structs which have multiple fields of non-trivial size,
202    /// then consider applying a [`map_unchanged`](Mut::map_unchanged) beforehand to allow
203    /// changing only the relevant field and prevent unnecessary copying and cloning.
204    /// See the docs of [`Mut::map_unchanged`], [`MutUntyped::map_unchanged`],
205    /// [`ResMut::map_unchanged`] or [`NonSendMut::map_unchanged`] for an example
206    ///
207    /// If you don't need the previous value, use [`set_if_neq`](DetectChangesMut::set_if_neq).
208    ///
209    /// # Examples
210    ///
211    /// ```
212    /// # use bevy_ecs::{prelude::*, schedule::common_conditions::{resource_changed, on_event}};
213    /// #[derive(Resource, PartialEq, Eq)]
214    /// pub struct Score(u32);
215    ///
216    /// #[derive(Event, PartialEq, Eq)]
217    /// pub struct ScoreChanged {
218    ///     current: u32,
219    ///     previous: u32,
220    /// }
221    ///
222    /// fn reset_score(mut score: ResMut<Score>, mut score_changed: EventWriter<ScoreChanged>) {
223    ///     // Set the score to zero, unless it is already zero.
224    ///     let new_score = 0;
225    ///     if let Some(Score(previous_score)) = score.replace_if_neq(Score(new_score)) {
226    ///         // If `score` change, emit a `ScoreChanged` event.
227    ///         score_changed.send(ScoreChanged {
228    ///             current: new_score,
229    ///             previous: previous_score,
230    ///         });
231    ///     }
232    /// }
233    /// # let mut world = World::new();
234    /// # world.insert_resource(Events::<ScoreChanged>::default());
235    /// # world.insert_resource(Score(1));
236    /// # let mut score_changed = IntoSystem::into_system(resource_changed::<Score>);
237    /// # score_changed.initialize(&mut world);
238    /// # score_changed.run((), &mut world);
239    /// #
240    /// # let mut score_changed_event = IntoSystem::into_system(on_event::<ScoreChanged>);
241    /// # score_changed_event.initialize(&mut world);
242    /// # score_changed_event.run((), &mut world);
243    /// #
244    /// # let mut schedule = Schedule::default();
245    /// # schedule.add_systems(reset_score);
246    /// #
247    /// # // first time `reset_score` runs, the score is changed.
248    /// # schedule.run(&mut world);
249    /// # assert!(score_changed.run((), &mut world));
250    /// # assert!(score_changed_event.run((), &mut world));
251    /// # // second time `reset_score` runs, the score is not changed.
252    /// # schedule.run(&mut world);
253    /// # assert!(!score_changed.run((), &mut world));
254    /// # assert!(!score_changed_event.run((), &mut world));
255    /// ```
256    #[inline]
257    #[must_use = "If you don't need to handle the previous value, use `set_if_neq` instead."]
258    fn replace_if_neq(&mut self, value: Self::Inner) -> Option<Self::Inner>
259    where
260        Self::Inner: Sized + PartialEq,
261    {
262        let old = self.bypass_change_detection();
263        if *old != value {
264            let previous = mem::replace(old, value);
265            self.set_changed();
266            Some(previous)
267        } else {
268            None
269        }
270    }
271}
272
273macro_rules! change_detection_impl {
274    ($name:ident < $( $generics:tt ),+ >, $target:ty, $($traits:ident)?) => {
275        impl<$($generics),* : ?Sized $(+ $traits)?> DetectChanges for $name<$($generics),*> {
276            #[inline]
277            fn is_added(&self) -> bool {
278                self.ticks
279                    .added
280                    .is_newer_than(self.ticks.last_run, self.ticks.this_run)
281            }
282
283            #[inline]
284            fn is_changed(&self) -> bool {
285                self.ticks
286                    .changed
287                    .is_newer_than(self.ticks.last_run, self.ticks.this_run)
288            }
289
290            #[inline]
291            fn last_changed(&self) -> Tick {
292                *self.ticks.changed
293            }
294
295            #[inline]
296            #[cfg(feature = "track_change_detection")]
297            fn changed_by(&self) -> &'static Location<'static> {
298                self.changed_by
299            }
300        }
301
302        impl<$($generics),*: ?Sized $(+ $traits)?> Deref for $name<$($generics),*> {
303            type Target = $target;
304
305            #[inline]
306            fn deref(&self) -> &Self::Target {
307                self.value
308            }
309        }
310
311        impl<$($generics),* $(: $traits)?> AsRef<$target> for $name<$($generics),*> {
312            #[inline]
313            fn as_ref(&self) -> &$target {
314                self.deref()
315            }
316        }
317    }
318}
319
320macro_rules! change_detection_mut_impl {
321    ($name:ident < $( $generics:tt ),+ >, $target:ty, $($traits:ident)?) => {
322        impl<$($generics),* : ?Sized $(+ $traits)?> DetectChangesMut for $name<$($generics),*> {
323            type Inner = $target;
324
325            #[inline]
326            #[track_caller]
327            fn set_changed(&mut self) {
328                *self.ticks.changed = self.ticks.this_run;
329                #[cfg(feature = "track_change_detection")]
330                {
331                    *self.changed_by = Location::caller();
332                }
333            }
334
335            #[inline]
336            #[track_caller]
337            fn set_last_changed(&mut self, last_changed: Tick) {
338                *self.ticks.changed = last_changed;
339                #[cfg(feature = "track_change_detection")]
340                {
341                    *self.changed_by = Location::caller();
342                }
343            }
344
345            #[inline]
346            fn bypass_change_detection(&mut self) -> &mut Self::Inner {
347                self.value
348            }
349        }
350
351        impl<$($generics),* : ?Sized $(+ $traits)?> DerefMut for $name<$($generics),*> {
352            #[inline]
353            #[track_caller]
354            fn deref_mut(&mut self) -> &mut Self::Target {
355                self.set_changed();
356                #[cfg(feature = "track_change_detection")]
357                {
358                    *self.changed_by = Location::caller();
359                }
360                self.value
361            }
362        }
363
364        impl<$($generics),* $(: $traits)?> AsMut<$target> for $name<$($generics),*> {
365            #[inline]
366            fn as_mut(&mut self) -> &mut $target {
367                self.deref_mut()
368            }
369        }
370    };
371}
372
373macro_rules! impl_methods {
374    ($name:ident < $( $generics:tt ),+ >, $target:ty, $($traits:ident)?) => {
375        impl<$($generics),* : ?Sized $(+ $traits)?> $name<$($generics),*> {
376            /// Consume `self` and return a mutable reference to the
377            /// contained value while marking `self` as "changed".
378            #[inline]
379            pub fn into_inner(mut self) -> &'w mut $target {
380                self.set_changed();
381                self.value
382            }
383
384            /// Returns a `Mut<>` with a smaller lifetime.
385            /// This is useful if you have `&mut
386            #[doc = stringify!($name)]
387            /// <T>`, but you need a `Mut<T>`.
388            pub fn reborrow(&mut self) -> Mut<'_, $target> {
389                Mut {
390                    value: self.value,
391                    ticks: TicksMut {
392                        added: self.ticks.added,
393                        changed: self.ticks.changed,
394                        last_run: self.ticks.last_run,
395                        this_run: self.ticks.this_run,
396                    },
397                    #[cfg(feature = "track_change_detection")]
398                    changed_by: self.changed_by,
399                }
400            }
401
402            /// Maps to an inner value by applying a function to the contained reference, without flagging a change.
403            ///
404            /// You should never modify the argument passed to the closure -- if you want to modify the data
405            /// without flagging a change, consider using [`DetectChangesMut::bypass_change_detection`] to make your intent explicit.
406            ///
407            /// ```
408            /// # use bevy_ecs::prelude::*;
409            /// # #[derive(PartialEq)] pub struct Vec2;
410            /// # impl Vec2 { pub const ZERO: Self = Self; }
411            /// # #[derive(Component)] pub struct Transform { translation: Vec2 }
412            /// // When run, zeroes the translation of every entity.
413            /// fn reset_positions(mut transforms: Query<&mut Transform>) {
414            ///     for transform in &mut transforms {
415            ///         // We pinky promise not to modify `t` within the closure.
416            ///         // Breaking this promise will result in logic errors, but will never cause undefined behavior.
417            ///         let mut translation = transform.map_unchanged(|t| &mut t.translation);
418            ///         // Only reset the translation if it isn't already zero;
419            ///         translation.set_if_neq(Vec2::ZERO);
420            ///     }
421            /// }
422            /// # bevy_ecs::system::assert_is_system(reset_positions);
423            /// ```
424            pub fn map_unchanged<U: ?Sized>(self, f: impl FnOnce(&mut $target) -> &mut U) -> Mut<'w, U> {
425                Mut {
426                    value: f(self.value),
427                    ticks: self.ticks,
428                    #[cfg(feature = "track_change_detection")]
429                    changed_by: self.changed_by,
430                }
431            }
432
433            /// Optionally maps to an inner value by applying a function to the contained reference.
434            /// This is useful in a situation where you need to convert a `Mut<T>` to a `Mut<U>`, but only if `T` contains `U`.
435            ///
436            /// As with `map_unchanged`, you should never modify the argument passed to the closure.
437            pub fn filter_map_unchanged<U: ?Sized>(self, f: impl FnOnce(&mut $target) -> Option<&mut U>) -> Option<Mut<'w, U>> {
438                let value = f(self.value);
439                value.map(|value| Mut {
440                    value,
441                    ticks: self.ticks,
442                    #[cfg(feature = "track_change_detection")]
443                    changed_by: self.changed_by,
444                })
445            }
446
447            /// Allows you access to the dereferenced value of this pointer without immediately
448            /// triggering change detection.
449            pub fn as_deref_mut(&mut self) -> Mut<'_, <$target as Deref>::Target>
450                where $target: DerefMut
451            {
452                self.reborrow().map_unchanged(|v| v.deref_mut())
453            }
454
455        }
456    };
457}
458
459macro_rules! impl_debug {
460    ($name:ident < $( $generics:tt ),+ >, $($traits:ident)?) => {
461        impl<$($generics),* : ?Sized $(+ $traits)?> core::fmt::Debug for $name<$($generics),*>
462            where T: core::fmt::Debug
463        {
464            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
465                f.debug_tuple(stringify!($name))
466                    .field(&self.value)
467                    .finish()
468            }
469        }
470
471    };
472}
473
474#[derive(Clone)]
475pub(crate) struct Ticks<'w> {
476    pub(crate) added: &'w Tick,
477    pub(crate) changed: &'w Tick,
478    pub(crate) last_run: Tick,
479    pub(crate) this_run: Tick,
480}
481
482impl<'w> Ticks<'w> {
483    /// # Safety
484    /// This should never alias the underlying ticks with a mutable one such as `TicksMut`.
485    #[inline]
486    pub(crate) unsafe fn from_tick_cells(
487        cells: TickCells<'w>,
488        last_run: Tick,
489        this_run: Tick,
490    ) -> Self {
491        Self {
492            // SAFETY: Caller ensures there is no mutable access to the cell.
493            added: unsafe { cells.added.deref() },
494            // SAFETY: Caller ensures there is no mutable access to the cell.
495            changed: unsafe { cells.changed.deref() },
496            last_run,
497            this_run,
498        }
499    }
500}
501
502pub(crate) struct TicksMut<'w> {
503    pub(crate) added: &'w mut Tick,
504    pub(crate) changed: &'w mut Tick,
505    pub(crate) last_run: Tick,
506    pub(crate) this_run: Tick,
507}
508
509impl<'w> TicksMut<'w> {
510    /// # Safety
511    /// This should never alias the underlying ticks. All access must be unique.
512    #[inline]
513    pub(crate) unsafe fn from_tick_cells(
514        cells: TickCells<'w>,
515        last_run: Tick,
516        this_run: Tick,
517    ) -> Self {
518        Self {
519            // SAFETY: Caller ensures there is no alias to the cell.
520            added: unsafe { cells.added.deref_mut() },
521            // SAFETY: Caller ensures there is no alias to the cell.
522            changed: unsafe { cells.changed.deref_mut() },
523            last_run,
524            this_run,
525        }
526    }
527}
528
529impl<'w> From<TicksMut<'w>> for Ticks<'w> {
530    fn from(ticks: TicksMut<'w>) -> Self {
531        Ticks {
532            added: ticks.added,
533            changed: ticks.changed,
534            last_run: ticks.last_run,
535            this_run: ticks.this_run,
536        }
537    }
538}
539
540/// Shared borrow of a [`Resource`].
541///
542/// See the [`Resource`] documentation for usage.
543///
544/// If you need a unique mutable borrow, use [`ResMut`] instead.
545///
546/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.
547/// This will cause a panic, but can be configured to do nothing or warn once.
548///
549/// Use [`Option<Res<T>>`] instead if the resource might not always exist.
550pub struct Res<'w, T: ?Sized + Resource> {
551    pub(crate) value: &'w T,
552    pub(crate) ticks: Ticks<'w>,
553    #[cfg(feature = "track_change_detection")]
554    pub(crate) changed_by: &'static Location<'static>,
555}
556
557impl<'w, T: Resource> Res<'w, T> {
558    /// Copies a reference to a resource.
559    ///
560    /// Note that unless you actually need an instance of `Res<T>`, you should
561    /// prefer to just convert it to `&T` which can be freely copied.
562    #[allow(clippy::should_implement_trait)]
563    pub fn clone(this: &Self) -> Self {
564        Self {
565            value: this.value,
566            ticks: this.ticks.clone(),
567            #[cfg(feature = "track_change_detection")]
568            changed_by: this.changed_by,
569        }
570    }
571
572    /// Due to lifetime limitations of the `Deref` trait, this method can be used to obtain a
573    /// reference of the [`Resource`] with a lifetime bound to `'w` instead of the lifetime of the
574    /// struct itself.
575    pub fn into_inner(self) -> &'w T {
576        self.value
577    }
578}
579
580impl<'w, T: Resource> From<ResMut<'w, T>> for Res<'w, T> {
581    fn from(res: ResMut<'w, T>) -> Self {
582        Self {
583            value: res.value,
584            ticks: res.ticks.into(),
585            #[cfg(feature = "track_change_detection")]
586            changed_by: res.changed_by,
587        }
588    }
589}
590
591impl<'w, T: Resource> From<Res<'w, T>> for Ref<'w, T> {
592    /// Convert a `Res` into a `Ref`. This allows keeping the change-detection feature of `Ref`
593    /// while losing the specificity of `Res` for resources.
594    fn from(res: Res<'w, T>) -> Self {
595        Self {
596            value: res.value,
597            ticks: res.ticks,
598            #[cfg(feature = "track_change_detection")]
599            changed_by: res.changed_by,
600        }
601    }
602}
603
604impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>
605where
606    &'a T: IntoIterator,
607{
608    type Item = <&'a T as IntoIterator>::Item;
609    type IntoIter = <&'a T as IntoIterator>::IntoIter;
610
611    fn into_iter(self) -> Self::IntoIter {
612        self.value.into_iter()
613    }
614}
615change_detection_impl!(Res<'w, T>, T, Resource);
616impl_debug!(Res<'w, T>, Resource);
617
618/// Unique mutable borrow of a [`Resource`].
619///
620/// See the [`Resource`] documentation for usage.
621///
622/// If you need a shared borrow, use [`Res`] instead.
623///
624/// This [`SystemParam`](crate::system::SystemParam) fails validation if resource doesn't exist.
625/// /// This will cause a panic, but can be configured to do nothing or warn once.
626///
627/// Use [`Option<ResMut<T>>`] instead if the resource might not always exist.
628pub struct ResMut<'w, T: ?Sized + Resource> {
629    pub(crate) value: &'w mut T,
630    pub(crate) ticks: TicksMut<'w>,
631    #[cfg(feature = "track_change_detection")]
632    pub(crate) changed_by: &'w mut &'static Location<'static>,
633}
634
635impl<'w, 'a, T: Resource> IntoIterator for &'a ResMut<'w, T>
636where
637    &'a T: IntoIterator,
638{
639    type Item = <&'a T as IntoIterator>::Item;
640    type IntoIter = <&'a T as IntoIterator>::IntoIter;
641
642    fn into_iter(self) -> Self::IntoIter {
643        self.value.into_iter()
644    }
645}
646
647impl<'w, 'a, T: Resource> IntoIterator for &'a mut ResMut<'w, T>
648where
649    &'a mut T: IntoIterator,
650{
651    type Item = <&'a mut T as IntoIterator>::Item;
652    type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
653
654    fn into_iter(self) -> Self::IntoIter {
655        self.set_changed();
656        self.value.into_iter()
657    }
658}
659
660change_detection_impl!(ResMut<'w, T>, T, Resource);
661change_detection_mut_impl!(ResMut<'w, T>, T, Resource);
662impl_methods!(ResMut<'w, T>, T, Resource);
663impl_debug!(ResMut<'w, T>, Resource);
664
665impl<'w, T: Resource> From<ResMut<'w, T>> for Mut<'w, T> {
666    /// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
667    /// while losing the specificity of `ResMut` for resources.
668    fn from(other: ResMut<'w, T>) -> Mut<'w, T> {
669        Mut {
670            value: other.value,
671            ticks: other.ticks,
672            #[cfg(feature = "track_change_detection")]
673            changed_by: other.changed_by,
674        }
675    }
676}
677
678/// Unique borrow of a non-[`Send`] resource.
679///
680/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
681/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
682/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
683/// over to another thread.
684///
685/// This [`SystemParam`](crate::system::SystemParam) fails validation if non-send resource doesn't exist.
686/// /// This will cause a panic, but can be configured to do nothing or warn once.
687///
688/// Use [`Option<NonSendMut<T>>`] instead if the resource might not always exist.
689pub struct NonSendMut<'w, T: ?Sized + 'static> {
690    pub(crate) value: &'w mut T,
691    pub(crate) ticks: TicksMut<'w>,
692    #[cfg(feature = "track_change_detection")]
693    pub(crate) changed_by: &'w mut &'static Location<'static>,
694}
695
696change_detection_impl!(NonSendMut<'w, T>, T,);
697change_detection_mut_impl!(NonSendMut<'w, T>, T,);
698impl_methods!(NonSendMut<'w, T>, T,);
699impl_debug!(NonSendMut<'w, T>,);
700
701impl<'w, T: 'static> From<NonSendMut<'w, T>> for Mut<'w, T> {
702    /// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
703    /// while losing the specificity of `NonSendMut`.
704    fn from(other: NonSendMut<'w, T>) -> Mut<'w, T> {
705        Mut {
706            value: other.value,
707            ticks: other.ticks,
708            #[cfg(feature = "track_change_detection")]
709            changed_by: other.changed_by,
710        }
711    }
712}
713
714/// Shared borrow of an entity's component with access to change detection.
715/// Similar to [`Mut`] but is immutable and so doesn't require unique access.
716///
717/// # Examples
718///
719/// These two systems produce the same output.
720///
721/// ```
722/// # use bevy_ecs::change_detection::DetectChanges;
723/// # use bevy_ecs::query::{Changed, With};
724/// # use bevy_ecs::system::Query;
725/// # use bevy_ecs::world::Ref;
726/// # use bevy_ecs_macros::Component;
727/// # #[derive(Component)]
728/// # struct MyComponent;
729///
730/// fn how_many_changed_1(query: Query<(), Changed<MyComponent>>) {
731///     println!("{} changed", query.iter().count());
732/// }
733///
734/// fn how_many_changed_2(query: Query<Ref<MyComponent>>) {
735///     println!("{} changed", query.iter().filter(|c| c.is_changed()).count());
736/// }
737/// ```
738pub struct Ref<'w, T: ?Sized> {
739    pub(crate) value: &'w T,
740    pub(crate) ticks: Ticks<'w>,
741    #[cfg(feature = "track_change_detection")]
742    pub(crate) changed_by: &'static Location<'static>,
743}
744
745impl<'w, T: ?Sized> Ref<'w, T> {
746    /// Returns the reference wrapped by this type. The reference is allowed to outlive `self`, which makes this method more flexible than simply borrowing `self`.
747    pub fn into_inner(self) -> &'w T {
748        self.value
749    }
750
751    /// Map `Ref` to a different type using `f`.
752    ///
753    /// This doesn't do anything else than call `f` on the wrapped value.
754    /// This is equivalent to [`Mut::map_unchanged`].
755    pub fn map<U: ?Sized>(self, f: impl FnOnce(&T) -> &U) -> Ref<'w, U> {
756        Ref {
757            value: f(self.value),
758            ticks: self.ticks,
759            #[cfg(feature = "track_change_detection")]
760            changed_by: self.changed_by,
761        }
762    }
763
764    /// Create a new `Ref` using provided values.
765    ///
766    /// This is an advanced feature, `Ref`s are designed to be _created_ by
767    /// engine-internal code and _consumed_ by end-user code.
768    ///
769    /// - `value` - The value wrapped by `Ref`.
770    /// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
771    /// - `changed` - A [`Tick`] that stores the last time the wrapped value was changed.
772    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
773    ///    as a reference to determine whether the wrapped value is newly added or changed.
774    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
775    pub fn new(
776        value: &'w T,
777        added: &'w Tick,
778        changed: &'w Tick,
779        last_run: Tick,
780        this_run: Tick,
781        #[cfg(feature = "track_change_detection")] caller: &'static Location<'static>,
782    ) -> Ref<'w, T> {
783        Ref {
784            value,
785            ticks: Ticks {
786                added,
787                changed,
788                last_run,
789                this_run,
790            },
791            #[cfg(feature = "track_change_detection")]
792            changed_by: caller,
793        }
794    }
795}
796
797impl<'w, 'a, T> IntoIterator for &'a Ref<'w, T>
798where
799    &'a T: IntoIterator,
800{
801    type Item = <&'a T as IntoIterator>::Item;
802    type IntoIter = <&'a T as IntoIterator>::IntoIter;
803
804    fn into_iter(self) -> Self::IntoIter {
805        self.value.into_iter()
806    }
807}
808change_detection_impl!(Ref<'w, T>, T,);
809impl_debug!(Ref<'w, T>,);
810
811/// Unique mutable borrow of an entity's component or of a resource.
812///
813/// This can be used in queries to opt into change detection on both their mutable and immutable forms, as opposed to
814/// `&mut T`, which only provides access to change detection while in its mutable form:
815///
816/// ```rust
817/// # use bevy_ecs::prelude::*;
818/// # use bevy_ecs::query::QueryData;
819/// #
820/// #[derive(Component, Clone)]
821/// struct Name(String);
822///
823/// #[derive(Component, Clone, Copy)]
824/// struct Health(f32);
825///
826/// #[derive(Component, Clone, Copy)]
827/// struct Position {
828///     x: f32,
829///     y: f32,
830/// };
831///
832/// #[derive(Component, Clone, Copy)]
833/// struct Player {
834///     id: usize,
835/// };
836///
837/// #[derive(QueryData)]
838/// #[query_data(mutable)]
839/// struct PlayerQuery {
840///     id: &'static Player,
841///
842///     // Reacting to `PlayerName` changes is expensive, so we need to enable change detection when reading it.
843///     name: Mut<'static, Name>,
844///
845///     health: &'static mut Health,
846///     position: &'static mut Position,
847/// }
848///
849/// fn update_player_avatars(players_query: Query<PlayerQuery>) {
850///     // The item returned by the iterator is of type `PlayerQueryReadOnlyItem`.
851///     for player in players_query.iter() {
852///         if player.name.is_changed() {
853///             // Update the player's name. This clones a String, and so is more expensive.
854///             update_player_name(player.id, player.name.clone());
855///         }
856///
857///         // Update the health bar.
858///         update_player_health(player.id, *player.health);
859///
860///         // Update the player's position.
861///         update_player_position(player.id, *player.position);
862///     }
863/// }
864///
865/// # bevy_ecs::system::assert_is_system(update_player_avatars);
866///
867/// # fn update_player_name(player: &Player, new_name: Name) {}
868/// # fn update_player_health(player: &Player, new_health: Health) {}
869/// # fn update_player_position(player: &Player, new_position: Position) {}
870/// ```
871pub struct Mut<'w, T: ?Sized> {
872    pub(crate) value: &'w mut T,
873    pub(crate) ticks: TicksMut<'w>,
874    #[cfg(feature = "track_change_detection")]
875    pub(crate) changed_by: &'w mut &'static Location<'static>,
876}
877
878impl<'w, T: ?Sized> Mut<'w, T> {
879    /// Creates a new change-detection enabled smart pointer.
880    /// In almost all cases you do not need to call this method manually,
881    /// as instances of `Mut` will be created by engine-internal code.
882    ///
883    /// Many use-cases of this method would be better served by [`Mut::map_unchanged`]
884    /// or [`Mut::reborrow`].
885    ///
886    /// - `value` - The value wrapped by this smart pointer.
887    /// - `added` - A [`Tick`] that stores the tick when the wrapped value was created.
888    /// - `last_changed` - A [`Tick`] that stores the last time the wrapped value was changed.
889    ///   This will be updated to the value of `change_tick` if the returned smart pointer
890    ///   is modified.
891    /// - `last_run` - A [`Tick`], occurring before `this_run`, which is used
892    ///   as a reference to determine whether the wrapped value is newly added or changed.
893    /// - `this_run` - A [`Tick`] corresponding to the current point in time -- "now".
894    pub fn new(
895        value: &'w mut T,
896        added: &'w mut Tick,
897        last_changed: &'w mut Tick,
898        last_run: Tick,
899        this_run: Tick,
900        #[cfg(feature = "track_change_detection")] caller: &'w mut &'static Location<'static>,
901    ) -> Self {
902        Self {
903            value,
904            ticks: TicksMut {
905                added,
906                changed: last_changed,
907                last_run,
908                this_run,
909            },
910            #[cfg(feature = "track_change_detection")]
911            changed_by: caller,
912        }
913    }
914}
915
916impl<'w, T: ?Sized> From<Mut<'w, T>> for Ref<'w, T> {
917    fn from(mut_ref: Mut<'w, T>) -> Self {
918        Self {
919            value: mut_ref.value,
920            ticks: mut_ref.ticks.into(),
921            #[cfg(feature = "track_change_detection")]
922            changed_by: mut_ref.changed_by,
923        }
924    }
925}
926
927impl<'w, 'a, T> IntoIterator for &'a Mut<'w, T>
928where
929    &'a T: IntoIterator,
930{
931    type Item = <&'a T as IntoIterator>::Item;
932    type IntoIter = <&'a T as IntoIterator>::IntoIter;
933
934    fn into_iter(self) -> Self::IntoIter {
935        self.value.into_iter()
936    }
937}
938
939impl<'w, 'a, T> IntoIterator for &'a mut Mut<'w, T>
940where
941    &'a mut T: IntoIterator,
942{
943    type Item = <&'a mut T as IntoIterator>::Item;
944    type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
945
946    fn into_iter(self) -> Self::IntoIter {
947        self.set_changed();
948        self.value.into_iter()
949    }
950}
951
952change_detection_impl!(Mut<'w, T>, T,);
953change_detection_mut_impl!(Mut<'w, T>, T,);
954impl_methods!(Mut<'w, T>, T,);
955impl_debug!(Mut<'w, T>,);
956
957/// Unique mutable borrow of resources or an entity's component.
958///
959/// Similar to [`Mut`], but not generic over the component type, instead
960/// exposing the raw pointer as a `*mut ()`.
961///
962/// Usually you don't need to use this and can instead use the APIs returning a
963/// [`Mut`], but in situations where the types are not known at compile time
964/// or are defined outside of rust this can be used.
965pub struct MutUntyped<'w> {
966    pub(crate) value: PtrMut<'w>,
967    pub(crate) ticks: TicksMut<'w>,
968    #[cfg(feature = "track_change_detection")]
969    pub(crate) changed_by: &'w mut &'static Location<'static>,
970}
971
972impl<'w> MutUntyped<'w> {
973    /// Returns the pointer to the value, marking it as changed.
974    ///
975    /// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
976    #[inline]
977    pub fn into_inner(mut self) -> PtrMut<'w> {
978        self.set_changed();
979        self.value
980    }
981
982    /// Returns a [`MutUntyped`] with a smaller lifetime.
983    /// This is useful if you have `&mut MutUntyped`, but you need a `MutUntyped`.
984    #[inline]
985    pub fn reborrow(&mut self) -> MutUntyped {
986        MutUntyped {
987            value: self.value.reborrow(),
988            ticks: TicksMut {
989                added: self.ticks.added,
990                changed: self.ticks.changed,
991                last_run: self.ticks.last_run,
992                this_run: self.ticks.this_run,
993            },
994            #[cfg(feature = "track_change_detection")]
995            changed_by: self.changed_by,
996        }
997    }
998
999    /// Returns `true` if this value was changed or mutably dereferenced
1000    /// either since a specific change tick.
1001    pub fn has_changed_since(&self, tick: Tick) -> bool {
1002        self.ticks.changed.is_newer_than(tick, self.ticks.this_run)
1003    }
1004
1005    /// Returns a pointer to the value without taking ownership of this smart pointer, marking it as changed.
1006    ///
1007    /// In order to avoid marking the value as changed, you need to call [`bypass_change_detection`](DetectChangesMut::bypass_change_detection).
1008    #[inline]
1009    pub fn as_mut(&mut self) -> PtrMut<'_> {
1010        self.set_changed();
1011        self.value.reborrow()
1012    }
1013
1014    /// Returns an immutable pointer to the value without taking ownership.
1015    #[inline]
1016    pub fn as_ref(&self) -> Ptr<'_> {
1017        self.value.as_ref()
1018    }
1019
1020    /// Turn this [`MutUntyped`] into a [`Mut`] by mapping the inner [`PtrMut`] to another value,
1021    /// without flagging a change.
1022    /// This function is the untyped equivalent of [`Mut::map_unchanged`].
1023    ///
1024    /// You should never modify the argument passed to the closure – if you want to modify the data without flagging a change, consider using [`bypass_change_detection`](DetectChangesMut::bypass_change_detection) to make your intent explicit.
1025    ///
1026    /// If you know the type of the value you can do
1027    /// ```no_run
1028    /// # use bevy_ecs::change_detection::{Mut, MutUntyped};
1029    /// # let mut_untyped: MutUntyped = unimplemented!();
1030    /// // SAFETY: ptr is of type `u8`
1031    /// mut_untyped.map_unchanged(|ptr| unsafe { ptr.deref_mut::<u8>() });
1032    /// ```
1033    /// If you have a [`ReflectFromPtr`](bevy_reflect::ReflectFromPtr) that you know belongs to this [`MutUntyped`],
1034    /// you can do
1035    /// ```no_run
1036    /// # use bevy_ecs::change_detection::{Mut, MutUntyped};
1037    /// # let mut_untyped: MutUntyped = unimplemented!();
1038    /// # let reflect_from_ptr: bevy_reflect::ReflectFromPtr = unimplemented!();
1039    /// // SAFETY: from the context it is known that `ReflectFromPtr` was made for the type of the `MutUntyped`
1040    /// mut_untyped.map_unchanged(|ptr| unsafe { reflect_from_ptr.as_reflect_mut(ptr) });
1041    /// ```
1042    pub fn map_unchanged<T: ?Sized>(self, f: impl FnOnce(PtrMut<'w>) -> &'w mut T) -> Mut<'w, T> {
1043        Mut {
1044            value: f(self.value),
1045            ticks: self.ticks,
1046            #[cfg(feature = "track_change_detection")]
1047            changed_by: self.changed_by,
1048        }
1049    }
1050
1051    /// Transforms this [`MutUntyped`] into a [`Mut<T>`] with the same lifetime.
1052    ///
1053    /// # Safety
1054    /// - `T` must be the erased pointee type for this [`MutUntyped`].
1055    pub unsafe fn with_type<T>(self) -> Mut<'w, T> {
1056        Mut {
1057            // SAFETY: `value` is `Aligned` and caller ensures the pointee type is `T`.
1058            value: unsafe { self.value.deref_mut() },
1059            ticks: self.ticks,
1060            // SAFETY: `caller` is `Aligned`.
1061            #[cfg(feature = "track_change_detection")]
1062            changed_by: self.changed_by,
1063        }
1064    }
1065}
1066
1067impl<'w> DetectChanges for MutUntyped<'w> {
1068    #[inline]
1069    fn is_added(&self) -> bool {
1070        self.ticks
1071            .added
1072            .is_newer_than(self.ticks.last_run, self.ticks.this_run)
1073    }
1074
1075    #[inline]
1076    fn is_changed(&self) -> bool {
1077        self.ticks
1078            .changed
1079            .is_newer_than(self.ticks.last_run, self.ticks.this_run)
1080    }
1081
1082    #[inline]
1083    fn last_changed(&self) -> Tick {
1084        *self.ticks.changed
1085    }
1086
1087    #[inline]
1088    #[cfg(feature = "track_change_detection")]
1089    fn changed_by(&self) -> &'static Location<'static> {
1090        self.changed_by
1091    }
1092}
1093
1094impl<'w> DetectChangesMut for MutUntyped<'w> {
1095    type Inner = PtrMut<'w>;
1096
1097    #[inline]
1098    #[track_caller]
1099    fn set_changed(&mut self) {
1100        *self.ticks.changed = self.ticks.this_run;
1101        #[cfg(feature = "track_change_detection")]
1102        {
1103            *self.changed_by = Location::caller();
1104        }
1105    }
1106
1107    #[inline]
1108    #[track_caller]
1109    fn set_last_changed(&mut self, last_changed: Tick) {
1110        *self.ticks.changed = last_changed;
1111        #[cfg(feature = "track_change_detection")]
1112        {
1113            *self.changed_by = Location::caller();
1114        }
1115    }
1116
1117    #[inline]
1118    #[track_caller]
1119    fn bypass_change_detection(&mut self) -> &mut Self::Inner {
1120        &mut self.value
1121    }
1122}
1123
1124impl core::fmt::Debug for MutUntyped<'_> {
1125    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1126        f.debug_tuple("MutUntyped")
1127            .field(&self.value.as_ptr())
1128            .finish()
1129    }
1130}
1131
1132impl<'w, T> From<Mut<'w, T>> for MutUntyped<'w> {
1133    fn from(value: Mut<'w, T>) -> Self {
1134        MutUntyped {
1135            value: value.value.into(),
1136            ticks: value.ticks,
1137            #[cfg(feature = "track_change_detection")]
1138            changed_by: value.changed_by,
1139        }
1140    }
1141}
1142
1143/// A type alias to [`&'static Location<'static>`](std::panic::Location) when the `track_change_detection` feature is
1144/// enabled, and the unit type `()` when it is not.
1145///
1146/// This is primarily used in places where `#[cfg(...)]` attributes are not allowed, such as
1147/// function return types. Because unit is a zero-sized type, it is the equivalent of not using a
1148/// `Location` at all.
1149///
1150/// Please use this type sparingly: prefer normal `#[cfg(...)]` attributes when possible.
1151#[cfg(feature = "track_change_detection")]
1152pub(crate) type MaybeLocation = &'static Location<'static>;
1153
1154/// A type alias to [`&'static Location<'static>`](std::panic::Location) when the `track_change_detection` feature is
1155/// enabled, and the unit type `()` when it is not.
1156///
1157/// This is primarily used in places where `#[cfg(...)]` attributes are not allowed, such as
1158/// function return types. Because unit is a zero-sized type, it is the equivalent of not using a
1159/// `Location` at all.
1160///
1161/// Please use this type sparingly: prefer normal `#[cfg(...)]` attributes when possible.
1162#[cfg(not(feature = "track_change_detection"))]
1163pub(crate) type MaybeLocation = ();
1164
1165/// A type alias to `&UnsafeCell<&'static Location<'static>>` when the `track_change_detection`
1166/// feature is enabled, and the unit type `()` when it is not.
1167///
1168/// See [`MaybeLocation`] for further information.
1169#[cfg(feature = "track_change_detection")]
1170pub(crate) type MaybeUnsafeCellLocation<'a> = &'a UnsafeCell<&'static Location<'static>>;
1171
1172/// A type alias to `&UnsafeCell<&'static Location<'static>>` when the `track_change_detection`
1173/// feature is enabled, and the unit type `()` when it is not.
1174///
1175/// See [`MaybeLocation`] for further information.
1176#[cfg(not(feature = "track_change_detection"))]
1177pub(crate) type MaybeUnsafeCellLocation<'a> = ();
1178
1179/// A type alias to `ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>` when the
1180/// `track_change_detection` feature is enabled, and the unit type `()` when it is not.
1181///
1182/// See [`MaybeLocation`] for further information.
1183#[cfg(feature = "track_change_detection")]
1184pub(crate) type MaybeThinSlicePtrLocation<'w> =
1185    ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>;
1186
1187/// A type alias to `ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>` when the
1188/// `track_change_detection` feature is enabled, and the unit type `()` when it is not.
1189///
1190/// See [`MaybeLocation`] for further information.
1191#[cfg(not(feature = "track_change_detection"))]
1192pub(crate) type MaybeThinSlicePtrLocation<'w> = ();
1193
1194#[cfg(test)]
1195mod tests {
1196    use bevy_ecs_macros::Resource;
1197    use bevy_ptr::PtrMut;
1198    use bevy_reflect::{FromType, ReflectFromPtr};
1199    use core::ops::{Deref, DerefMut};
1200    #[cfg(feature = "track_change_detection")]
1201    use core::panic::Location;
1202
1203    use crate::{
1204        self as bevy_ecs,
1205        change_detection::{
1206            Mut, NonSendMut, Ref, ResMut, TicksMut, CHECK_TICK_THRESHOLD, MAX_CHANGE_AGE,
1207        },
1208        component::{Component, ComponentTicks, Tick},
1209        system::{IntoSystem, Single, System},
1210        world::World,
1211    };
1212
1213    use super::{DetectChanges, DetectChangesMut, MutUntyped};
1214
1215    #[derive(Component, PartialEq)]
1216    struct C;
1217
1218    #[derive(Resource)]
1219    struct R;
1220
1221    #[derive(Resource, PartialEq)]
1222    struct R2(u8);
1223
1224    impl Deref for R2 {
1225        type Target = u8;
1226        fn deref(&self) -> &u8 {
1227            &self.0
1228        }
1229    }
1230
1231    impl DerefMut for R2 {
1232        fn deref_mut(&mut self) -> &mut u8 {
1233            &mut self.0
1234        }
1235    }
1236
1237    #[test]
1238    fn change_expiration() {
1239        fn change_detected(query: Option<Single<Ref<C>>>) -> bool {
1240            query.unwrap().is_changed()
1241        }
1242
1243        fn change_expired(query: Option<Single<Ref<C>>>) -> bool {
1244            query.unwrap().is_changed()
1245        }
1246
1247        let mut world = World::new();
1248
1249        // component added: 1, changed: 1
1250        world.spawn(C);
1251
1252        let mut change_detected_system = IntoSystem::into_system(change_detected);
1253        let mut change_expired_system = IntoSystem::into_system(change_expired);
1254        change_detected_system.initialize(&mut world);
1255        change_expired_system.initialize(&mut world);
1256
1257        // world: 1, system last ran: 0, component changed: 1
1258        // The spawn will be detected since it happened after the system "last ran".
1259        assert!(change_detected_system.run((), &mut world));
1260
1261        // world: 1 + MAX_CHANGE_AGE
1262        let change_tick = world.change_tick.get_mut();
1263        *change_tick = change_tick.wrapping_add(MAX_CHANGE_AGE);
1264
1265        // Both the system and component appeared `MAX_CHANGE_AGE` ticks ago.
1266        // Since we clamp things to `MAX_CHANGE_AGE` for determinism,
1267        // `ComponentTicks::is_changed` will now see `MAX_CHANGE_AGE > MAX_CHANGE_AGE`
1268        // and return `false`.
1269        assert!(!change_expired_system.run((), &mut world));
1270    }
1271
1272    #[test]
1273    fn change_tick_wraparound() {
1274        let mut world = World::new();
1275        world.last_change_tick = Tick::new(u32::MAX);
1276        *world.change_tick.get_mut() = 0;
1277
1278        // component added: 0, changed: 0
1279        world.spawn(C);
1280
1281        world.increment_change_tick();
1282
1283        // Since the world is always ahead, as long as changes can't get older than `u32::MAX` (which we ensure),
1284        // the wrapping difference will always be positive, so wraparound doesn't matter.
1285        let mut query = world.query::<Ref<C>>();
1286        assert!(query.single(&world).is_changed());
1287    }
1288
1289    #[test]
1290    fn change_tick_scan() {
1291        let mut world = World::new();
1292
1293        // component added: 1, changed: 1
1294        world.spawn(C);
1295
1296        // a bunch of stuff happens, the component is now older than `MAX_CHANGE_AGE`
1297        *world.change_tick.get_mut() += MAX_CHANGE_AGE + CHECK_TICK_THRESHOLD;
1298        let change_tick = world.change_tick();
1299
1300        let mut query = world.query::<Ref<C>>();
1301        for tracker in query.iter(&world) {
1302            let ticks_since_insert = change_tick.relative_to(*tracker.ticks.added).get();
1303            let ticks_since_change = change_tick.relative_to(*tracker.ticks.changed).get();
1304            assert!(ticks_since_insert > MAX_CHANGE_AGE);
1305            assert!(ticks_since_change > MAX_CHANGE_AGE);
1306        }
1307
1308        // scan change ticks and clamp those at risk of overflow
1309        world.check_change_ticks();
1310
1311        for tracker in query.iter(&world) {
1312            let ticks_since_insert = change_tick.relative_to(*tracker.ticks.added).get();
1313            let ticks_since_change = change_tick.relative_to(*tracker.ticks.changed).get();
1314            assert_eq!(ticks_since_insert, MAX_CHANGE_AGE);
1315            assert_eq!(ticks_since_change, MAX_CHANGE_AGE);
1316        }
1317    }
1318
1319    #[test]
1320    fn mut_from_res_mut() {
1321        let mut component_ticks = ComponentTicks {
1322            added: Tick::new(1),
1323            changed: Tick::new(2),
1324        };
1325        let ticks = TicksMut {
1326            added: &mut component_ticks.added,
1327            changed: &mut component_ticks.changed,
1328            last_run: Tick::new(3),
1329            this_run: Tick::new(4),
1330        };
1331        let mut res = R {};
1332        #[cfg(feature = "track_change_detection")]
1333        let mut caller = Location::caller();
1334
1335        let res_mut = ResMut {
1336            value: &mut res,
1337            ticks,
1338            #[cfg(feature = "track_change_detection")]
1339            changed_by: &mut caller,
1340        };
1341
1342        let into_mut: Mut<R> = res_mut.into();
1343        assert_eq!(1, into_mut.ticks.added.get());
1344        assert_eq!(2, into_mut.ticks.changed.get());
1345        assert_eq!(3, into_mut.ticks.last_run.get());
1346        assert_eq!(4, into_mut.ticks.this_run.get());
1347    }
1348
1349    #[test]
1350    fn mut_new() {
1351        let mut component_ticks = ComponentTicks {
1352            added: Tick::new(1),
1353            changed: Tick::new(3),
1354        };
1355        let mut res = R {};
1356        #[cfg(feature = "track_change_detection")]
1357        let mut caller = Location::caller();
1358
1359        let val = Mut::new(
1360            &mut res,
1361            &mut component_ticks.added,
1362            &mut component_ticks.changed,
1363            Tick::new(2), // last_run
1364            Tick::new(4), // this_run
1365            #[cfg(feature = "track_change_detection")]
1366            &mut caller,
1367        );
1368
1369        assert!(!val.is_added());
1370        assert!(val.is_changed());
1371    }
1372
1373    #[test]
1374    fn mut_from_non_send_mut() {
1375        let mut component_ticks = ComponentTicks {
1376            added: Tick::new(1),
1377            changed: Tick::new(2),
1378        };
1379        let ticks = TicksMut {
1380            added: &mut component_ticks.added,
1381            changed: &mut component_ticks.changed,
1382            last_run: Tick::new(3),
1383            this_run: Tick::new(4),
1384        };
1385        let mut res = R {};
1386        #[cfg(feature = "track_change_detection")]
1387        let mut caller = Location::caller();
1388
1389        let non_send_mut = NonSendMut {
1390            value: &mut res,
1391            ticks,
1392            #[cfg(feature = "track_change_detection")]
1393            changed_by: &mut caller,
1394        };
1395
1396        let into_mut: Mut<R> = non_send_mut.into();
1397        assert_eq!(1, into_mut.ticks.added.get());
1398        assert_eq!(2, into_mut.ticks.changed.get());
1399        assert_eq!(3, into_mut.ticks.last_run.get());
1400        assert_eq!(4, into_mut.ticks.this_run.get());
1401    }
1402
1403    #[test]
1404    fn map_mut() {
1405        use super::*;
1406        struct Outer(i64);
1407
1408        let last_run = Tick::new(2);
1409        let this_run = Tick::new(3);
1410        let mut component_ticks = ComponentTicks {
1411            added: Tick::new(1),
1412            changed: Tick::new(2),
1413        };
1414        let ticks = TicksMut {
1415            added: &mut component_ticks.added,
1416            changed: &mut component_ticks.changed,
1417            last_run,
1418            this_run,
1419        };
1420
1421        let mut outer = Outer(0);
1422        #[cfg(feature = "track_change_detection")]
1423        let mut caller = Location::caller();
1424
1425        let ptr = Mut {
1426            value: &mut outer,
1427            ticks,
1428            #[cfg(feature = "track_change_detection")]
1429            changed_by: &mut caller,
1430        };
1431        assert!(!ptr.is_changed());
1432
1433        // Perform a mapping operation.
1434        let mut inner = ptr.map_unchanged(|x| &mut x.0);
1435        assert!(!inner.is_changed());
1436
1437        // Mutate the inner value.
1438        *inner = 64;
1439        assert!(inner.is_changed());
1440        // Modifying one field of a component should flag a change for the entire component.
1441        assert!(component_ticks.is_changed(last_run, this_run));
1442    }
1443
1444    #[test]
1445    fn set_if_neq() {
1446        let mut world = World::new();
1447
1448        world.insert_resource(R2(0));
1449        // Resources are Changed when first added
1450        world.increment_change_tick();
1451        // This is required to update world::last_change_tick
1452        world.clear_trackers();
1453
1454        let mut r = world.resource_mut::<R2>();
1455        assert!(!r.is_changed(), "Resource must begin unchanged.");
1456
1457        r.set_if_neq(R2(0));
1458        assert!(
1459            !r.is_changed(),
1460            "Resource must not be changed after setting to the same value."
1461        );
1462
1463        r.set_if_neq(R2(3));
1464        assert!(
1465            r.is_changed(),
1466            "Resource must be changed after setting to a different value."
1467        );
1468    }
1469
1470    #[test]
1471    fn as_deref_mut() {
1472        let mut world = World::new();
1473
1474        world.insert_resource(R2(0));
1475        // Resources are Changed when first added
1476        world.increment_change_tick();
1477        // This is required to update world::last_change_tick
1478        world.clear_trackers();
1479
1480        let mut r = world.resource_mut::<R2>();
1481        assert!(!r.is_changed(), "Resource must begin unchanged.");
1482
1483        let mut r = r.as_deref_mut();
1484        assert!(
1485            !r.is_changed(),
1486            "Dereferencing should not mark the item as changed yet"
1487        );
1488
1489        r.set_if_neq(3);
1490        assert!(
1491            r.is_changed(),
1492            "Resource must be changed after setting to a different value."
1493        );
1494    }
1495
1496    #[test]
1497    fn mut_untyped_to_reflect() {
1498        let last_run = Tick::new(2);
1499        let this_run = Tick::new(3);
1500        let mut component_ticks = ComponentTicks {
1501            added: Tick::new(1),
1502            changed: Tick::new(2),
1503        };
1504        let ticks = TicksMut {
1505            added: &mut component_ticks.added,
1506            changed: &mut component_ticks.changed,
1507            last_run,
1508            this_run,
1509        };
1510
1511        let mut value: i32 = 5;
1512        #[cfg(feature = "track_change_detection")]
1513        let mut caller = Location::caller();
1514
1515        let value = MutUntyped {
1516            value: PtrMut::from(&mut value),
1517            ticks,
1518            #[cfg(feature = "track_change_detection")]
1519            changed_by: &mut caller,
1520        };
1521
1522        let reflect_from_ptr = <ReflectFromPtr as FromType<i32>>::from_type();
1523
1524        let mut new = value.map_unchanged(|ptr| {
1525            // SAFETY: The underlying type of `ptr` matches `reflect_from_ptr`.
1526            let value = unsafe { reflect_from_ptr.as_reflect_mut(ptr) };
1527            value
1528        });
1529
1530        assert!(!new.is_changed());
1531
1532        new.reflect_mut();
1533
1534        assert!(new.is_changed());
1535    }
1536
1537    #[test]
1538    fn mut_untyped_from_mut() {
1539        let mut component_ticks = ComponentTicks {
1540            added: Tick::new(1),
1541            changed: Tick::new(2),
1542        };
1543        let ticks = TicksMut {
1544            added: &mut component_ticks.added,
1545            changed: &mut component_ticks.changed,
1546            last_run: Tick::new(3),
1547            this_run: Tick::new(4),
1548        };
1549        let mut c = C {};
1550        #[cfg(feature = "track_change_detection")]
1551        let mut caller = Location::caller();
1552
1553        let mut_typed = Mut {
1554            value: &mut c,
1555            ticks,
1556            #[cfg(feature = "track_change_detection")]
1557            changed_by: &mut caller,
1558        };
1559
1560        let into_mut: MutUntyped = mut_typed.into();
1561        assert_eq!(1, into_mut.ticks.added.get());
1562        assert_eq!(2, into_mut.ticks.changed.get());
1563        assert_eq!(3, into_mut.ticks.last_run.get());
1564        assert_eq!(4, into_mut.ticks.this_run.get());
1565    }
1566}