diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index f518e0a0e73f7..2d1bab83b2882 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -462,21 +462,6 @@ pub fn derive_stage_label(input: TokenStream) -> TokenStream { derive_label(input, &trait_path, "stage_label") } -/// Generates an impl of the `AmbiguitySetLabel` trait. -/// -/// This works only for unit structs, or enums with only unit variants. -/// You may force a struct or variant to behave as if it were fieldless with `#[ambiguity_set_label(ignore_fields)]`. -#[proc_macro_derive(AmbiguitySetLabel, attributes(ambiguity_set_label))] -pub fn derive_ambiguity_set_label(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); - let mut trait_path = bevy_ecs_path(); - trait_path.segments.push(format_ident!("schedule").into()); - trait_path - .segments - .push(format_ident!("AmbiguitySetLabel").into()); - derive_label(input, &trait_path, "ambiguity_set_label") -} - /// Generates an impl of the `RunCriteriaLabel` trait. /// /// This works only for unit structs, or enums with only unit variants. diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index d129f4c833d68..124a7c7261369 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -34,9 +34,9 @@ pub mod prelude { event::{EventReader, EventWriter, Events}, query::{Added, AnyOf, ChangeTrackers, Changed, Or, QueryState, With, Without}, schedule::{ - AmbiguitySetLabel, ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, - RunCriteria, RunCriteriaDescriptorCoercion, RunCriteriaLabel, Schedule, Stage, - StageLabel, State, SystemLabel, SystemSet, SystemStage, + ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, RunCriteria, + RunCriteriaDescriptorCoercion, RunCriteriaLabel, Schedule, Stage, StageLabel, State, + SystemLabel, SystemSet, SystemStage, }, system::{ adapter as system_adapter, Commands, In, IntoChainSystem, IntoExclusiveSystem, diff --git a/crates/bevy_ecs/src/schedule/label.rs b/crates/bevy_ecs/src/schedule/label.rs index c9bccf8303084..c2f4d1fbfab7e 100644 --- a/crates/bevy_ecs/src/schedule/label.rs +++ b/crates/bevy_ecs/src/schedule/label.rs @@ -1,4 +1,4 @@ -pub use bevy_ecs_macros::{AmbiguitySetLabel, RunCriteriaLabel, StageLabel, SystemLabel}; +pub use bevy_ecs_macros::{RunCriteriaLabel, StageLabel, SystemLabel}; use bevy_utils::define_label; define_label!( @@ -13,12 +13,6 @@ define_label!( /// Strongly-typed identifier for a [`SystemLabel`]. SystemLabelId, ); -define_label!( - /// A strongly-typed class of labels used to identify sets of systems with intentionally ambiguous execution order. - AmbiguitySetLabel, - /// Strongly-typed identifier for an [`AmbiguitySetLabel`]. - AmbiguitySetLabelId, -); define_label!( /// A strongly-typed class of labels used to identify [run criteria](crate::schedule::RunCriteria). RunCriteriaLabel, diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index 9152df7466ffa..307f652b57fe2 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -713,20 +713,9 @@ fn process_systems( /// along with specific components that have triggered the warning. /// Systems must be topologically sorted beforehand. fn find_ambiguities(systems: &[impl SystemContainer]) -> Vec<(usize, usize, Vec)> { - let mut ambiguity_set_labels = HashMap::default(); - for set in systems.iter().flat_map(|c| c.ambiguity_sets()) { - let len = ambiguity_set_labels.len(); - ambiguity_set_labels.entry(set).or_insert(len); - } - let mut all_ambiguity_sets = Vec::::with_capacity(systems.len()); let mut all_dependencies = Vec::::with_capacity(systems.len()); let mut all_dependants = Vec::::with_capacity(systems.len()); for (index, container) in systems.iter().enumerate() { - let mut ambiguity_sets = FixedBitSet::with_capacity(ambiguity_set_labels.len()); - for set in container.ambiguity_sets() { - ambiguity_sets.insert(ambiguity_set_labels[set]); - } - all_ambiguity_sets.push(ambiguity_sets); let mut dependencies = FixedBitSet::with_capacity(systems.len()); for &dependency in container.dependencies() { dependencies.union_with(&all_dependencies[dependency]); @@ -765,9 +754,7 @@ fn find_ambiguities(systems: &[impl SystemContainer]) -> Vec<(usize, usize, Vec< for index_b in full_bitset.difference(&relations) // .take(index_a) { - if !processed.contains(index_b) - && all_ambiguity_sets[index_a].is_disjoint(&all_ambiguity_sets[index_b]) - { + if !processed.contains(index_b) { let a_access = systems[index_a].component_access(); let b_access = systems[index_b].component_access(); if let (Some(a), Some(b)) = (a_access, b_access) { @@ -972,13 +959,13 @@ impl Stage for SystemStage { #[cfg(test)] mod tests { - use bevy_ecs_macros::{AmbiguitySetLabel, RunCriteriaLabel}; + use bevy_ecs_macros::RunCriteriaLabel; use crate::{ schedule::{ ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, RunCriteria, RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage, SystemLabel, - SystemLabelId, SystemSet, SystemStage, + SystemSet, SystemStage, }, system::{In, IntoExclusiveSystem, Local, Query, ResMut}, world::World, @@ -1607,392 +1594,6 @@ mod tests { stage.run(&mut world); } - #[test] - fn ambiguity_detection() { - use super::{find_ambiguities, SystemContainer}; - - // these labels must all be the same type in order for - // `find_ambiguities_first_labels` to work - #[derive(SystemLabel)] - enum Labels { - A0, - A1, - A2, - A3, - A4, - A5, - A6, - A7, - } - use Labels::*; - - #[derive(AmbiguitySetLabel)] - enum SetLabels { - SetA, - SetB, - } - use SetLabels::*; - - fn find_ambiguities_first_labels( - systems: &[impl SystemContainer], - ) -> Vec<(SystemLabelId, SystemLabelId)> { - find_ambiguities(systems) - .drain(..) - .map(|(index_a, index_b, _conflicts)| { - ( - *systems[index_a] - .labels() - .iter() - .find(|a| a.type_id() == std::any::TypeId::of::()) - .unwrap(), - *systems[index_b] - .labels() - .iter() - .find(|a| a.type_id() == std::any::TypeId::of::()) - .unwrap(), - ) - }) - .collect() - } - - fn empty() {} - fn resource(_: ResMut) {} - fn component(_: Query<&mut W>) {} - - let mut world = World::new(); - - let mut stage = SystemStage::parallel() - .with_system(empty.label(A0)) - .with_system(empty.label(A1).after(A0)) - .with_system(empty.label(A2)) - .with_system(empty.label(A3).after(A2).before(A4)) - .with_system(empty.label(A4)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - assert_eq!(find_ambiguities(&stage.parallel).len(), 0); - - let mut stage = SystemStage::parallel() - .with_system(empty.label(A0)) - .with_system(component.label(A1).after(A0)) - .with_system(empty.label(A2)) - .with_system(empty.label(A3).after(A2).before(A4)) - .with_system(component.label(A4)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A1.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A1.as_label())) - ); - assert_eq!(ambiguities.len(), 1); - - let mut stage = SystemStage::parallel() - .with_system(empty.label(A0)) - .with_system(resource.label(A1).after(A0)) - .with_system(empty.label(A2)) - .with_system(empty.label(A3).after(A2).before(A4)) - .with_system(resource.label(A4)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A1.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A1.as_label())) - ); - assert_eq!(ambiguities.len(), 1); - - let mut stage = SystemStage::parallel() - .with_system(empty.label(A0)) - .with_system(resource.label(A1).after(A0)) - .with_system(empty.label(A2)) - .with_system(empty.label(A3).after(A2).before(A4)) - .with_system(component.label(A4)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - assert_eq!(find_ambiguities(&stage.parallel).len(), 0); - - let mut stage = SystemStage::parallel() - .with_system(component.label(A0)) - .with_system(resource.label(A1).after(A0)) - .with_system(empty.label(A2)) - .with_system(component.label(A3).after(A2).before(A4)) - .with_system(resource.label(A4)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A0.as_label(), A3.as_label())) - || ambiguities.contains(&(A3.as_label(), A0.as_label())) - ); - assert!( - ambiguities.contains(&(A1.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A1.as_label())) - ); - assert_eq!(ambiguities.len(), 2); - - let mut stage = SystemStage::parallel() - .with_system(component.label(A0)) - .with_system(resource.label(A1).after(A0).in_ambiguity_set(SetA)) - .with_system(empty.label(A2)) - .with_system(component.label(A3).after(A2).before(A4)) - .with_system(resource.label(A4).in_ambiguity_set(SetA)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A0.as_label(), A3.as_label())) - || ambiguities.contains(&(A3.as_label(), A0.as_label())) - ); - assert_eq!(ambiguities.len(), 1); - - let mut stage = SystemStage::parallel() - .with_system(component.label(A0).before(A2)) - .with_system(component.label(A1).before(A2)) - .with_system(component.label(A2)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A0.as_label(), A1.as_label())) - || ambiguities.contains(&(A1.as_label(), A0.as_label())) - ); - assert_eq!(ambiguities.len(), 1); - - let mut stage = SystemStage::parallel() - .with_system(component.label(A0)) - .with_system(component.label(A1).after(A0)) - .with_system(component.label(A2).after(A0)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A1.as_label(), A2.as_label())) - || ambiguities.contains(&(A2.as_label(), A1.as_label())) - ); - assert_eq!(ambiguities.len(), 1); - - let mut stage = SystemStage::parallel() - .with_system(component.label(A0).before(A1).before(A2)) - .with_system(component.label(A1)) - .with_system(component.label(A2)) - .with_system(component.label(A3).after(A1).after(A2)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A1.as_label(), A2.as_label())) - || ambiguities.contains(&(A2.as_label(), A1.as_label())) - ); - assert_eq!(ambiguities.len(), 1); - - let mut stage = SystemStage::parallel() - .with_system(component.label(A0).before(A1).before(A2)) - .with_system(component.label(A1).in_ambiguity_set(SetA)) - .with_system(component.label(A2).in_ambiguity_set(SetA)) - .with_system(component.label(A3).after(A1).after(A2)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert_eq!(ambiguities.len(), 0); - - let mut stage = SystemStage::parallel() - .with_system(component.label(A0).before(A1).before(A2)) - .with_system(component.label(A1).in_ambiguity_set(SetA)) - .with_system(component.label(A2).in_ambiguity_set(SetB)) - .with_system(component.label(A3).after(A1).after(A2)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A1.as_label(), A2.as_label())) - || ambiguities.contains(&(A2.as_label(), A1.as_label())) - ); - assert_eq!(ambiguities.len(), 1); - - let mut stage = SystemStage::parallel() - .with_system( - component - .label(A0) - .before(A1) - .before(A2) - .before(A3) - .before(A4), - ) - .with_system(component.label(A1)) - .with_system(component.label(A2)) - .with_system(component.label(A3)) - .with_system(component.label(A4)) - .with_system(component.label(A5).after(A1).after(A2).after(A3).after(A4)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A1.as_label(), A2.as_label())) - || ambiguities.contains(&(A2.as_label(), A1.as_label())) - ); - assert!( - ambiguities.contains(&(A1.as_label(), A3.as_label())) - || ambiguities.contains(&(A3.as_label(), A1.as_label())) - ); - assert!( - ambiguities.contains(&(A1.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A1.as_label())) - ); - assert!( - ambiguities.contains(&(A2.as_label(), A3.as_label())) - || ambiguities.contains(&(A3.as_label(), A2.as_label())) - ); - assert!( - ambiguities.contains(&(A2.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A2.as_label())) - ); - assert!( - ambiguities.contains(&(A3.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A3.as_label())) - ); - assert_eq!(ambiguities.len(), 6); - - let mut stage = SystemStage::parallel() - .with_system( - component - .label(A0) - .before(A1) - .before(A2) - .before(A3) - .before(A4), - ) - .with_system(component.label(A1).in_ambiguity_set(SetA)) - .with_system(component.label(A2).in_ambiguity_set(SetA)) - .with_system(component.label(A3).in_ambiguity_set(SetA)) - .with_system(component.label(A4).in_ambiguity_set(SetA)) - .with_system(component.label(A5).after(A1).after(A2).after(A3).after(A4)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert_eq!(ambiguities.len(), 0); - - let mut stage = SystemStage::parallel() - .with_system( - component - .label(A0) - .before(A1) - .before(A2) - .before(A3) - .before(A4), - ) - .with_system(component.label(A1).in_ambiguity_set(SetA)) - .with_system(component.label(A2).in_ambiguity_set(SetA)) - .with_system( - component - .label(A3) - .in_ambiguity_set(SetA) - .in_ambiguity_set(SetB), - ) - .with_system(component.label(A4).in_ambiguity_set(SetB)) - .with_system(component.label(A5).after(A1).after(A2).after(A3).after(A4)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.parallel); - assert!( - ambiguities.contains(&(A1.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A1.as_label())) - ); - assert!( - ambiguities.contains(&(A2.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A2.as_label())) - ); - assert_eq!(ambiguities.len(), 2); - - let mut stage = SystemStage::parallel() - .with_system(empty.exclusive_system().label(A0)) - .with_system(empty.exclusive_system().label(A1).after(A0)) - .with_system(empty.exclusive_system().label(A2).after(A1)) - .with_system(empty.exclusive_system().label(A3).after(A2)) - .with_system(empty.exclusive_system().label(A4).after(A3)) - .with_system(empty.exclusive_system().label(A5).after(A4)) - .with_system(empty.exclusive_system().label(A6).after(A5)) - .with_system(empty.exclusive_system().label(A7).after(A6)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - assert_eq!(find_ambiguities(&stage.exclusive_at_start).len(), 0); - - let mut stage = SystemStage::parallel() - .with_system(empty.exclusive_system().label(A0).before(A1).before(A3)) - .with_system(empty.exclusive_system().label(A1)) - .with_system(empty.exclusive_system().label(A2).after(A1)) - .with_system(empty.exclusive_system().label(A3)) - .with_system(empty.exclusive_system().label(A4).after(A3).before(A5)) - .with_system(empty.exclusive_system().label(A5)) - .with_system(empty.exclusive_system().label(A6).after(A2).after(A5)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.exclusive_at_start); - assert!( - ambiguities.contains(&(A1.as_label(), A3.as_label())) - || ambiguities.contains(&(A3.as_label(), A1.as_label())) - ); - assert!( - ambiguities.contains(&(A2.as_label(), A3.as_label())) - || ambiguities.contains(&(A3.as_label(), A2.as_label())) - ); - assert!( - ambiguities.contains(&(A1.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A1.as_label())) - ); - assert!( - ambiguities.contains(&(A2.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A2.as_label())) - ); - assert!( - ambiguities.contains(&(A1.as_label(), A5.as_label())) - || ambiguities.contains(&(A5.as_label(), A1.as_label())) - ); - assert!( - ambiguities.contains(&(A2.as_label(), A5.as_label())) - || ambiguities.contains(&(A5.as_label(), A2.as_label())) - ); - assert_eq!(ambiguities.len(), 6); - - let mut stage = SystemStage::parallel() - .with_system(empty.exclusive_system().label(A0).before(A1).before(A3)) - .with_system(empty.exclusive_system().label(A1).in_ambiguity_set(SetA)) - .with_system(empty.exclusive_system().label(A2).after(A1)) - .with_system(empty.exclusive_system().label(A3).in_ambiguity_set(SetA)) - .with_system(empty.exclusive_system().label(A4).after(A3).before(A5)) - .with_system(empty.exclusive_system().label(A5).in_ambiguity_set(SetA)) - .with_system(empty.exclusive_system().label(A6).after(A2).after(A5)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.exclusive_at_start); - assert!( - ambiguities.contains(&(A2.as_label(), A3.as_label())) - || ambiguities.contains(&(A3.as_label(), A2.as_label())) - ); - assert!( - ambiguities.contains(&(A1.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A1.as_label())) - ); - assert!( - ambiguities.contains(&(A2.as_label(), A4.as_label())) - || ambiguities.contains(&(A4.as_label(), A2.as_label())) - ); - assert!( - ambiguities.contains(&(A2.as_label(), A5.as_label())) - || ambiguities.contains(&(A5.as_label(), A2.as_label())) - ); - assert_eq!(ambiguities.len(), 4); - - let mut stage = SystemStage::parallel() - .with_system(empty.exclusive_system().label(A0).in_ambiguity_set(SetA)) - .with_system(empty.exclusive_system().label(A1).in_ambiguity_set(SetA)) - .with_system(empty.exclusive_system().label(A2).in_ambiguity_set(SetA)) - .with_system(empty.exclusive_system().label(A3).in_ambiguity_set(SetA)); - stage.initialize_systems(&mut world); - stage.rebuild_orders_and_dependencies(); - let ambiguities = find_ambiguities_first_labels(&stage.exclusive_at_start); - assert_eq!(ambiguities.len(), 0); - } - #[test] #[should_panic] fn multiple_worlds_same_stage() { diff --git a/crates/bevy_ecs/src/schedule/system_container.rs b/crates/bevy_ecs/src/schedule/system_container.rs index 51d0962489143..2318d65ca7b13 100644 --- a/crates/bevy_ecs/src/schedule/system_container.rs +++ b/crates/bevy_ecs/src/schedule/system_container.rs @@ -2,8 +2,8 @@ use crate::{ component::ComponentId, query::Access, schedule::{ - AmbiguitySetLabelId, ExclusiveSystemDescriptor, GraphNode, ParallelSystemDescriptor, - RunCriteriaLabelId, SystemLabelId, + ExclusiveSystemDescriptor, GraphNode, ParallelSystemDescriptor, RunCriteriaLabelId, + SystemLabelId, }, system::{ExclusiveSystem, System}, }; @@ -20,7 +20,6 @@ pub trait SystemContainer: GraphNode