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