Skip to content

Commit 647794f

Browse files
committed
Introduce a boxed label wrapper type
1 parent 646a2c9 commit 647794f

File tree

11 files changed

+110
-62
lines changed

11 files changed

+110
-62
lines changed

crates/bevy_app/src/app.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::fmt::Debug;
1515

1616
#[cfg(feature = "trace")]
1717
use bevy_utils::tracing::info_span;
18-
bevy_utils::define_label!(AppLabel);
18+
bevy_utils::define_label!(AppLabel, BoxedAppLabel);
1919

2020
#[allow(clippy::needless_doctest_main)]
2121
/// A container of app logic and data.
@@ -56,7 +56,7 @@ pub struct App {
5656
pub runner: Box<dyn Fn(App)>,
5757
/// A container of [`Stage`]s set to be run in a linear order.
5858
pub schedule: Schedule,
59-
sub_apps: HashMap<Box<dyn AppLabel>, SubApp>,
59+
sub_apps: HashMap<BoxedAppLabel, SubApp>,
6060
}
6161

6262
/// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns.
@@ -889,7 +889,7 @@ impl App {
889889
/// an [`Err`] containing the given label.
890890
pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Result<&mut App, impl AppLabel> {
891891
self.sub_apps
892-
.get_mut((&label) as &dyn AppLabel)
892+
.get_mut(&label.dyn_clone())
893893
.map(|sub_app| &mut sub_app.app)
894894
.ok_or(label)
895895
}
@@ -910,7 +910,7 @@ impl App {
910910
/// an [`Err`] containing the given label.
911911
pub fn get_sub_app(&self, label: impl AppLabel) -> Result<&App, impl AppLabel> {
912912
self.sub_apps
913-
.get((&label) as &dyn AppLabel)
913+
.get(&label.dyn_clone())
914914
.map(|sub_app| &sub_app.app)
915915
.ok_or(label)
916916
}

crates/bevy_derive/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
8585
pub fn derive_app_label(input: TokenStream) -> TokenStream {
8686
let input = syn::parse_macro_input!(input as syn::DeriveInput);
8787
let mut trait_path = BevyManifest::default().get_path("bevy_app");
88+
let mut boxed_type_path = trait_path.clone();
8889
trait_path.segments.push(format_ident!("AppLabel").into());
89-
derive_label(input, &trait_path)
90+
boxed_type_path
91+
.segments
92+
.push(format_ident!("BoxedAppLabel").into());
93+
derive_label(input, &trait_path, &boxed_type_path)
9094
}

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -424,43 +424,62 @@ pub fn derive_world_query(input: TokenStream) -> TokenStream {
424424
#[proc_macro_derive(SystemLabel)]
425425
pub fn derive_system_label(input: TokenStream) -> TokenStream {
426426
let input = parse_macro_input!(input as DeriveInput);
427-
let mut trait_path = bevy_ecs_path();
428-
trait_path.segments.push(format_ident!("schedule").into());
429-
trait_path
430-
.segments
431-
.push(format_ident!("SystemLabel").into());
432-
derive_label(input, &trait_path)
427+
let LabelPaths {
428+
trait_path,
429+
boxed_type_path,
430+
} = label_paths("SystemLabel");
431+
derive_label(input, &trait_path, &boxed_type_path)
433432
}
434433

435434
#[proc_macro_derive(StageLabel)]
436435
pub fn derive_stage_label(input: TokenStream) -> TokenStream {
437436
let input = parse_macro_input!(input as DeriveInput);
438-
let mut trait_path = bevy_ecs_path();
439-
trait_path.segments.push(format_ident!("schedule").into());
440-
trait_path.segments.push(format_ident!("StageLabel").into());
441-
derive_label(input, &trait_path)
437+
let LabelPaths {
438+
trait_path,
439+
boxed_type_path,
440+
} = label_paths("StageLabel");
441+
derive_label(input, &trait_path, &boxed_type_path)
442442
}
443443

444444
#[proc_macro_derive(AmbiguitySetLabel)]
445445
pub fn derive_ambiguity_set_label(input: TokenStream) -> TokenStream {
446446
let input = parse_macro_input!(input as DeriveInput);
447-
let mut trait_path = bevy_ecs_path();
448-
trait_path.segments.push(format_ident!("schedule").into());
449-
trait_path
450-
.segments
451-
.push(format_ident!("AmbiguitySetLabel").into());
452-
derive_label(input, &trait_path)
447+
let LabelPaths {
448+
trait_path,
449+
boxed_type_path,
450+
} = label_paths("AmbiguitySetLabel");
451+
derive_label(input, &trait_path, &boxed_type_path)
453452
}
454453

455454
#[proc_macro_derive(RunCriteriaLabel)]
456455
pub fn derive_run_criteria_label(input: TokenStream) -> TokenStream {
457456
let input = parse_macro_input!(input as DeriveInput);
457+
let LabelPaths {
458+
trait_path,
459+
boxed_type_path,
460+
} = label_paths("RunCriteriaLabel");
461+
derive_label(input, &trait_path, &boxed_type_path)
462+
}
463+
464+
struct LabelPaths {
465+
trait_path: syn::Path,
466+
boxed_type_path: syn::Path,
467+
}
468+
469+
fn label_paths(label_trait_name: &'static str) -> LabelPaths {
458470
let mut trait_path = bevy_ecs_path();
459471
trait_path.segments.push(format_ident!("schedule").into());
472+
let mut boxed_type_path = trait_path.clone();
460473
trait_path
461474
.segments
462-
.push(format_ident!("RunCriteriaLabel").into());
463-
derive_label(input, &trait_path)
475+
.push(format_ident!("{}", label_trait_name).into());
476+
boxed_type_path
477+
.segments
478+
.push(format_ident!("Boxed{}", label_trait_name).into());
479+
LabelPaths {
480+
trait_path,
481+
boxed_type_path,
482+
}
464483
}
465484

466485
pub(crate) fn bevy_ecs_path() -> syn::Path {

crates/bevy_ecs/src/schedule/label.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
pub use bevy_ecs_macros::{AmbiguitySetLabel, RunCriteriaLabel, StageLabel, SystemLabel};
22
use bevy_utils::define_label;
33

4-
define_label!(StageLabel);
5-
define_label!(SystemLabel);
6-
define_label!(AmbiguitySetLabel);
7-
define_label!(RunCriteriaLabel);
8-
9-
pub(crate) type BoxedStageLabel = Box<dyn StageLabel>;
10-
pub(crate) type BoxedSystemLabel = Box<dyn SystemLabel>;
11-
pub(crate) type BoxedAmbiguitySetLabel = Box<dyn AmbiguitySetLabel>;
12-
pub(crate) type BoxedRunCriteriaLabel = Box<dyn RunCriteriaLabel>;
4+
define_label!(StageLabel, BoxedStageLabel);
5+
define_label!(SystemLabel, BoxedSystemLabel);
6+
define_label!(AmbiguitySetLabel, BoxedAmbiguitySetLabel);
7+
define_label!(RunCriteriaLabel, BoxedRunCriteriaLabel);

crates/bevy_ecs/src/schedule/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl Schedule {
111111
/// schedule.add_stage("my_stage", SystemStage::parallel());
112112
/// ```
113113
pub fn add_stage<S: Stage>(&mut self, label: impl StageLabel, stage: S) -> &mut Self {
114-
let label: Box<dyn StageLabel> = label.dyn_clone();
114+
let label: BoxedStageLabel = label.dyn_clone();
115115
self.stage_order.push(label.clone());
116116
let prev = self.stages.insert(label.clone(), Box::new(stage));
117117
assert!(prev.is_none(), "Stage already exists: {:?}.", label);
@@ -135,7 +135,7 @@ impl Schedule {
135135
label: impl StageLabel,
136136
stage: S,
137137
) -> &mut Self {
138-
let label: Box<dyn StageLabel> = label.dyn_clone();
138+
let label: BoxedStageLabel = label.dyn_clone();
139139
let target = &target as &dyn StageLabel;
140140
let target_index = self
141141
.stage_order
@@ -169,7 +169,7 @@ impl Schedule {
169169
label: impl StageLabel,
170170
stage: S,
171171
) -> &mut Self {
172-
let label: Box<dyn StageLabel> = label.dyn_clone();
172+
let label: BoxedStageLabel = label.dyn_clone();
173173
let target = &target as &dyn StageLabel;
174174
let target_index = self
175175
.stage_order
@@ -307,7 +307,7 @@ impl Schedule {
307307
/// ```
308308
pub fn get_stage<T: Stage>(&self, label: &dyn StageLabel) -> Option<&T> {
309309
self.stages
310-
.get(label)
310+
.get(&label.dyn_clone())
311311
.and_then(|stage| stage.downcast_ref::<T>())
312312
}
313313

@@ -328,7 +328,7 @@ impl Schedule {
328328
/// ```
329329
pub fn get_stage_mut<T: Stage>(&mut self, label: &dyn StageLabel) -> Option<&mut T> {
330330
self.stages
331-
.get_mut(label)
331+
.get_mut(&label.dyn_clone())
332332
.and_then(|stage| stage.downcast_mut::<T>())
333333
}
334334

crates/bevy_ecs/src/schedule/state.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::schedule::BoxedRunCriteriaLabel;
12
use crate::{
23
schedule::{
34
RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, RunCriteriaLabel, ShouldRun,
@@ -75,16 +76,16 @@ impl<T> RunCriteriaLabel for StateRunCriteriaLabel<T>
7576
where
7677
T: StateData,
7778
{
78-
fn dyn_clone(&self) -> Box<dyn RunCriteriaLabel> {
79-
Box::new(self.clone())
79+
fn dyn_clone(&self) -> BoxedRunCriteriaLabel {
80+
BoxedRunCriteriaLabel(Box::new(self.clone()))
8081
}
8182
}
8283

8384
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
8485
struct DriverLabel(TypeId);
8586
impl RunCriteriaLabel for DriverLabel {
86-
fn dyn_clone(&self) -> Box<dyn RunCriteriaLabel> {
87-
Box::new(self.clone())
87+
fn dyn_clone(&self) -> BoxedRunCriteriaLabel {
88+
BoxedRunCriteriaLabel(Box::new(self.clone()))
8889
}
8990
}
9091

crates/bevy_ecs/src/schedule/system_set.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl SystemSet {
7272

7373
#[must_use]
7474
pub fn in_ambiguity_set(mut self, set: impl AmbiguitySetLabel) -> Self {
75-
self.ambiguity_sets.push(Box::new(set));
75+
self.ambiguity_sets.push(set.dyn_clone());
7676
self
7777
}
7878

crates/bevy_ecs/src/system/function_system.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::schedule::BoxedSystemLabel;
12
use crate::{
23
archetype::{ArchetypeComponentId, ArchetypeGeneration, ArchetypeId},
34
component::ComponentId,
@@ -445,7 +446,7 @@ where
445446
self.system_meta.name.as_ref(),
446447
);
447448
}
448-
fn default_labels(&self) -> Vec<Box<dyn SystemLabel>> {
449+
fn default_labels(&self) -> Vec<BoxedSystemLabel> {
449450
vec![self.func.as_system_label().dyn_clone()]
450451
}
451452
}
@@ -483,8 +484,8 @@ impl<T> PartialEq for SystemTypeIdLabel<T> {
483484
impl<T> Eq for SystemTypeIdLabel<T> {}
484485

485486
impl<T> SystemLabel for SystemTypeIdLabel<T> {
486-
fn dyn_clone(&self) -> Box<dyn SystemLabel> {
487-
Box::new(*self)
487+
fn dyn_clone(&self) -> BoxedSystemLabel {
488+
BoxedSystemLabel(Box::new(*self))
488489
}
489490
}
490491

crates/bevy_ecs/src/system/system.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use bevy_utils::tracing::warn;
22

3-
use crate::{
4-
archetype::ArchetypeComponentId, component::ComponentId, query::Access, schedule::SystemLabel,
5-
world::World,
6-
};
3+
use crate::schedule::BoxedSystemLabel;
4+
use crate::{archetype::ArchetypeComponentId, component::ComponentId, query::Access, world::World};
75
use std::borrow::Cow;
86

97
/// An ECS system that can be added to a [`Schedule`](crate::schedule::Schedule)
@@ -56,7 +54,7 @@ pub trait System: Send + Sync + 'static {
5654
fn update_archetype_component_access(&mut self, world: &World);
5755
fn check_change_tick(&mut self, change_tick: u32);
5856
/// The default labels for the system
59-
fn default_labels(&self) -> Vec<Box<dyn SystemLabel>> {
57+
fn default_labels(&self) -> Vec<BoxedSystemLabel> {
6058
Vec::new()
6159
}
6260
}

crates/bevy_macro_utils/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ impl BevyManifest {
7676
///
7777
/// - `input`: The [`syn::DeriveInput`] for struct that is deriving the label trait
7878
/// - `trait_path`: The path [`syn::Path`] to the label trait
79-
pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStream {
79+
pub fn derive_label(
80+
input: syn::DeriveInput,
81+
trait_path: &syn::Path,
82+
boxed_type_path: &syn::Path,
83+
) -> TokenStream {
8084
let ident = input.ident;
8185

8286
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
8892

8993
(quote! {
9094
impl #impl_generics #trait_path for #ident #ty_generics #where_clause {
91-
fn dyn_clone(&self) -> std::boxed::Box<dyn #trait_path> {
92-
std::boxed::Box::new(std::clone::Clone::clone(self))
95+
fn dyn_clone(&self) -> #boxed_type_path {
96+
#boxed_type_path(std::boxed::Box::new(std::clone::Clone::clone(self)))
9397
}
9498
}
9599
})

crates/bevy_utils/src/label.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ where
5757
/// ```
5858
#[macro_export]
5959
macro_rules! define_label {
60-
($label_trait_name:ident) => {
60+
($label_trait_name:ident, $boxed_type_name:ident) => {
6161
/// Defines a set of strongly-typed labels for a class of objects
6262
pub trait $label_trait_name:
6363
::bevy_utils::label::DynHash + ::std::fmt::Debug + Send + Sync + 'static
6464
{
6565
#[doc(hidden)]
66-
fn dyn_clone(&self) -> Box<dyn $label_trait_name>;
66+
fn dyn_clone(&self) -> $boxed_type_name;
6767
}
6868

6969
impl PartialEq for dyn $label_trait_name {
@@ -80,27 +80,53 @@ macro_rules! define_label {
8080
}
8181
}
8282

83-
impl Clone for Box<dyn $label_trait_name> {
83+
impl Clone for $boxed_type_name {
8484
fn clone(&self) -> Self {
8585
self.dyn_clone()
8686
}
8787
}
8888

8989
impl $label_trait_name for ::std::borrow::Cow<'static, str> {
90-
fn dyn_clone(&self) -> Box<dyn $label_trait_name> {
91-
Box::new(self.clone())
90+
fn dyn_clone(&self) -> $boxed_type_name {
91+
$boxed_type_name(Box::new(self.clone()))
9292
}
9393
}
9494

9595
impl $label_trait_name for &'static str {
96-
fn dyn_clone(&self) -> Box<dyn $label_trait_name> {
97-
Box::new(<&str>::clone(self))
96+
fn dyn_clone(&self) -> $boxed_type_name {
97+
$boxed_type_name(Box::new(<&str>::clone(self)))
9898
}
9999
}
100100

101-
impl $label_trait_name for Box<dyn $label_trait_name> {
101+
impl ::std::ops::Deref for $boxed_type_name {
102+
type Target = <Box<dyn $label_trait_name> as ::std::ops::Deref>::Target;
103+
104+
fn deref(&self) -> &Self::Target {
105+
self.0.deref()
106+
}
107+
}
108+
109+
/// A wrapper for a boxed label
110+
#[derive(Debug)]
111+
pub struct $boxed_type_name(pub Box<dyn $label_trait_name>);
112+
113+
impl ::std::hash::Hash for $boxed_type_name {
114+
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
115+
self.0.as_ref().dyn_hash(state);
116+
}
117+
}
118+
119+
impl PartialEq for $boxed_type_name {
120+
fn eq(&self, other: &Self) -> bool {
121+
self.0.as_ref().dyn_eq(other.as_dyn_eq())
122+
}
123+
}
124+
125+
impl Eq for $boxed_type_name {}
126+
127+
impl $label_trait_name for $boxed_type_name {
102128
fn dyn_clone(&self) -> Self {
103-
self.as_ref().dyn_clone()
129+
self.0.as_ref().dyn_clone()
104130
}
105131
}
106132
};

0 commit comments

Comments
 (0)