mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
AnyOf soundness fix (#14013)
# Objective Fixes https://github.com/bevyengine/bevy/issues/13993 PR inspired by https://github.com/bevyengine/bevy/pull/14007 to accomplish the same thing, but maybe in a clearer fashion. @Gingeh feel free to take my changes and add them to your PR, I don't want to steal any credit --------- Co-authored-by: Gingeh <39150378+Gingeh@users.noreply.github.com> Co-authored-by: Bob Gardner <rgardner@inworld.ai> Co-authored-by: Martín Maita <47983254+mnmaita@users.noreply.github.com>
This commit is contained in:
parent
82f01569e8
commit
f89f7f306c
2 changed files with 62 additions and 5 deletions
|
@ -1862,16 +1862,20 @@ macro_rules! impl_anytuple_fetch {
|
|||
}
|
||||
|
||||
fn update_component_access(state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {
|
||||
let ($($name,)*) = state;
|
||||
|
||||
let mut _new_access = _access.clone();
|
||||
|
||||
// update the access (add the read/writes)
|
||||
<($(Option<$name>,)*)>::update_component_access(state, _access);
|
||||
|
||||
// update the filters (Or<(With<$name>,)>)
|
||||
let ($($name,)*) = state;
|
||||
let mut _not_first = false;
|
||||
$(
|
||||
if _not_first {
|
||||
let mut intermediate = _access.clone();
|
||||
// we use an intermediate access because we only want to update the filters, not the access
|
||||
let mut intermediate = FilteredAccess::default();
|
||||
$name::update_component_access($name, &mut intermediate);
|
||||
_new_access.append_or(&intermediate);
|
||||
_new_access.extend_access(&intermediate);
|
||||
} else {
|
||||
$name::update_component_access($name, &mut _new_access);
|
||||
_new_access.required = _access.required.clone();
|
||||
|
@ -1879,7 +1883,7 @@ macro_rules! impl_anytuple_fetch {
|
|||
}
|
||||
)*
|
||||
|
||||
*_access = _new_access;
|
||||
_access.filter_sets = _new_access.filter_sets;
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
fn init_state(world: &mut World) -> Self::State {
|
||||
|
|
|
@ -556,6 +556,51 @@ mod tests {
|
|||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn any_of_working() {
|
||||
fn sys(_: Query<AnyOf<(&mut A, &B)>>) {}
|
||||
let mut world = World::default();
|
||||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "&bevy_ecs::system::tests::A conflicts with a previous access in this query."]
|
||||
fn any_of_with_mut_and_ref() {
|
||||
fn sys(_: Query<AnyOf<(&mut A, &A)>>) {}
|
||||
let mut world = World::default();
|
||||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "&mut bevy_ecs::system::tests::A conflicts with a previous access in this query."]
|
||||
fn any_of_with_ref_and_mut() {
|
||||
fn sys(_: Query<AnyOf<(&A, &mut A)>>) {}
|
||||
let mut world = World::default();
|
||||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "&bevy_ecs::system::tests::A conflicts with a previous access in this query."]
|
||||
fn any_of_with_mut_and_option() {
|
||||
fn sys(_: Query<AnyOf<(&mut A, Option<&A>)>>) {}
|
||||
let mut world = World::default();
|
||||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn any_of_with_entity_and_mut() {
|
||||
fn sys(_: Query<AnyOf<(Entity, &mut A)>>) {}
|
||||
let mut world = World::default();
|
||||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn any_of_with_empty_and_mut() {
|
||||
fn sys(_: Query<AnyOf<((), &mut A)>>) {}
|
||||
let mut world = World::default();
|
||||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "error[B0001]"]
|
||||
fn any_of_has_no_filter_with() {
|
||||
|
@ -564,6 +609,14 @@ mod tests {
|
|||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "&mut bevy_ecs::system::tests::A conflicts with a previous access in this query."]
|
||||
fn any_of_with_conflicting() {
|
||||
fn sys(_: Query<AnyOf<(&mut A, &mut A)>>) {}
|
||||
let mut world = World::default();
|
||||
run_system(&mut world, sys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn any_of_has_filter_with_when_both_have_it() {
|
||||
fn sys(_: Query<(AnyOf<(&A, &A)>, &mut B)>, _: Query<&mut B, Without<A>>) {}
|
||||
|
|
Loading…
Reference in a new issue