@@ -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