Skip to content

Commit d478711

Browse files
committed
Conversion of ResMut and NonSendMut to Mut (#5438)
# Objective Enable treating components and resources equally, which can simplify the implementation of some systems where only the change detection feature is relevant and not the kind of object (resource or component). ## Solution Implement `From<ResMut<T>>` and `From<NonSendMut<T>>` for `Mut`. Since the 3 structs are similar, and only differ by their system param role, the conversion is trivial. --- ## Changelog Added - `From<ResMut>` and `From<NonSendMut>` for `Mut<T>`.
1 parent 231894a commit d478711

File tree

1 file changed

+75
-1
lines changed

1 file changed

+75
-1
lines changed

crates/bevy_ecs/src/change_detection.rs

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,17 @@ change_detection_impl!(ResMut<'a, T>, T, Resource);
185185
impl_into_inner!(ResMut<'a, T>, T, Resource);
186186
impl_debug!(ResMut<'a, T>, Resource);
187187

188+
impl<'a, T: Resource> From<ResMut<'a, T>> for Mut<'a, T> {
189+
/// Convert this `ResMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
190+
/// while losing the specificity of `ResMut` for resources.
191+
fn from(other: ResMut<'a, T>) -> Mut<'a, T> {
192+
Mut {
193+
value: other.value,
194+
ticks: other.ticks,
195+
}
196+
}
197+
}
198+
188199
/// Unique borrow of a non-[`Send`] resource.
189200
///
190201
/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the
@@ -206,6 +217,17 @@ change_detection_impl!(NonSendMut<'a, T>, T,);
206217
impl_into_inner!(NonSendMut<'a, T>, T,);
207218
impl_debug!(NonSendMut<'a, T>,);
208219

220+
impl<'a, T: Resource> From<NonSendMut<'a, T>> for Mut<'a, T> {
221+
/// Convert this `NonSendMut` into a `Mut`. This allows keeping the change-detection feature of `Mut`
222+
/// while losing the specificity of `NonSendMut`.
223+
fn from(other: NonSendMut<'a, T>) -> Mut<'a, T> {
224+
Mut {
225+
value: other.value,
226+
ticks: other.ticks,
227+
}
228+
}
229+
}
230+
209231
/// Unique mutable borrow of an entity's component
210232
pub struct Mut<'a, T> {
211233
pub(crate) value: &'a mut T,
@@ -286,7 +308,9 @@ impl std::fmt::Debug for MutUntyped<'_> {
286308
mod tests {
287309
use crate::{
288310
self as bevy_ecs,
289-
change_detection::{CHECK_TICK_THRESHOLD, MAX_CHANGE_AGE},
311+
change_detection::{
312+
ComponentTicks, Mut, NonSendMut, ResMut, Ticks, CHECK_TICK_THRESHOLD, MAX_CHANGE_AGE,
313+
},
290314
component::Component,
291315
query::ChangeTrackers,
292316
system::{IntoSystem, Query, System},
@@ -296,6 +320,8 @@ mod tests {
296320
#[derive(Component)]
297321
struct C;
298322

323+
struct R; // Resource
324+
299325
#[test]
300326
fn change_expiration() {
301327
fn change_detected(query: Query<ChangeTrackers<C>>) -> bool {
@@ -382,4 +408,52 @@ mod tests {
382408
assert!(ticks_since_change == MAX_CHANGE_AGE);
383409
}
384410
}
411+
412+
#[test]
413+
fn mut_from_res_mut() {
414+
let mut component_ticks = ComponentTicks {
415+
added: 1,
416+
changed: 2,
417+
};
418+
let ticks = Ticks {
419+
component_ticks: &mut component_ticks,
420+
last_change_tick: 3,
421+
change_tick: 4,
422+
};
423+
let mut res = R {};
424+
let res_mut = ResMut {
425+
value: &mut res,
426+
ticks,
427+
};
428+
429+
let into_mut: Mut<R> = res_mut.into();
430+
assert_eq!(1, into_mut.ticks.component_ticks.added);
431+
assert_eq!(2, into_mut.ticks.component_ticks.changed);
432+
assert_eq!(3, into_mut.ticks.last_change_tick);
433+
assert_eq!(4, into_mut.ticks.change_tick);
434+
}
435+
436+
#[test]
437+
fn mut_from_non_send_mut() {
438+
let mut component_ticks = ComponentTicks {
439+
added: 1,
440+
changed: 2,
441+
};
442+
let ticks = Ticks {
443+
component_ticks: &mut component_ticks,
444+
last_change_tick: 3,
445+
change_tick: 4,
446+
};
447+
let mut res = R {};
448+
let non_send_mut = NonSendMut {
449+
value: &mut res,
450+
ticks,
451+
};
452+
453+
let into_mut: Mut<R> = non_send_mut.into();
454+
assert_eq!(1, into_mut.ticks.component_ticks.added);
455+
assert_eq!(2, into_mut.ticks.component_ticks.changed);
456+
assert_eq!(3, into_mut.ticks.last_change_tick);
457+
assert_eq!(4, into_mut.ticks.change_tick);
458+
}
385459
}

0 commit comments

Comments
 (0)