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:
		
							parent
							
								
									4f57f380c7
								
							
						
					
					
						commit
						670c4c1852
					
				@ -125,10 +125,17 @@ pub trait DetectChangesMut: DetectChanges {
 | 
			
		||||
    ///
 | 
			
		||||
    /// This is useful to ensure change detection is only triggered when the underlying value
 | 
			
		||||
    /// 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
 | 
			
		||||
        Self: Deref<Target = Target> + DerefMut<Target = Target>,
 | 
			
		||||
        Target: PartialEq;
 | 
			
		||||
        Self::Inner: Sized + PartialEq,
 | 
			
		||||
    {
 | 
			
		||||
        let old = self.bypass_change_detection();
 | 
			
		||||
        if *old != value {
 | 
			
		||||
            *old = value;
 | 
			
		||||
            self.set_changed();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! change_detection_impl {
 | 
			
		||||
@ -195,19 +202,6 @@ macro_rules! change_detection_mut_impl {
 | 
			
		||||
            fn bypass_change_detection(&mut self) -> &mut Self::Inner {
 | 
			
		||||
                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),*> {
 | 
			
		||||
@ -685,19 +679,6 @@ impl<'a> DetectChangesMut for MutUntyped<'a> {
 | 
			
		||||
    fn bypass_change_detection(&mut self) -> &mut Self::Inner {
 | 
			
		||||
        &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<'_> {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user