From 5e651d0355ad985e6aab708836de551c3dc31acf Mon Sep 17 00:00:00 2001 From: mvlabat Date: Tue, 20 Jul 2021 10:14:40 +0200 Subject: [PATCH 1/4] Implement StageLabel for Box --- crates/bevy_ecs/src/schedule/label.rs | 6 ++++++ crates/bevy_ecs/src/schedule/mod.rs | 27 +++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/schedule/label.rs b/crates/bevy_ecs/src/schedule/label.rs index 5235dc5837692..b1d742af4d53b 100644 --- a/crates/bevy_ecs/src/schedule/label.rs +++ b/crates/bevy_ecs/src/schedule/label.rs @@ -6,6 +6,12 @@ define_label!(SystemLabel); define_label!(AmbiguitySetLabel); define_label!(RunCriteriaLabel); +impl StageLabel for Box { + fn dyn_clone(&self) -> Box { + self.as_ref().dyn_clone() + } +} + pub(crate) type BoxedStageLabel = Box; pub(crate) type BoxedSystemLabel = Box; pub(crate) type BoxedAmbiguitySetLabel = Box; diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index dc228f4265de3..96a22548e9d52 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -141,7 +141,7 @@ impl Schedule { .stage_order .iter() .enumerate() - .find(|(_i, stage_label)| &***stage_label == target) + .find(|(_i, stage_label)| stage_label.dyn_clone() == target.dyn_clone()) .map(|(i, _)| i) .unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target)); @@ -175,7 +175,7 @@ impl Schedule { .stage_order .iter() .enumerate() - .find(|(_i, stage_label)| &***stage_label == target) + .find(|(_i, stage_label)| stage_label.dyn_clone() == target.dyn_clone()) .map(|(i, _)| i) .unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target)); @@ -369,3 +369,26 @@ impl Stage for Schedule { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_adding_after_boxed_stage() { + let mut schedule = Schedule::default(); + schedule.add_stage("first", SystemStage::single_threaded()); + let stage = schedule.iter_stages().next().unwrap().0.dyn_clone(); + // shouldn't panic + schedule.add_stage_after(stage, "second", SystemStage::single_threaded()); + } + + #[test] + fn test_adding_before_boxed_stage() { + let mut schedule = Schedule::default(); + schedule.add_stage("first", SystemStage::single_threaded()); + let stage = schedule.iter_stages().next().unwrap().0.dyn_clone(); + // shouldn't panic + schedule.add_stage_before(stage, "second", SystemStage::single_threaded()); + } +} From 646a2c982f76ead59d05dcc607c0deb367d3baaa Mon Sep 17 00:00:00 2001 From: mvlabat Date: Mon, 11 Apr 2022 16:55:25 +0300 Subject: [PATCH 2/4] Implement for all label types --- crates/bevy_app/src/app.rs | 2 +- crates/bevy_ecs/src/schedule/label.rs | 6 ------ crates/bevy_ecs/src/schedule/mod.rs | 6 +++--- crates/bevy_ecs/src/schedule/run_criteria.rs | 12 ++++++------ .../bevy_ecs/src/schedule/system_descriptor.rs | 16 ++++++++-------- crates/bevy_ecs/src/schedule/system_set.rs | 6 +++--- crates/bevy_ecs/src/system/function_system.rs | 2 +- crates/bevy_utils/src/label.rs | 6 ++++++ 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 67dad6fc2b403..2595414537664 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -864,7 +864,7 @@ impl App { sub_app_runner: impl Fn(&mut World, &mut App) + 'static, ) -> &mut Self { self.sub_apps.insert( - Box::new(label), + label.dyn_clone(), SubApp { app, runner: Box::new(sub_app_runner), diff --git a/crates/bevy_ecs/src/schedule/label.rs b/crates/bevy_ecs/src/schedule/label.rs index b1d742af4d53b..5235dc5837692 100644 --- a/crates/bevy_ecs/src/schedule/label.rs +++ b/crates/bevy_ecs/src/schedule/label.rs @@ -6,12 +6,6 @@ define_label!(SystemLabel); define_label!(AmbiguitySetLabel); define_label!(RunCriteriaLabel); -impl StageLabel for Box { - fn dyn_clone(&self) -> Box { - self.as_ref().dyn_clone() - } -} - pub(crate) type BoxedStageLabel = Box; pub(crate) type BoxedSystemLabel = Box; pub(crate) type BoxedAmbiguitySetLabel = Box; diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index 96a22548e9d52..a8207875fa6a2 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -111,7 +111,7 @@ impl Schedule { /// schedule.add_stage("my_stage", SystemStage::parallel()); /// ``` pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { - let label: Box = Box::new(label); + let label: Box = label.dyn_clone(); self.stage_order.push(label.clone()); let prev = self.stages.insert(label.clone(), Box::new(stage)); assert!(prev.is_none(), "Stage already exists: {:?}.", label); @@ -135,7 +135,7 @@ impl Schedule { label: impl StageLabel, stage: S, ) -> &mut Self { - let label: Box = Box::new(label); + let label: Box = label.dyn_clone(); let target = &target as &dyn StageLabel; let target_index = self .stage_order @@ -169,7 +169,7 @@ impl Schedule { label: impl StageLabel, stage: S, ) -> &mut Self { - let label: Box = Box::new(label); + let label: Box = label.dyn_clone(); let target = &target as &dyn StageLabel; let target_index = self .stage_order diff --git a/crates/bevy_ecs/src/schedule/run_criteria.rs b/crates/bevy_ecs/src/schedule/run_criteria.rs index f3b42500b6919..135dbbaff9856 100644 --- a/crates/bevy_ecs/src/schedule/run_criteria.rs +++ b/crates/bevy_ecs/src/schedule/run_criteria.rs @@ -205,7 +205,7 @@ where L: RunCriteriaLabel, { fn into(self) -> RunCriteriaDescriptorOrLabel { - RunCriteriaDescriptorOrLabel::Label(Box::new(self)) + RunCriteriaDescriptorOrLabel::Label(self.dyn_clone()) } } @@ -232,24 +232,24 @@ pub trait RunCriteriaDescriptorCoercion { impl RunCriteriaDescriptorCoercion<()> for RunCriteriaDescriptor { fn label(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.label = Some(Box::new(label)); + self.label = Some(label.dyn_clone()); self.duplicate_label_strategy = DuplicateLabelStrategy::Panic; self } fn label_discard_if_duplicate(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.label = Some(Box::new(label)); + self.label = Some(label.dyn_clone()); self.duplicate_label_strategy = DuplicateLabelStrategy::Discard; self } fn before(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.before.push(Box::new(label)); + self.before.push(label.dyn_clone()); self } fn after(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.after.push(Box::new(label)); + self.after.push(label.dyn_clone()); self } } @@ -320,7 +320,7 @@ impl RunCriteria { label: None, duplicate_label_strategy: DuplicateLabelStrategy::Panic, before: vec![], - after: vec![Box::new(label)], + after: vec![label.dyn_clone()], } } } diff --git a/crates/bevy_ecs/src/schedule/system_descriptor.rs b/crates/bevy_ecs/src/schedule/system_descriptor.rs index 405c8760f3a81..641826067be24 100644 --- a/crates/bevy_ecs/src/schedule/system_descriptor.rs +++ b/crates/bevy_ecs/src/schedule/system_descriptor.rs @@ -149,22 +149,22 @@ impl ParallelSystemDescriptorCoercion<()> for ParallelSystemDescriptor { } fn label(mut self, label: impl SystemLabel) -> ParallelSystemDescriptor { - self.labels.push(Box::new(label)); + self.labels.push(label.dyn_clone()); self } fn before(mut self, label: impl AsSystemLabel) -> ParallelSystemDescriptor { - self.before.push(Box::new(label.as_system_label())); + self.before.push(label.as_system_label().dyn_clone()); self } fn after(mut self, label: impl AsSystemLabel) -> ParallelSystemDescriptor { - self.after.push(Box::new(label.as_system_label())); + self.after.push(label.as_system_label().dyn_clone()); self } fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> ParallelSystemDescriptor { - self.ambiguity_sets.push(Box::new(set)); + self.ambiguity_sets.push(set.dyn_clone()); self } } @@ -295,22 +295,22 @@ impl ExclusiveSystemDescriptorCoercion for ExclusiveSystemDescriptor { } fn label(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor { - self.labels.push(Box::new(label)); + self.labels.push(label.dyn_clone()); self } fn before(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor { - self.before.push(Box::new(label)); + self.before.push(label.dyn_clone()); self } fn after(mut self, label: impl SystemLabel) -> ExclusiveSystemDescriptor { - self.after.push(Box::new(label)); + self.after.push(label.dyn_clone()); self } fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> ExclusiveSystemDescriptor { - self.ambiguity_sets.push(Box::new(set)); + self.ambiguity_sets.push(set.dyn_clone()); self } diff --git a/crates/bevy_ecs/src/schedule/system_set.rs b/crates/bevy_ecs/src/schedule/system_set.rs index 5e32c2e48d1bb..96e42e09f4f04 100644 --- a/crates/bevy_ecs/src/schedule/system_set.rs +++ b/crates/bevy_ecs/src/schedule/system_set.rs @@ -90,19 +90,19 @@ impl SystemSet { #[must_use] pub fn label(mut self, label: impl SystemLabel) -> Self { - self.labels.push(Box::new(label)); + self.labels.push(label.dyn_clone()); self } #[must_use] pub fn before(mut self, label: impl SystemLabel) -> Self { - self.before.push(Box::new(label)); + self.before.push(label.dyn_clone()); self } #[must_use] pub fn after(mut self, label: impl SystemLabel) -> Self { - self.after.push(Box::new(label)); + self.after.push(label.dyn_clone()); self } diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 30f421cabad37..21f2b6bd60dde 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -446,7 +446,7 @@ where ); } fn default_labels(&self) -> Vec> { - vec![Box::new(self.func.as_system_label())] + vec![self.func.as_system_label().dyn_clone()] } } diff --git a/crates/bevy_utils/src/label.rs b/crates/bevy_utils/src/label.rs index 7728ef8b947df..859b4480aa5d3 100644 --- a/crates/bevy_utils/src/label.rs +++ b/crates/bevy_utils/src/label.rs @@ -97,5 +97,11 @@ macro_rules! define_label { Box::new(<&str>::clone(self)) } } + + impl $label_trait_name for Box { + fn dyn_clone(&self) -> Self { + self.as_ref().dyn_clone() + } + } }; } From 7db56106e3b0635b0f1a95e0199410b4d9527fbe Mon Sep 17 00:00:00 2001 From: mvlabat Date: Mon, 11 Apr 2022 17:51:58 +0300 Subject: [PATCH 3/4] Introduce a boxed label wrapper type --- crates/bevy_app/src/app.rs | 8 +- crates/bevy_derive/src/lib.rs | 6 +- crates/bevy_ecs/macros/src/lib.rs | 55 ++++++--- crates/bevy_ecs/src/schedule/label.rs | 13 +- crates/bevy_ecs/src/schedule/mod.rs | 10 +- crates/bevy_ecs/src/schedule/stage.rs | 111 +++++++++--------- crates/bevy_ecs/src/schedule/state.rs | 9 +- crates/bevy_ecs/src/schedule/system_set.rs | 2 +- crates/bevy_ecs/src/system/function_system.rs | 7 +- crates/bevy_ecs/src/system/system.rs | 8 +- crates/bevy_macro_utils/src/lib.rs | 10 +- crates/bevy_utils/src/label.rs | 46 ++++++-- 12 files changed, 167 insertions(+), 118 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 2595414537664..863dcf4a1a71c 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -15,7 +15,7 @@ use std::fmt::Debug; #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; -bevy_utils::define_label!(AppLabel); +bevy_utils::define_label!(AppLabel, BoxedAppLabel); #[allow(clippy::needless_doctest_main)] /// A container of app logic and data. @@ -56,7 +56,7 @@ pub struct App { pub runner: Box, /// A container of [`Stage`]s set to be run in a linear order. pub schedule: Schedule, - sub_apps: HashMap, SubApp>, + sub_apps: HashMap, } /// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns. @@ -889,7 +889,7 @@ impl App { /// an [`Err`] containing the given label. pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Result<&mut App, impl AppLabel> { self.sub_apps - .get_mut((&label) as &dyn AppLabel) + .get_mut(&label.dyn_clone()) .map(|sub_app| &mut sub_app.app) .ok_or(label) } @@ -910,7 +910,7 @@ impl App { /// an [`Err`] containing the given label. pub fn get_sub_app(&self, label: impl AppLabel) -> Result<&App, impl AppLabel> { self.sub_apps - .get((&label) as &dyn AppLabel) + .get(&label.dyn_clone()) .map(|sub_app| &sub_app.app) .ok_or(label) } diff --git a/crates/bevy_derive/src/lib.rs b/crates/bevy_derive/src/lib.rs index 929eaf67b7bb1..7442d9852bd33 100644 --- a/crates/bevy_derive/src/lib.rs +++ b/crates/bevy_derive/src/lib.rs @@ -85,6 +85,10 @@ pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream { pub fn derive_app_label(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); let mut trait_path = BevyManifest::default().get_path("bevy_app"); + let mut boxed_type_path = trait_path.clone(); trait_path.segments.push(format_ident!("AppLabel").into()); - derive_label(input, &trait_path) + boxed_type_path + .segments + .push(format_ident!("BoxedAppLabel").into()); + derive_label(input, &trait_path, &boxed_type_path) } diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index c0dfb21199269..940be4807eb0b 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -424,43 +424,62 @@ pub fn derive_world_query(input: TokenStream) -> TokenStream { #[proc_macro_derive(SystemLabel)] pub fn derive_system_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!("SystemLabel").into()); - derive_label(input, &trait_path) + let LabelPaths { + trait_path, + boxed_type_path, + } = label_paths("SystemLabel"); + derive_label(input, &trait_path, &boxed_type_path) } #[proc_macro_derive(StageLabel)] pub fn derive_stage_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!("StageLabel").into()); - derive_label(input, &trait_path) + let LabelPaths { + trait_path, + boxed_type_path, + } = label_paths("StageLabel"); + derive_label(input, &trait_path, &boxed_type_path) } #[proc_macro_derive(AmbiguitySetLabel)] 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) + let LabelPaths { + trait_path, + boxed_type_path, + } = label_paths("AmbiguitySetLabel"); + derive_label(input, &trait_path, &boxed_type_path) } #[proc_macro_derive(RunCriteriaLabel)] pub fn derive_run_criteria_label(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); + let LabelPaths { + trait_path, + boxed_type_path, + } = label_paths("RunCriteriaLabel"); + derive_label(input, &trait_path, &boxed_type_path) +} + +struct LabelPaths { + trait_path: syn::Path, + boxed_type_path: syn::Path, +} + +fn label_paths(label_trait_name: &'static str) -> LabelPaths { let mut trait_path = bevy_ecs_path(); trait_path.segments.push(format_ident!("schedule").into()); + let mut boxed_type_path = trait_path.clone(); trait_path .segments - .push(format_ident!("RunCriteriaLabel").into()); - derive_label(input, &trait_path) + .push(format_ident!("{}", label_trait_name).into()); + boxed_type_path + .segments + .push(format_ident!("Boxed{}", label_trait_name).into()); + LabelPaths { + trait_path, + boxed_type_path, + } } pub(crate) fn bevy_ecs_path() -> syn::Path { diff --git a/crates/bevy_ecs/src/schedule/label.rs b/crates/bevy_ecs/src/schedule/label.rs index 5235dc5837692..2b0dd92c695f5 100644 --- a/crates/bevy_ecs/src/schedule/label.rs +++ b/crates/bevy_ecs/src/schedule/label.rs @@ -1,12 +1,7 @@ pub use bevy_ecs_macros::{AmbiguitySetLabel, RunCriteriaLabel, StageLabel, SystemLabel}; use bevy_utils::define_label; -define_label!(StageLabel); -define_label!(SystemLabel); -define_label!(AmbiguitySetLabel); -define_label!(RunCriteriaLabel); - -pub(crate) type BoxedStageLabel = Box; -pub(crate) type BoxedSystemLabel = Box; -pub(crate) type BoxedAmbiguitySetLabel = Box; -pub(crate) type BoxedRunCriteriaLabel = Box; +define_label!(StageLabel, BoxedStageLabel); +define_label!(SystemLabel, BoxedSystemLabel); +define_label!(AmbiguitySetLabel, BoxedAmbiguitySetLabel); +define_label!(RunCriteriaLabel, BoxedRunCriteriaLabel); diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index a8207875fa6a2..b9fbad4aebc4a 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -111,7 +111,7 @@ impl Schedule { /// schedule.add_stage("my_stage", SystemStage::parallel()); /// ``` pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { - let label: Box = label.dyn_clone(); + let label: BoxedStageLabel = label.dyn_clone(); self.stage_order.push(label.clone()); let prev = self.stages.insert(label.clone(), Box::new(stage)); assert!(prev.is_none(), "Stage already exists: {:?}.", label); @@ -135,7 +135,7 @@ impl Schedule { label: impl StageLabel, stage: S, ) -> &mut Self { - let label: Box = label.dyn_clone(); + let label: BoxedStageLabel = label.dyn_clone(); let target = &target as &dyn StageLabel; let target_index = self .stage_order @@ -169,7 +169,7 @@ impl Schedule { label: impl StageLabel, stage: S, ) -> &mut Self { - let label: Box = label.dyn_clone(); + let label: BoxedStageLabel = label.dyn_clone(); let target = &target as &dyn StageLabel; let target_index = self .stage_order @@ -307,7 +307,7 @@ impl Schedule { /// ``` pub fn get_stage(&self, label: &dyn StageLabel) -> Option<&T> { self.stages - .get(label) + .get(&label.dyn_clone()) .and_then(|stage| stage.downcast_ref::()) } @@ -328,7 +328,7 @@ impl Schedule { /// ``` pub fn get_stage_mut(&mut self, label: &dyn StageLabel) -> Option<&mut T> { self.stages - .get_mut(label) + .get_mut(&label.dyn_clone()) .and_then(|stage| stage.downcast_mut::()) } diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index c2a040d648517..a46d6637c0e7e 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -945,7 +945,7 @@ mod tests { schedule::{ BoxedSystemLabel, ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, RunCriteria, RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage, - SystemSet, SystemStage, + SystemLabel, SystemSet, SystemStage, }, system::{In, IntoExclusiveSystem, Local, Query, ResMut}, world::World, @@ -953,6 +953,7 @@ mod tests { use crate as bevy_ecs; use crate::component::Component; + #[derive(Component)] struct W(T); @@ -1626,8 +1627,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "1".dyn_clone())) ); assert_eq!(ambiguities.len(), 1); @@ -1641,8 +1642,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "1".dyn_clone())) ); assert_eq!(ambiguities.len(), 1); @@ -1666,12 +1667,12 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("0"))) + ambiguities.contains(&("0".dyn_clone(), "3".dyn_clone())) + || ambiguities.contains(&("3".dyn_clone(), "0".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "1".dyn_clone())) ); assert_eq!(ambiguities.len(), 2); @@ -1685,8 +1686,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("0"))) + ambiguities.contains(&("0".dyn_clone(), "3".dyn_clone())) + || ambiguities.contains(&("3".dyn_clone(), "0".dyn_clone())) ); assert_eq!(ambiguities.len(), 1); @@ -1698,8 +1699,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("1"))) - || ambiguities.contains(&(Box::new("1"), Box::new("0"))) + ambiguities.contains(&("0".dyn_clone(), "1".dyn_clone())) + || ambiguities.contains(&("1".dyn_clone(), "0".dyn_clone())) ); assert_eq!(ambiguities.len(), 1); @@ -1711,8 +1712,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "2".dyn_clone())) + || ambiguities.contains(&("2".dyn_clone(), "1".dyn_clone())) ); assert_eq!(ambiguities.len(), 1); @@ -1725,8 +1726,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "2".dyn_clone())) + || ambiguities.contains(&("2".dyn_clone(), "1".dyn_clone())) ); assert_eq!(ambiguities.len(), 1); @@ -1749,8 +1750,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "2".dyn_clone())) + || ambiguities.contains(&("2".dyn_clone(), "1".dyn_clone())) ); assert_eq!(ambiguities.len(), 1); @@ -1779,28 +1780,28 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "2".dyn_clone())) + || ambiguities.contains(&("2".dyn_clone(), "1".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "3".dyn_clone())) + || ambiguities.contains(&("3".dyn_clone(), "1".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "1".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "3".dyn_clone())) + || ambiguities.contains(&("3".dyn_clone(), "2".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "2".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("3"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("3"))) + ambiguities.contains(&("3".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "3".dyn_clone())) ); assert_eq!(ambiguities.len(), 6); @@ -1860,12 +1861,12 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "1".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "2".dyn_clone())) ); assert_eq!(ambiguities.len(), 2); @@ -1894,28 +1895,28 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "3".dyn_clone())) + || ambiguities.contains(&("3".dyn_clone(), "1".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "3".dyn_clone())) + || ambiguities.contains(&("3".dyn_clone(), "2".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "1".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "2".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "5".dyn_clone())) + || ambiguities.contains(&("5".dyn_clone(), "1".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "5".dyn_clone())) + || ambiguities.contains(&("5".dyn_clone(), "2".dyn_clone())) ); assert_eq!(ambiguities.len(), 6); @@ -1931,20 +1932,20 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "3".dyn_clone())) + || ambiguities.contains(&("3".dyn_clone(), "2".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "1".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "4".dyn_clone())) + || ambiguities.contains(&("4".dyn_clone(), "2".dyn_clone())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("2"))) + ambiguities.contains(&("2".dyn_clone(), "5".dyn_clone())) + || ambiguities.contains(&("5".dyn_clone(), "2".dyn_clone())) ); assert_eq!(ambiguities.len(), 4); diff --git a/crates/bevy_ecs/src/schedule/state.rs b/crates/bevy_ecs/src/schedule/state.rs index 3b4c894a8c1bc..31835d0367e4d 100644 --- a/crates/bevy_ecs/src/schedule/state.rs +++ b/crates/bevy_ecs/src/schedule/state.rs @@ -1,3 +1,4 @@ +use crate::schedule::BoxedRunCriteriaLabel; use crate::{ schedule::{ RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, RunCriteriaLabel, ShouldRun, @@ -75,16 +76,16 @@ impl RunCriteriaLabel for StateRunCriteriaLabel where T: StateData, { - fn dyn_clone(&self) -> Box { - Box::new(self.clone()) + fn dyn_clone(&self) -> BoxedRunCriteriaLabel { + BoxedRunCriteriaLabel(Box::new(self.clone())) } } #[derive(Debug, PartialEq, Eq, Clone, Hash)] struct DriverLabel(TypeId); impl RunCriteriaLabel for DriverLabel { - fn dyn_clone(&self) -> Box { - Box::new(self.clone()) + fn dyn_clone(&self) -> BoxedRunCriteriaLabel { + BoxedRunCriteriaLabel(Box::new(self.clone())) } } diff --git a/crates/bevy_ecs/src/schedule/system_set.rs b/crates/bevy_ecs/src/schedule/system_set.rs index 96e42e09f4f04..98d6016b51ccf 100644 --- a/crates/bevy_ecs/src/schedule/system_set.rs +++ b/crates/bevy_ecs/src/schedule/system_set.rs @@ -72,7 +72,7 @@ impl SystemSet { #[must_use] pub fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> Self { - self.ambiguity_sets.push(Box::new(set)); + self.ambiguity_sets.push(set.dyn_clone()); self } diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 21f2b6bd60dde..8e5121126d224 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -1,3 +1,4 @@ +use crate::schedule::BoxedSystemLabel; use crate::{ archetype::{ArchetypeComponentId, ArchetypeGeneration, ArchetypeId}, component::ComponentId, @@ -445,7 +446,7 @@ where self.system_meta.name.as_ref(), ); } - fn default_labels(&self) -> Vec> { + fn default_labels(&self) -> Vec { vec![self.func.as_system_label().dyn_clone()] } } @@ -483,8 +484,8 @@ impl PartialEq for SystemTypeIdLabel { impl Eq for SystemTypeIdLabel {} impl SystemLabel for SystemTypeIdLabel { - fn dyn_clone(&self) -> Box { - Box::new(*self) + fn dyn_clone(&self) -> BoxedSystemLabel { + BoxedSystemLabel(Box::new(*self)) } } diff --git a/crates/bevy_ecs/src/system/system.rs b/crates/bevy_ecs/src/system/system.rs index 92f30532caea1..4bdbd7c3dcf1c 100644 --- a/crates/bevy_ecs/src/system/system.rs +++ b/crates/bevy_ecs/src/system/system.rs @@ -1,9 +1,7 @@ use bevy_utils::tracing::warn; -use crate::{ - archetype::ArchetypeComponentId, component::ComponentId, query::Access, schedule::SystemLabel, - world::World, -}; +use crate::schedule::BoxedSystemLabel; +use crate::{archetype::ArchetypeComponentId, component::ComponentId, query::Access, world::World}; use std::borrow::Cow; /// An ECS system that can be added to a [`Schedule`](crate::schedule::Schedule) @@ -56,7 +54,7 @@ pub trait System: Send + Sync + 'static { fn update_archetype_component_access(&mut self, world: &World); fn check_change_tick(&mut self, change_tick: u32); /// The default labels for the system - fn default_labels(&self) -> Vec> { + fn default_labels(&self) -> Vec { Vec::new() } } diff --git a/crates/bevy_macro_utils/src/lib.rs b/crates/bevy_macro_utils/src/lib.rs index 4f360a3bd3af6..6922392613a94 100644 --- a/crates/bevy_macro_utils/src/lib.rs +++ b/crates/bevy_macro_utils/src/lib.rs @@ -76,7 +76,11 @@ impl BevyManifest { /// /// - `input`: The [`syn::DeriveInput`] for struct that is deriving the label trait /// - `trait_path`: The path [`syn::Path`] to the label trait -pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStream { +pub fn derive_label( + input: syn::DeriveInput, + trait_path: &syn::Path, + boxed_type_path: &syn::Path, +) -> TokenStream { let ident = input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); @@ -88,8 +92,8 @@ pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStr (quote! { impl #impl_generics #trait_path for #ident #ty_generics #where_clause { - fn dyn_clone(&self) -> std::boxed::Box { - std::boxed::Box::new(std::clone::Clone::clone(self)) + fn dyn_clone(&self) -> #boxed_type_path { + #boxed_type_path(std::boxed::Box::new(std::clone::Clone::clone(self))) } } }) diff --git a/crates/bevy_utils/src/label.rs b/crates/bevy_utils/src/label.rs index 859b4480aa5d3..5bf8f702f0771 100644 --- a/crates/bevy_utils/src/label.rs +++ b/crates/bevy_utils/src/label.rs @@ -53,17 +53,17 @@ where /// /// ``` /// # use bevy_utils::define_label; -/// define_label!(MyNewLabelTrait); +/// define_label!(MyNewLabelTrait, MyNewBoxedLabelTrait); /// ``` #[macro_export] macro_rules! define_label { - ($label_trait_name:ident) => { + ($label_trait_name:ident, $boxed_type_name:ident) => { /// Defines a set of strongly-typed labels for a class of objects pub trait $label_trait_name: ::bevy_utils::label::DynHash + ::std::fmt::Debug + Send + Sync + 'static { #[doc(hidden)] - fn dyn_clone(&self) -> Box; + fn dyn_clone(&self) -> $boxed_type_name; } impl PartialEq for dyn $label_trait_name { @@ -80,27 +80,53 @@ macro_rules! define_label { } } - impl Clone for Box { + impl Clone for $boxed_type_name { fn clone(&self) -> Self { self.dyn_clone() } } impl $label_trait_name for ::std::borrow::Cow<'static, str> { - fn dyn_clone(&self) -> Box { - Box::new(self.clone()) + fn dyn_clone(&self) -> $boxed_type_name { + $boxed_type_name(Box::new(self.clone())) } } impl $label_trait_name for &'static str { - fn dyn_clone(&self) -> Box { - Box::new(<&str>::clone(self)) + fn dyn_clone(&self) -> $boxed_type_name { + $boxed_type_name(Box::new(<&str>::clone(self))) } } - impl $label_trait_name for Box { + impl ::std::ops::Deref for $boxed_type_name { + type Target = as ::std::ops::Deref>::Target; + + fn deref(&self) -> &Self::Target { + self.0.deref() + } + } + + /// A wrapper for a boxed label + #[derive(Debug)] + pub struct $boxed_type_name(pub Box); + + impl ::std::hash::Hash for $boxed_type_name { + fn hash(&self, state: &mut H) { + self.0.as_ref().dyn_hash(state); + } + } + + impl PartialEq for $boxed_type_name { + fn eq(&self, other: &Self) -> bool { + self.0.as_ref().dyn_eq(other.as_dyn_eq()) + } + } + + impl Eq for $boxed_type_name {} + + impl $label_trait_name for $boxed_type_name { fn dyn_clone(&self) -> Self { - self.as_ref().dyn_clone() + self.0.as_ref().dyn_clone() } } }; From 61500703d453cf8884766a5d24560744be54c608 Mon Sep 17 00:00:00 2001 From: mvlabat Date: Mon, 11 Apr 2022 19:33:59 +0300 Subject: [PATCH 4/4] Hide the box wrapper constructor from the docs --- crates/bevy_ecs/src/schedule/state.rs | 4 ++-- crates/bevy_ecs/src/system/function_system.rs | 2 +- crates/bevy_macro_utils/src/lib.rs | 2 +- crates/bevy_utils/src/label.rs | 9 ++++++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ecs/src/schedule/state.rs b/crates/bevy_ecs/src/schedule/state.rs index 31835d0367e4d..810ca10e82b9c 100644 --- a/crates/bevy_ecs/src/schedule/state.rs +++ b/crates/bevy_ecs/src/schedule/state.rs @@ -77,7 +77,7 @@ where T: StateData, { fn dyn_clone(&self) -> BoxedRunCriteriaLabel { - BoxedRunCriteriaLabel(Box::new(self.clone())) + BoxedRunCriteriaLabel::new(Box::new(self.clone())) } } @@ -85,7 +85,7 @@ where struct DriverLabel(TypeId); impl RunCriteriaLabel for DriverLabel { fn dyn_clone(&self) -> BoxedRunCriteriaLabel { - BoxedRunCriteriaLabel(Box::new(self.clone())) + BoxedRunCriteriaLabel::new(Box::new(self.clone())) } } diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 8e5121126d224..66e0e1dde43f1 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -485,7 +485,7 @@ impl Eq for SystemTypeIdLabel {} impl SystemLabel for SystemTypeIdLabel { fn dyn_clone(&self) -> BoxedSystemLabel { - BoxedSystemLabel(Box::new(*self)) + BoxedSystemLabel::new(Box::new(*self)) } } diff --git a/crates/bevy_macro_utils/src/lib.rs b/crates/bevy_macro_utils/src/lib.rs index 6922392613a94..a40c8dbc030e4 100644 --- a/crates/bevy_macro_utils/src/lib.rs +++ b/crates/bevy_macro_utils/src/lib.rs @@ -93,7 +93,7 @@ pub fn derive_label( (quote! { impl #impl_generics #trait_path for #ident #ty_generics #where_clause { fn dyn_clone(&self) -> #boxed_type_path { - #boxed_type_path(std::boxed::Box::new(std::clone::Clone::clone(self))) + #boxed_type_path::new(std::boxed::Box::new(std::clone::Clone::clone(self))) } } }) diff --git a/crates/bevy_utils/src/label.rs b/crates/bevy_utils/src/label.rs index 5bf8f702f0771..f5a5f84586914 100644 --- a/crates/bevy_utils/src/label.rs +++ b/crates/bevy_utils/src/label.rs @@ -108,7 +108,14 @@ macro_rules! define_label { /// A wrapper for a boxed label #[derive(Debug)] - pub struct $boxed_type_name(pub Box); + pub struct $boxed_type_name(Box); + + impl $boxed_type_name { + #[doc(hidden)] + pub fn new(label: Box) -> Self { + Self(label) + } + } impl ::std::hash::Hash for $boxed_type_name { fn hash(&self, state: &mut H) {