@@ -920,15 +920,21 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
920
920
}
921
921
922
922
fn update_component_access ( state : & Self :: State , access : & mut FilteredAccess < ComponentId > ) {
923
- T :: update_component_access ( & state. state , access) ;
923
+ // We don't want to add the `with`/`without` of `T` as `Option<T>` will match things regardless of
924
+ // `T`'s filters. for example `Query<(Option<&U>, &mut V)>` will match every entity with a `V` component
925
+ // regardless of whether it has a `U` component. If we dont do this the query will not conflict with
926
+ // `Query<&mut V, Without<U>>` which would be unsound.
927
+ let mut intermediate = access. clone ( ) ;
928
+ T :: update_component_access ( & state. state , & mut intermediate) ;
929
+ access. extend_access ( & intermediate) ;
924
930
}
925
931
926
932
fn update_archetype_component_access (
927
933
state : & Self :: State ,
928
934
archetype : & Archetype ,
929
935
access : & mut Access < ArchetypeComponentId > ,
930
936
) {
931
- if state. state . matches_archetype ( archetype) {
937
+ if state. matches_archetype ( archetype) {
932
938
T :: update_archetype_component_access ( & state. state , archetype, access) ;
933
939
}
934
940
}
@@ -958,27 +964,6 @@ impl<T: FetchState> FetchState for OptionState<T> {
958
964
}
959
965
}
960
966
961
- fn update_component_access ( & self , access : & mut FilteredAccess < ComponentId > ) {
962
- // We don't want to add the `with`/`without` of `T` as `Option<T>` will match things regardless of
963
- // `T`'s filters. for example `Query<(Option<&U>, &mut V)>` will match every entity with a `V` component
964
- // regardless of whether it has a `U` component. If we dont do this the query will not conflict with
965
- // `Query<&mut V, Without<U>>` which would be unsound.
966
- let mut intermediate = access. clone ( ) ;
967
- self . state . update_component_access ( & mut intermediate) ;
968
- access. extend_access ( & intermediate) ;
969
- }
970
-
971
- fn update_archetype_component_access (
972
- & self ,
973
- archetype : & Archetype ,
974
- access : & mut Access < ArchetypeComponentId > ,
975
- ) {
976
- if self . state . matches_archetype ( archetype) {
977
- self . state
978
- . update_archetype_component_access ( archetype, access) ;
979
- }
980
- }
981
-
982
967
fn matches_archetype ( & self , _archetype : & Archetype ) -> bool {
983
968
true
984
969
}
@@ -1529,47 +1514,6 @@ macro_rules! impl_anytuple_fetch {
1529
1514
AnyOf ( ( $( $name:: init( _world) , ) * ) )
1530
1515
}
1531
1516
1532
- fn update_component_access( & self , _access: & mut FilteredAccess <ComponentId >) {
1533
- let ( $( $name, ) * ) = & self . 0 ;
1534
-
1535
- // We do not unconditionally add `$name`'s `with`/`without` accesses to `_access`
1536
- // as this would be unsound. For example the following two queries should conflict:
1537
- // - Query<(AnyOf<(&A, ())>, &mut B)>
1538
- // - Query<&mut B, Without<A>>
1539
- //
1540
- // If we were to unconditionally add `$name`'s `with`/`without` accesses then `AnyOf<(&A, ())>`
1541
- // would have a `With<A>` access which is incorrect as this `WorldQuery` will match entities that
1542
- // do not have the `A` component. This is the same logic as the `Or<...>: WorldQuery` impl.
1543
- //
1544
- // The correct thing to do here is to only add a `with`/`without` access to `_access` if all
1545
- // `$name` params have that `with`/`without` access. More jargony put- we add the intersection
1546
- // of all `with`/`without` accesses of the `$name` params to `_access`.
1547
- let mut _intersected_access = _access. clone( ) ;
1548
- let mut _not_first = false ;
1549
- $(
1550
- if _not_first {
1551
- let mut intermediate = _access. clone( ) ;
1552
- $name. update_component_access( & mut intermediate) ;
1553
- _intersected_access. extend_intersect_filter( & intermediate) ;
1554
- _intersected_access. extend_access( & intermediate) ;
1555
- } else {
1556
- $name. update_component_access( & mut _intersected_access) ;
1557
- _not_first = true ;
1558
- }
1559
- ) *
1560
-
1561
- * _access = _intersected_access;
1562
- }
1563
-
1564
- fn update_archetype_component_access( & self , _archetype: & Archetype , _access: & mut Access <ArchetypeComponentId >) {
1565
- let ( $( $name, ) * ) = & self . 0 ;
1566
- $(
1567
- if $name. matches_archetype( _archetype) {
1568
- $name. update_archetype_component_access( _archetype, _access) ;
1569
- }
1570
- ) *
1571
- }
1572
-
1573
1517
fn matches_archetype( & self , _archetype: & Archetype ) -> bool {
1574
1518
let ( $( $name, ) * ) = & self . 0 ;
1575
1519
false $( || $name. matches_archetype( _archetype) ) *
@@ -1597,7 +1541,35 @@ macro_rules! impl_anytuple_fetch {
1597
1541
1598
1542
fn update_component_access( state: & Self :: State , _access: & mut FilteredAccess <ComponentId >) {
1599
1543
let ( $( $name, ) * ) = & state. 0 ;
1600
- $( $name:: update_component_access( $name, _access) ; ) *
1544
+
1545
+ // We do not unconditionally add `$name`'s `with`/`without` accesses to `_access`
1546
+ // as this would be unsound. For example the following two queries should conflict:
1547
+ // - Query<(AnyOf<(&A, ())>, &mut B)>
1548
+ // - Query<&mut B, Without<A>>
1549
+ //
1550
+ // If we were to unconditionally add `$name`'s `with`/`without` accesses then `AnyOf<(&A, ())>`
1551
+ // would have a `With<A>` access which is incorrect as this `WorldQuery` will match entities that
1552
+ // do not have the `A` component. This is the same logic as the `Or<...>: WorldQuery` impl.
1553
+ //
1554
+ // The correct thing to do here is to only add a `with`/`without` access to `_access` if all
1555
+ // `$name` params have that `with`/`without` access. More jargony put- we add the intersection
1556
+ // of all `with`/`without` accesses of the `$name` params to `_access`.
1557
+ let mut _intersected_access = _access. clone( ) ;
1558
+ let mut _not_first = false ;
1559
+ $(
1560
+ if _not_first {
1561
+ let mut intermediate = _access. clone( ) ;
1562
+ $name:: update_component_access( $name, & mut intermediate) ;
1563
+ _intersected_access. extend_intersect_filter( & intermediate) ;
1564
+ _intersected_access. extend_access( & intermediate) ;
1565
+ } else {
1566
+
1567
+ $name:: update_component_access( $name, & mut _intersected_access) ;
1568
+ _not_first = true ;
1569
+ }
1570
+ ) *
1571
+
1572
+ * _access = _intersected_access;
1601
1573
}
1602
1574
1603
1575
fn update_archetype_component_access( state: & Self :: State , _archetype: & Archetype , _access: & mut Access <ArchetypeComponentId >) {
0 commit comments