Use a default implementation for set_if_neq (#7660)

# Objective

While porting my crate `bevy_trait_query` to bevy 0.10, I ran into an issue with the `DetectChangesMut` trait. Due to the way that the `set_if_neq` method (added in #6853) is implemented, you are forced to write a nonsense implementation of it for dynamically sized types. This edge case shows up when implementing trait queries, since `DetectChangesMut` is implemented for `Mut<dyn Trait>`.

## Solution

Simplify the generics for `set_if_neq` and add the `where Self::Target: Sized` trait bound to it. Add a default implementation so implementers don't need to implement a method with nonsensical trait bounds.
This commit is contained in:
JoJoJet 2023-02-15 20:10:23 +00:00
parent 4f57f380c7
commit 670c4c1852

View File

@ -125,10 +125,17 @@ pub trait DetectChangesMut: DetectChanges {
/// ///
/// This is useful to ensure change detection is only triggered when the underlying value /// This is useful to ensure change detection is only triggered when the underlying value
/// changes, instead of every time [`DerefMut`] is used. /// changes, instead of every time [`DerefMut`] is used.
fn set_if_neq<Target>(&mut self, value: Target) #[inline]
fn set_if_neq(&mut self, value: Self::Inner)
where where
Self: Deref<Target = Target> + DerefMut<Target = Target>, Self::Inner: Sized + PartialEq,
Target: PartialEq; {
let old = self.bypass_change_detection();
if *old != value {
*old = value;
self.set_changed();
}
}
} }
macro_rules! change_detection_impl { macro_rules! change_detection_impl {
@ -195,19 +202,6 @@ macro_rules! change_detection_mut_impl {
fn bypass_change_detection(&mut self) -> &mut Self::Inner { fn bypass_change_detection(&mut self) -> &mut Self::Inner {
self.value self.value
} }
#[inline]
fn set_if_neq<Target>(&mut self, value: Target)
where
Self: Deref<Target = Target> + DerefMut<Target = Target>,
Target: PartialEq,
{
// This dereference is immutable, so does not trigger change detection
if *<Self as Deref>::deref(self) != value {
// `DerefMut` usage triggers change detection
*<Self as DerefMut>::deref_mut(self) = value;
}
}
} }
impl<$($generics),* : ?Sized $(+ $traits)?> DerefMut for $name<$($generics),*> { impl<$($generics),* : ?Sized $(+ $traits)?> DerefMut for $name<$($generics),*> {
@ -685,19 +679,6 @@ impl<'a> DetectChangesMut for MutUntyped<'a> {
fn bypass_change_detection(&mut self) -> &mut Self::Inner { fn bypass_change_detection(&mut self) -> &mut Self::Inner {
&mut self.value &mut self.value
} }
#[inline]
fn set_if_neq<Target>(&mut self, value: Target)
where
Self: Deref<Target = Target> + DerefMut<Target = Target>,
Target: PartialEq,
{
// This dereference is immutable, so does not trigger change detection
if *<Self as Deref>::deref(self) != value {
// `DerefMut` usage triggers change detection
*<Self as DerefMut>::deref_mut(self) = value;
}
}
} }
impl std::fmt::Debug for MutUntyped<'_> { impl std::fmt::Debug for MutUntyped<'_> {