Simplify world schedule methods (#8403)

# Objective

Methods for interacting with world schedules currently have two
variants: one that takes `impl ScheduleLabel` and one that takes `&dyn
ScheduleLabel`. Operations such as `run_schedule` or `schedule_scope`
only use the label by reference, so there is little reason to have an
owned variant of these functions.

## Solution

Decrease maintenance burden by merging the `ref` variants of these
functions with the owned variants.

---

## Changelog

- Deprecated `World::run_schedule_ref`. It is now redundant, since
`World::run_schedule` can take values by reference.

## Migration Guide

The method `World::run_schedule_ref` has been deprecated, and will be
removed in the next version of Bevy. Use `run_schedule` instead.
This commit is contained in:
JoJoJet 2023-04-19 15:48:35 -04:00 committed by GitHub
parent fe852fd0ad
commit 9fd867aeba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 74 deletions

View file

@ -162,9 +162,7 @@ impl SubApp {
/// Runs the `SubApp`'s default schedule. /// Runs the `SubApp`'s default schedule.
pub fn run(&mut self) { pub fn run(&mut self) {
self.app self.app.world.run_schedule(&*self.app.main_schedule_label);
.world
.run_schedule_ref(&*self.app.main_schedule_label);
self.app.world.clear_trackers(); self.app.world.clear_trackers();
} }
@ -241,7 +239,7 @@ impl App {
{ {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let _bevy_frame_update_span = info_span!("main app").entered(); let _bevy_frame_update_span = info_span!("main app").entered();
self.world.run_schedule_ref(&*self.main_schedule_label); self.world.run_schedule(&*self.main_schedule_label);
} }
for (_label, sub_app) in self.sub_apps.iter_mut() { for (_label, sub_app) in self.sub_apps.iter_mut() {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]

View file

@ -143,7 +143,7 @@ impl Main {
world.resource_scope(|world, order: Mut<MainScheduleOrder>| { world.resource_scope(|world, order: Mut<MainScheduleOrder>| {
for label in &order.labels { for label in &order.labels {
let _ = world.try_run_schedule_ref(&**label); let _ = world.try_run_schedule(&**label);
} }
}); });
} }

View file

@ -201,7 +201,7 @@ mod tests {
let boxed: Box<dyn ScheduleLabel> = Box::new(A); let boxed: Box<dyn ScheduleLabel> = Box::new(A);
world.insert_resource(Flag(false)); world.insert_resource(Flag(false));
world.run_schedule_ref(&boxed); world.run_schedule(&boxed);
assert!(world.resource::<Flag>().0); assert!(world.resource::<Flag>().0);
world.insert_resource(Flag(false)); world.insert_resource(Flag(false));

View file

@ -1734,30 +1734,10 @@ impl World {
/// For other use cases, see the example on [`World::schedule_scope`]. /// For other use cases, see the example on [`World::schedule_scope`].
pub fn try_schedule_scope<R>( pub fn try_schedule_scope<R>(
&mut self, &mut self,
label: impl ScheduleLabel, label: impl AsRef<dyn ScheduleLabel>,
f: impl FnOnce(&mut World, &mut Schedule) -> R,
) -> Result<R, TryRunScheduleError> {
self.try_schedule_scope_ref(&label, f)
}
/// Temporarily removes the schedule associated with `label` from the world,
/// runs user code, and finally re-adds the schedule.
/// This returns a [`TryRunScheduleError`] if there is no schedule
/// associated with `label`.
///
/// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone.
///
/// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
/// and system state is cached.
///
/// For simple cases where you just need to call the schedule once,
/// consider using [`World::try_run_schedule_ref`] instead.
/// For other use cases, see the example on [`World::schedule_scope`].
pub fn try_schedule_scope_ref<R>(
&mut self,
label: &dyn ScheduleLabel,
f: impl FnOnce(&mut World, &mut Schedule) -> R, f: impl FnOnce(&mut World, &mut Schedule) -> R,
) -> Result<R, TryRunScheduleError> { ) -> Result<R, TryRunScheduleError> {
let label = label.as_ref();
let Some((extracted_label, mut schedule)) let Some((extracted_label, mut schedule))
= self.get_resource_mut::<Schedules>().and_then(|mut s| s.remove_entry(label)) = self.get_resource_mut::<Schedules>().and_then(|mut s| s.remove_entry(label))
else { else {
@ -1818,33 +1798,10 @@ impl World {
/// If the requested schedule does not exist. /// If the requested schedule does not exist.
pub fn schedule_scope<R>( pub fn schedule_scope<R>(
&mut self, &mut self,
label: impl ScheduleLabel, label: impl AsRef<dyn ScheduleLabel>,
f: impl FnOnce(&mut World, &mut Schedule) -> R, f: impl FnOnce(&mut World, &mut Schedule) -> R,
) -> R { ) -> R {
self.schedule_scope_ref(&label, f) self.try_schedule_scope(label, f)
}
/// Temporarily removes the schedule associated with `label` from the world,
/// runs user code, and finally re-adds the schedule.
///
/// Unlike the `run_schedule` method, this method takes the label by reference, which can save a clone.
///
/// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
/// and system state is cached.
///
/// For simple cases where you just need to call the schedule,
/// consider using [`World::run_schedule_ref`] instead.
/// For other use cases, see the example on [`World::schedule_scope`].
///
/// # Panics
///
/// If the requested schedule does not exist.
pub fn schedule_scope_ref<R>(
&mut self,
label: &dyn ScheduleLabel,
f: impl FnOnce(&mut World, &mut Schedule) -> R,
) -> R {
self.try_schedule_scope_ref(label, f)
.unwrap_or_else(|e| panic!("{e}")) .unwrap_or_else(|e| panic!("{e}"))
} }
@ -1857,25 +1814,9 @@ impl World {
/// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead. /// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead.
pub fn try_run_schedule( pub fn try_run_schedule(
&mut self, &mut self,
label: impl ScheduleLabel, label: impl AsRef<dyn ScheduleLabel>,
) -> Result<(), TryRunScheduleError> { ) -> Result<(), TryRunScheduleError> {
self.try_run_schedule_ref(&label) self.try_schedule_scope(label, |world, sched| sched.run(world))
}
/// Attempts to run the [`Schedule`] associated with the `label` a single time,
/// and returns a [`TryRunScheduleError`] if the schedule does not exist.
///
/// Unlike the `try_run_schedule` method, this method takes the label by reference, which can save a clone.
///
/// The [`Schedule`] is fetched from the [`Schedules`] resource of the world by its label,
/// and system state is cached.
///
/// For simple testing use cases, call [`Schedule::run(&mut world)`](Schedule::run) instead.
pub fn try_run_schedule_ref(
&mut self,
label: &dyn ScheduleLabel,
) -> Result<(), TryRunScheduleError> {
self.try_schedule_scope_ref(label, |world, sched| sched.run(world))
} }
/// Runs the [`Schedule`] associated with the `label` a single time. /// Runs the [`Schedule`] associated with the `label` a single time.
@ -1888,8 +1829,8 @@ impl World {
/// # Panics /// # Panics
/// ///
/// If the requested schedule does not exist. /// If the requested schedule does not exist.
pub fn run_schedule(&mut self, label: impl ScheduleLabel) { pub fn run_schedule(&mut self, label: impl AsRef<dyn ScheduleLabel>) {
self.run_schedule_ref(&label); self.schedule_scope(label, |world, sched| sched.run(world));
} }
/// Runs the [`Schedule`] associated with the `label` a single time. /// Runs the [`Schedule`] associated with the `label` a single time.
@ -1904,8 +1845,9 @@ impl World {
/// # Panics /// # Panics
/// ///
/// If the requested schedule does not exist. /// If the requested schedule does not exist.
#[deprecated = "Use `World::run_schedule` instead."]
pub fn run_schedule_ref(&mut self, label: &dyn ScheduleLabel) { pub fn run_schedule_ref(&mut self, label: &dyn ScheduleLabel) {
self.schedule_scope_ref(label, |world, sched| sched.run(world)); self.schedule_scope(label, |world, sched| sched.run(world));
} }
} }

View file

@ -191,6 +191,12 @@ pub fn derive_boxed_label(input: syn::DeriveInput, trait_path: &syn::Path) -> To
::std::hash::Hash::hash(self, &mut state); ::std::hash::Hash::hash(self, &mut state);
} }
} }
impl #impl_generics ::std::convert::AsRef<dyn #trait_path> for #ident #ty_generics #where_clause {
fn as_ref(&self) -> &dyn #trait_path {
self
}
}
}) })
.into() .into()
} }

View file

@ -111,6 +111,13 @@ macro_rules! define_boxed_label {
} }
} }
impl ::std::convert::AsRef<dyn $label_trait_name> for dyn $label_trait_name {
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
impl Clone for Box<dyn $label_trait_name> { impl Clone for Box<dyn $label_trait_name> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
self.dyn_clone() self.dyn_clone()