Skip to content

Commit 7d69d31

Browse files
authored
refactor: Simplify lifetimes for Commands and related types (#11445)
# Objective It would be convenient to be able to call functions with `Commands` as a parameter without having to move your own instance of `Commands`. Since this struct is composed entirely of references, we can easily get an owned instance of `Commands` by shortening the lifetime. ## Solution Add `Commands::reborrow`, `EntiyCommands::reborrow`, and `Deferred::reborrow`, which returns an owned version of themselves with a shorter lifetime. Remove unnecessary lifetimes from `EntityCommands`. The `'w` and `'s` lifetimes only have to be separate for `Commands` because it's used as a `SystemParam` -- this is not the case for `EntityCommands`. --- ## Changelog Added `Commands::reborrow`. This is useful if you have `&mut Commands` but need `Commands`. Also added `EntityCommands::reborrow` and `Deferred:reborrow` which serve the same purpose. ## Migration Guide The lifetimes for `EntityCommands` have been simplified. ```rust // Before (Bevy 0.12) struct MyStruct<'w, 's, 'a> { commands: EntityCommands<'w, 's, 'a>, } // After (Bevy 0.13) struct MyStruct<'a> { commands: EntityCommands<'a>, } ``` The method `EntityCommands::commands` now returns `Commands` rather than `&mut Commands`. ```rust // Before (Bevy 0.12) let commands = entity_commands.commands(); commands.spawn(...); // After (Bevy 0.13) let mut commands = entity_commands.commands(); commands.spawn(...); ```
1 parent e2e4e8e commit 7d69d31

File tree

6 files changed

+65
-23
lines changed

6 files changed

+65
-23
lines changed

crates/bevy_ecs/src/reflect/entity_commands.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ pub trait ReflectCommandExt {
140140
) -> &mut Self;
141141
}
142142

143-
impl<'w, 's, 'a> ReflectCommandExt for EntityCommands<'w, 's, 'a> {
143+
impl ReflectCommandExt for EntityCommands<'_> {
144144
fn insert_reflect(&mut self, component: Box<dyn Reflect>) -> &mut Self {
145145
self.commands.add(InsertReflect {
146146
entity: self.entity,

crates/bevy_ecs/src/system/commands/mod.rs

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,31 @@ impl<'w, 's> Commands<'w, 's> {
146146
}
147147
}
148148

149+
/// Returns a [`Commands`] with a smaller lifetime.
150+
/// This is useful if you have `&mut Commands` but need `Commands`.
151+
///
152+
/// # Examples
153+
///
154+
/// ```
155+
/// # use bevy_ecs::prelude::*;
156+
/// fn my_system(mut commands: Commands) {
157+
/// // We do our initialization in a separate function,
158+
/// // which expects an owned `Commands`.
159+
/// do_initialization(commands.reborrow());
160+
///
161+
/// // Since we only reborrowed the commands instead of moving them, we can still use them.
162+
/// commands.spawn_empty();
163+
/// }
164+
/// #
165+
/// # fn do_initialization(_: Commands) {}
166+
/// ```
167+
pub fn reborrow(&mut self) -> Commands<'w, '_> {
168+
Commands {
169+
queue: self.queue.reborrow(),
170+
entities: self.entities,
171+
}
172+
}
173+
149174
/// Take all commands from `other` and append them to `self`, leaving `other` empty
150175
pub fn append(&mut self, other: &mut CommandQueue) {
151176
self.queue.append(other);
@@ -186,11 +211,11 @@ impl<'w, 's> Commands<'w, 's> {
186211
///
187212
/// - [`spawn`](Self::spawn) to spawn an entity with a bundle.
188213
/// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
189-
pub fn spawn_empty<'a>(&'a mut self) -> EntityCommands<'w, 's, 'a> {
214+
pub fn spawn_empty(&mut self) -> EntityCommands {
190215
let entity = self.entities.reserve_entity();
191216
EntityCommands {
192217
entity,
193-
commands: self,
218+
commands: self.reborrow(),
194219
}
195220
}
196221

@@ -208,13 +233,13 @@ impl<'w, 's> Commands<'w, 's> {
208233
/// [`Commands::spawn`]. This method should generally only be used for sharing entities across
209234
/// apps, and only when they have a scheme worked out to share an ID space (which doesn't happen
210235
/// by default).
211-
pub fn get_or_spawn<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> {
236+
pub fn get_or_spawn(&mut self, entity: Entity) -> EntityCommands {
212237
self.add(move |world: &mut World| {
213238
world.get_or_spawn(entity);
214239
});
215240
EntityCommands {
216241
entity,
217-
commands: self,
242+
commands: self.reborrow(),
218243
}
219244
}
220245

@@ -268,7 +293,7 @@ impl<'w, 's> Commands<'w, 's> {
268293
///
269294
/// - [`spawn_empty`](Self::spawn_empty) to spawn an entity without any components.
270295
/// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
271-
pub fn spawn<'a, T: Bundle>(&'a mut self, bundle: T) -> EntityCommands<'w, 's, 'a> {
296+
pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
272297
let mut e = self.spawn_empty();
273298
e.insert(bundle);
274299
e
@@ -310,7 +335,7 @@ impl<'w, 's> Commands<'w, 's> {
310335
/// - [`get_entity`](Self::get_entity) for the fallible version.
311336
#[inline]
312337
#[track_caller]
313-
pub fn entity<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> {
338+
pub fn entity(&mut self, entity: Entity) -> EntityCommands {
314339
#[inline(never)]
315340
#[cold]
316341
#[track_caller]
@@ -359,10 +384,10 @@ impl<'w, 's> Commands<'w, 's> {
359384
/// - [`entity`](Self::entity) for the panicking version.
360385
#[inline]
361386
#[track_caller]
362-
pub fn get_entity<'a>(&'a mut self, entity: Entity) -> Option<EntityCommands<'w, 's, 'a>> {
387+
pub fn get_entity(&mut self, entity: Entity) -> Option<EntityCommands> {
363388
self.entities.contains(entity).then_some(EntityCommands {
364389
entity,
365-
commands: self,
390+
commands: self.reborrow(),
366391
})
367392
}
368393

@@ -674,12 +699,12 @@ where
674699
}
675700

676701
/// A list of commands that will be run to modify an [entity](crate::entity).
677-
pub struct EntityCommands<'w, 's, 'a> {
702+
pub struct EntityCommands<'a> {
678703
pub(crate) entity: Entity,
679-
pub(crate) commands: &'a mut Commands<'w, 's>,
704+
pub(crate) commands: Commands<'a, 'a>,
680705
}
681706

682-
impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
707+
impl EntityCommands<'_> {
683708
/// Returns the [`Entity`] id of the entity.
684709
///
685710
/// # Example
@@ -698,6 +723,15 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
698723
self.entity
699724
}
700725

726+
/// Returns an [`EntityCommands`] with a smaller lifetime.
727+
/// This is useful if you have `&mut EntityCommands` but you need `EntityCommands`.
728+
pub fn reborrow(&mut self) -> EntityCommands {
729+
EntityCommands {
730+
entity: self.entity,
731+
commands: self.commands.reborrow(),
732+
}
733+
}
734+
701735
/// Adds a [`Bundle`] of components to the entity.
702736
///
703737
/// This will overwrite any previous value(s) of the same component type.
@@ -956,8 +990,8 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
956990
}
957991

958992
/// Returns the underlying [`Commands`].
959-
pub fn commands(&mut self) -> &mut Commands<'w, 's> {
960-
self.commands
993+
pub fn commands(&mut self) -> Commands {
994+
self.commands.reborrow()
961995
}
962996
}
963997

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,14 @@ impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {
919919
}
920920
}
921921

922+
impl<T: SystemBuffer> Deferred<'_, T> {
923+
/// Returns a [`Deferred<T>`] with a smaller lifetime.
924+
/// This is useful if you have `&mut Deferred<T>` but need `Deferred<T>`.
925+
pub fn reborrow(&mut self) -> Deferred<T> {
926+
Deferred(self.0)
927+
}
928+
}
929+
922930
// SAFETY: Only local state is accessed.
923931
unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
924932

crates/bevy_hierarchy/src/child_builder.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -274,23 +274,23 @@ impl Command for RemoveParent {
274274
/// });
275275
/// # }
276276
/// ```
277-
pub struct ChildBuilder<'w, 's, 'a> {
278-
commands: &'a mut Commands<'w, 's>,
277+
pub struct ChildBuilder<'a> {
278+
commands: Commands<'a, 'a>,
279279
push_children: PushChildren,
280280
}
281281

282-
impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
282+
impl ChildBuilder<'_> {
283283
/// Spawns an entity with the given bundle and inserts it into the parent entity's [`Children`].
284284
/// Also adds [`Parent`] component to the created entity.
285-
pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands<'w, 's, '_> {
285+
pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands {
286286
let e = self.commands.spawn(bundle);
287287
self.push_children.children.push(e.id());
288288
e
289289
}
290290

291291
/// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
292292
/// Also adds [`Parent`] component to the created entity.
293-
pub fn spawn_empty(&mut self) -> EntityCommands<'w, 's, '_> {
293+
pub fn spawn_empty(&mut self) -> EntityCommands {
294294
let e = self.commands.spawn_empty();
295295
self.push_children.children.push(e.id());
296296
e
@@ -302,7 +302,7 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
302302
}
303303

304304
/// Adds a command to be executed, like [`Commands::add`].
305-
pub fn add_command<C: Command + 'static>(&mut self, command: C) -> &mut Self {
305+
pub fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
306306
self.commands.add(command);
307307
self
308308
}
@@ -374,7 +374,7 @@ pub trait BuildChildren {
374374
fn remove_parent(&mut self) -> &mut Self;
375375
}
376376

377-
impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
377+
impl BuildChildren for EntityCommands<'_> {
378378
fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self {
379379
let parent = self.id();
380380
let mut builder = ChildBuilder {

crates/bevy_hierarchy/src/hierarchy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub trait DespawnRecursiveExt {
8989
fn despawn_descendants(&mut self) -> &mut Self;
9090
}
9191

92-
impl<'w, 's, 'a> DespawnRecursiveExt for EntityCommands<'w, 's, 'a> {
92+
impl DespawnRecursiveExt for EntityCommands<'_> {
9393
/// Despawns the provided entity and its children.
9494
fn despawn_recursive(mut self) {
9595
let entity = self.id();

crates/bevy_transform/src/commands.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub trait BuildChildrenTransformExt {
8585
/// (during [`apply_deferred`](bevy_ecs::schedule::apply_deferred)).
8686
fn remove_parent_in_place(&mut self) -> &mut Self;
8787
}
88-
impl<'w, 's, 'a> BuildChildrenTransformExt for EntityCommands<'w, 's, 'a> {
88+
impl BuildChildrenTransformExt for EntityCommands<'_> {
8989
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self {
9090
let child = self.id();
9191
self.commands().add(PushChildInPlace { child, parent });

0 commit comments

Comments
 (0)