@@ -431,78 +431,58 @@ impl<T: SparseSetIndex> Access<T> {
431431
432432    /// Adds all access from `other`. 
433433     pub  fn  extend ( & mut  self ,  other :  & Access < T > )  { 
434-         let  component_read_and_writes_inverted =
435-             self . component_read_and_writes_inverted  || other. component_read_and_writes_inverted ; 
436-         let  component_writes_inverted =
437-             self . component_writes_inverted  || other. component_writes_inverted ; 
438- 
439-         match  ( 
440-             self . component_read_and_writes_inverted , 
434+         invertible_union_with ( 
435+             & mut  self . component_read_and_writes , 
436+             & mut  self . component_read_and_writes_inverted , 
437+             & other. component_read_and_writes , 
441438            other. component_read_and_writes_inverted , 
442-         )  { 
443-             ( true ,  true )  => { 
444-                 self . component_read_and_writes 
445-                     . intersect_with ( & other. component_read_and_writes ) ; 
446-             } 
447-             ( true ,  false )  => { 
448-                 self . component_read_and_writes 
449-                     . difference_with ( & other. component_read_and_writes ) ; 
450-             } 
451-             ( false ,  true )  => { 
452-                 // We have to grow here because the new bits are going to get flipped to 1. 
453-                 self . component_read_and_writes . grow ( 
454-                     self . component_read_and_writes 
455-                         . len ( ) 
456-                         . max ( other. component_read_and_writes . len ( ) ) , 
457-                 ) ; 
458-                 self . component_read_and_writes . toggle_range ( ..) ; 
459-                 self . component_read_and_writes 
460-                     . intersect_with ( & other. component_read_and_writes ) ; 
461-             } 
462-             ( false ,  false )  => { 
463-                 self . component_read_and_writes 
464-                     . union_with ( & other. component_read_and_writes ) ; 
465-             } 
466-         } 
467- 
468-         match  ( 
469-             self . component_writes_inverted , 
439+         ) ; 
440+         invertible_union_with ( 
441+             & mut  self . component_writes , 
442+             & mut  self . component_writes_inverted , 
443+             & other. component_writes , 
470444            other. component_writes_inverted , 
471-         )  { 
472-             ( true ,  true )  => { 
473-                 self . component_writes 
474-                     . intersect_with ( & other. component_writes ) ; 
475-             } 
476-             ( true ,  false )  => { 
477-                 self . component_writes 
478-                     . difference_with ( & other. component_writes ) ; 
479-             } 
480-             ( false ,  true )  => { 
481-                 // We have to grow here because the new bits are going to get flipped to 1. 
482-                 self . component_writes . grow ( 
483-                     self . component_writes 
484-                         . len ( ) 
485-                         . max ( other. component_writes . len ( ) ) , 
486-                 ) ; 
487-                 self . component_writes . toggle_range ( ..) ; 
488-                 self . component_writes 
489-                     . intersect_with ( & other. component_writes ) ; 
490-             } 
491-             ( false ,  false )  => { 
492-                 self . component_writes . union_with ( & other. component_writes ) ; 
493-             } 
494-         } 
445+         ) ; 
495446
496447        self . reads_all_resources  = self . reads_all_resources  || other. reads_all_resources ; 
497448        self . writes_all_resources  = self . writes_all_resources  || other. writes_all_resources ; 
498-         self . component_read_and_writes_inverted  = component_read_and_writes_inverted; 
499-         self . component_writes_inverted  = component_writes_inverted; 
500449        self . resource_read_and_writes 
501450            . union_with ( & other. resource_read_and_writes ) ; 
502451        self . resource_writes . union_with ( & other. resource_writes ) ; 
503452        self . archetypal . union_with ( & other. archetypal ) ; 
504453    } 
505454
455+     /// Removes any access from `self` that would conflict with `other`. 
456+      /// This removes any reads and writes for any component written by `other`, 
457+      /// and removes any writes for any component read by `other`. 
458+      pub  fn  remove_conflicting_access ( & mut  self ,  other :  & Access < T > )  { 
459+         invertible_difference_with ( 
460+             & mut  self . component_read_and_writes , 
461+             & mut  self . component_read_and_writes_inverted , 
462+             & other. component_writes , 
463+             other. component_writes_inverted , 
464+         ) ; 
465+         invertible_difference_with ( 
466+             & mut  self . component_writes , 
467+             & mut  self . component_writes_inverted , 
468+             & other. component_read_and_writes , 
469+             other. component_read_and_writes_inverted , 
470+         ) ; 
471+ 
472+         if  other. reads_all_resources  { 
473+             self . writes_all_resources  = false ; 
474+             self . resource_writes . clear ( ) ; 
475+         } 
476+         if  other. writes_all_resources  { 
477+             self . reads_all_resources  = false ; 
478+             self . resource_read_and_writes . clear ( ) ; 
479+         } 
480+         self . resource_read_and_writes 
481+             . difference_with ( & other. resource_writes ) ; 
482+         self . resource_writes 
483+             . difference_with ( & other. resource_read_and_writes ) ; 
484+     } 
485+ 
506486    /// Returns `true` if the access and `other` can be active at the same time, 
507487     /// only looking at their component access. 
508488     /// 
@@ -840,6 +820,55 @@ impl<T: SparseSetIndex> Access<T> {
840820    } 
841821} 
842822
823+ /// Performs an in-place union of `other` into `self`, where either set may be inverted. 
824+ /// 
825+ /// Each set corresponds to a `FixedBitSet` if `inverted` is `false`, 
826+ /// or to the infinite (co-finite) complement of the `FixedBitSet` if `inverted` is `true`. 
827+ /// 
828+ /// This updates the `self` set to include any elements in the `other` set. 
829+ /// Note that this may change `self_inverted` to `true` if we add an infinite 
830+ /// set to a finite one, resulting in a new infinite set. 
831+ fn  invertible_union_with ( 
832+     self_set :  & mut  FixedBitSet , 
833+     self_inverted :  & mut  bool , 
834+     other_set :  & FixedBitSet , 
835+     other_inverted :  bool , 
836+ )  { 
837+     match  ( * self_inverted,  other_inverted)  { 
838+         ( true ,  true )  => self_set. intersect_with ( other_set) , 
839+         ( true ,  false )  => self_set. difference_with ( other_set) , 
840+         ( false ,  true )  => { 
841+             * self_inverted = true ; 
842+             // We have to grow here because the new bits are going to get flipped to 1. 
843+             self_set. grow ( other_set. len ( ) ) ; 
844+             self_set. toggle_range ( ..) ; 
845+             self_set. intersect_with ( other_set) ; 
846+         } 
847+         ( false ,  false )  => self_set. union_with ( other_set) , 
848+     } 
849+ } 
850+ 
851+ /// Performs an in-place set difference of `other` from `self`, where either set may be inverted. 
852+ /// 
853+ /// Each set corresponds to a `FixedBitSet` if `inverted` is `false`, 
854+ /// or to the infinite (co-finite) complement of the `FixedBitSet` if `inverted` is `true`. 
855+ /// 
856+ /// This updates the `self` set to remove any elements in the `other` set. 
857+ /// Note that this may change `self_inverted` to `false` if we remove an 
858+ /// infinite set from another infinite one, resulting in a finite difference. 
859+ fn  invertible_difference_with ( 
860+     self_set :  & mut  FixedBitSet , 
861+     self_inverted :  & mut  bool , 
862+     other_set :  & FixedBitSet , 
863+     other_inverted :  bool , 
864+ )  { 
865+     // We can share the implementation of `invertible_union_with` with some algebra: 
866+     // A - B = A & !B = !(!A | B) 
867+     * self_inverted = !* self_inverted; 
868+     invertible_union_with ( self_set,  self_inverted,  other_set,  other_inverted) ; 
869+     * self_inverted = !* self_inverted; 
870+ } 
871+ 
843872/// Error returned when attempting to iterate over items included in an [`Access`] 
844873/// if the access excludes items rather than including them. 
845874#[ derive( Clone ,  Copy ,  PartialEq ,  Eq ,  Debug ,  Error ) ]  
@@ -1428,6 +1457,7 @@ impl<T: SparseSetIndex> Default for FilteredAccessSet<T> {
14281457
14291458#[ cfg( test) ]  
14301459mod  tests { 
1460+     use  super :: { invertible_difference_with,  invertible_union_with} ; 
14311461    use  crate :: query:: { 
14321462        access:: AccessFilters ,  Access ,  AccessConflicts ,  ComponentAccessKind ,  FilteredAccess , 
14331463        FilteredAccessSet ,  UnboundedAccessError , 
@@ -1770,4 +1800,99 @@ mod tests {
17701800            } ) , 
17711801        ) ; 
17721802    } 
1803+ 
1804+     /// Create a `FixedBitSet` with a given number of total bits and a given list of bits to set. 
1805+      /// Setting the number of bits is important in tests since the `PartialEq` impl checks that the length matches. 
1806+      fn  bit_set ( bits :  usize ,  iter :  impl  IntoIterator < Item  = usize > )  -> FixedBitSet  { 
1807+         let  mut  result = FixedBitSet :: with_capacity ( bits) ; 
1808+         result. extend ( iter) ; 
1809+         result
1810+     } 
1811+ 
1812+     #[ test]  
1813+     fn  invertible_union_with_tests ( )  { 
1814+         let  invertible_union = |mut  self_inverted :  bool ,  other_inverted :  bool | { 
1815+             // Check all four possible bit states: In both sets, the first, the second, or neither 
1816+             let  mut  self_set = bit_set ( 4 ,  [ 0 ,  1 ] ) ; 
1817+             let  other_set = bit_set ( 4 ,  [ 0 ,  2 ] ) ; 
1818+             invertible_union_with ( 
1819+                 & mut  self_set, 
1820+                 & mut  self_inverted, 
1821+                 & other_set, 
1822+                 other_inverted, 
1823+             ) ; 
1824+             ( self_set,  self_inverted) 
1825+         } ; 
1826+ 
1827+         // Check each combination of `inverted` flags 
1828+         let  ( s,  i)  = invertible_union ( false ,  false ) ; 
1829+         // [0, 1] | [0, 2] = [0, 1, 2] 
1830+         assert_eq ! ( ( s,  i) ,  ( bit_set( 4 ,  [ 0 ,  1 ,  2 ] ) ,  false ) ) ; 
1831+ 
1832+         let  ( s,  i)  = invertible_union ( false ,  true ) ; 
1833+         // [0, 1] | [1, 3, ...] = [0, 1, 3, ...] 
1834+         assert_eq ! ( ( s,  i) ,  ( bit_set( 4 ,  [ 2 ] ) ,  true ) ) ; 
1835+ 
1836+         let  ( s,  i)  = invertible_union ( true ,  false ) ; 
1837+         // [2, 3, ...] | [0, 2] = [0, 2, 3, ...] 
1838+         assert_eq ! ( ( s,  i) ,  ( bit_set( 4 ,  [ 1 ] ) ,  true ) ) ; 
1839+ 
1840+         let  ( s,  i)  = invertible_union ( true ,  true ) ; 
1841+         // [2, 3, ...] | [1, 3, ...] = [1, 2, 3, ...] 
1842+         assert_eq ! ( ( s,  i) ,  ( bit_set( 4 ,  [ 0 ] ) ,  true ) ) ; 
1843+     } 
1844+ 
1845+     #[ test]  
1846+     fn  invertible_union_with_different_lengths ( )  { 
1847+         // When adding a large inverted set to a small normal set, 
1848+         // make sure we invert the bits beyond the original length. 
1849+         // Failing to call `grow` before `toggle_range` would cause bit 1 to be zero, 
1850+         // which would incorrectly treat it as included in the output set. 
1851+         let  mut  self_set = bit_set ( 1 ,  [ 0 ] ) ; 
1852+         let  mut  self_inverted = false ; 
1853+         let  other_set = bit_set ( 3 ,  [ 0 ,  1 ] ) ; 
1854+         let  other_inverted = true ; 
1855+         invertible_union_with ( 
1856+             & mut  self_set, 
1857+             & mut  self_inverted, 
1858+             & other_set, 
1859+             other_inverted, 
1860+         ) ; 
1861+ 
1862+         // [0] | [2, ...] = [0, 2, ...] 
1863+         assert_eq ! ( ( self_set,  self_inverted) ,  ( bit_set( 3 ,  [ 1 ] ) ,  true ) ) ; 
1864+     } 
1865+ 
1866+     #[ test]  
1867+     fn  invertible_difference_with_tests ( )  { 
1868+         let  invertible_difference = |mut  self_inverted :  bool ,  other_inverted :  bool | { 
1869+             // Check all four possible bit states: In both sets, the first, the second, or neither 
1870+             let  mut  self_set = bit_set ( 4 ,  [ 0 ,  1 ] ) ; 
1871+             let  other_set = bit_set ( 4 ,  [ 0 ,  2 ] ) ; 
1872+             invertible_difference_with ( 
1873+                 & mut  self_set, 
1874+                 & mut  self_inverted, 
1875+                 & other_set, 
1876+                 other_inverted, 
1877+             ) ; 
1878+             ( self_set,  self_inverted) 
1879+         } ; 
1880+ 
1881+         // Check each combination of `inverted` flags 
1882+         let  ( s,  i)  = invertible_difference ( false ,  false ) ; 
1883+         // [0, 1] - [0, 2] = [1] 
1884+         assert_eq ! ( ( s,  i) ,  ( bit_set( 4 ,  [ 1 ] ) ,  false ) ) ; 
1885+ 
1886+         let  ( s,  i)  = invertible_difference ( false ,  true ) ; 
1887+         // [0, 1] - [1, 3, ...] = [0] 
1888+         assert_eq ! ( ( s,  i) ,  ( bit_set( 4 ,  [ 0 ] ) ,  false ) ) ; 
1889+ 
1890+         let  ( s,  i)  = invertible_difference ( true ,  false ) ; 
1891+         // [2, 3, ...] - [0, 2] = [3, ...] 
1892+         assert_eq ! ( ( s,  i) ,  ( bit_set( 4 ,  [ 0 ,  1 ,  2 ] ) ,  true ) ) ; 
1893+ 
1894+         let  ( s,  i)  = invertible_difference ( true ,  true ) ; 
1895+         // [2, 3, ...] - [1, 3, ...] = [2] 
1896+         assert_eq ! ( ( s,  i) ,  ( bit_set( 4 ,  [ 2 ] ) ,  false ) ) ; 
1897+     } 
17731898} 
0 commit comments