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(...);
```
			
			
This commit is contained in:
		
							parent
							
								
									e2e4e8eb9a
								
							
						
					
					
						commit
						7d69d3195f
					
				@ -140,7 +140,7 @@ pub trait ReflectCommandExt {
 | 
				
			|||||||
    ) -> &mut Self;
 | 
					    ) -> &mut Self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'w, 's, 'a> ReflectCommandExt for EntityCommands<'w, 's, 'a> {
 | 
					impl ReflectCommandExt for EntityCommands<'_> {
 | 
				
			||||||
    fn insert_reflect(&mut self, component: Box<dyn Reflect>) -> &mut Self {
 | 
					    fn insert_reflect(&mut self, component: Box<dyn Reflect>) -> &mut Self {
 | 
				
			||||||
        self.commands.add(InsertReflect {
 | 
					        self.commands.add(InsertReflect {
 | 
				
			||||||
            entity: self.entity,
 | 
					            entity: self.entity,
 | 
				
			||||||
 | 
				
			|||||||
@ -146,6 +146,31 @@ impl<'w, 's> Commands<'w, 's> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns a [`Commands`] with a smaller lifetime.
 | 
				
			||||||
 | 
					    /// This is useful if you have `&mut Commands` but need `Commands`.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Examples
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// ```
 | 
				
			||||||
 | 
					    /// # use bevy_ecs::prelude::*;
 | 
				
			||||||
 | 
					    /// fn my_system(mut commands: Commands) {
 | 
				
			||||||
 | 
					    ///     // We do our initialization in a separate function,
 | 
				
			||||||
 | 
					    ///     // which expects an owned `Commands`.
 | 
				
			||||||
 | 
					    ///     do_initialization(commands.reborrow());
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    ///     // Since we only reborrowed the commands instead of moving them, we can still use them.
 | 
				
			||||||
 | 
					    ///     commands.spawn_empty();
 | 
				
			||||||
 | 
					    /// }
 | 
				
			||||||
 | 
					    /// #
 | 
				
			||||||
 | 
					    /// # fn do_initialization(_: Commands) {}
 | 
				
			||||||
 | 
					    /// ```
 | 
				
			||||||
 | 
					    pub fn reborrow(&mut self) -> Commands<'w, '_> {
 | 
				
			||||||
 | 
					        Commands {
 | 
				
			||||||
 | 
					            queue: self.queue.reborrow(),
 | 
				
			||||||
 | 
					            entities: self.entities,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Take all commands from `other` and append them to `self`, leaving `other` empty
 | 
					    /// Take all commands from `other` and append them to `self`, leaving `other` empty
 | 
				
			||||||
    pub fn append(&mut self, other: &mut CommandQueue) {
 | 
					    pub fn append(&mut self, other: &mut CommandQueue) {
 | 
				
			||||||
        self.queue.append(other);
 | 
					        self.queue.append(other);
 | 
				
			||||||
@ -186,11 +211,11 @@ impl<'w, 's> Commands<'w, 's> {
 | 
				
			|||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// - [`spawn`](Self::spawn) to spawn an entity with a bundle.
 | 
					    /// - [`spawn`](Self::spawn) to spawn an entity with a bundle.
 | 
				
			||||||
    /// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
 | 
					    /// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
 | 
				
			||||||
    pub fn spawn_empty<'a>(&'a mut self) -> EntityCommands<'w, 's, 'a> {
 | 
					    pub fn spawn_empty(&mut self) -> EntityCommands {
 | 
				
			||||||
        let entity = self.entities.reserve_entity();
 | 
					        let entity = self.entities.reserve_entity();
 | 
				
			||||||
        EntityCommands {
 | 
					        EntityCommands {
 | 
				
			||||||
            entity,
 | 
					            entity,
 | 
				
			||||||
            commands: self,
 | 
					            commands: self.reborrow(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -208,13 +233,13 @@ impl<'w, 's> Commands<'w, 's> {
 | 
				
			|||||||
    /// [`Commands::spawn`]. This method should generally only be used for sharing entities across
 | 
					    /// [`Commands::spawn`]. This method should generally only be used for sharing entities across
 | 
				
			||||||
    /// apps, and only when they have a scheme worked out to share an ID space (which doesn't happen
 | 
					    /// apps, and only when they have a scheme worked out to share an ID space (which doesn't happen
 | 
				
			||||||
    /// by default).
 | 
					    /// by default).
 | 
				
			||||||
    pub fn get_or_spawn<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> {
 | 
					    pub fn get_or_spawn(&mut self, entity: Entity) -> EntityCommands {
 | 
				
			||||||
        self.add(move |world: &mut World| {
 | 
					        self.add(move |world: &mut World| {
 | 
				
			||||||
            world.get_or_spawn(entity);
 | 
					            world.get_or_spawn(entity);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        EntityCommands {
 | 
					        EntityCommands {
 | 
				
			||||||
            entity,
 | 
					            entity,
 | 
				
			||||||
            commands: self,
 | 
					            commands: self.reborrow(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -268,7 +293,7 @@ impl<'w, 's> Commands<'w, 's> {
 | 
				
			|||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// - [`spawn_empty`](Self::spawn_empty) to spawn an entity without any components.
 | 
					    /// - [`spawn_empty`](Self::spawn_empty) to spawn an entity without any components.
 | 
				
			||||||
    /// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
 | 
					    /// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
 | 
				
			||||||
    pub fn spawn<'a, T: Bundle>(&'a mut self, bundle: T) -> EntityCommands<'w, 's, 'a> {
 | 
					    pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
 | 
				
			||||||
        let mut e = self.spawn_empty();
 | 
					        let mut e = self.spawn_empty();
 | 
				
			||||||
        e.insert(bundle);
 | 
					        e.insert(bundle);
 | 
				
			||||||
        e
 | 
					        e
 | 
				
			||||||
@ -310,7 +335,7 @@ impl<'w, 's> Commands<'w, 's> {
 | 
				
			|||||||
    /// - [`get_entity`](Self::get_entity) for the fallible version.
 | 
					    /// - [`get_entity`](Self::get_entity) for the fallible version.
 | 
				
			||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    #[track_caller]
 | 
					    #[track_caller]
 | 
				
			||||||
    pub fn entity<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> {
 | 
					    pub fn entity(&mut self, entity: Entity) -> EntityCommands {
 | 
				
			||||||
        #[inline(never)]
 | 
					        #[inline(never)]
 | 
				
			||||||
        #[cold]
 | 
					        #[cold]
 | 
				
			||||||
        #[track_caller]
 | 
					        #[track_caller]
 | 
				
			||||||
@ -359,10 +384,10 @@ impl<'w, 's> Commands<'w, 's> {
 | 
				
			|||||||
    /// - [`entity`](Self::entity) for the panicking version.
 | 
					    /// - [`entity`](Self::entity) for the panicking version.
 | 
				
			||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    #[track_caller]
 | 
					    #[track_caller]
 | 
				
			||||||
    pub fn get_entity<'a>(&'a mut self, entity: Entity) -> Option<EntityCommands<'w, 's, 'a>> {
 | 
					    pub fn get_entity(&mut self, entity: Entity) -> Option<EntityCommands> {
 | 
				
			||||||
        self.entities.contains(entity).then_some(EntityCommands {
 | 
					        self.entities.contains(entity).then_some(EntityCommands {
 | 
				
			||||||
            entity,
 | 
					            entity,
 | 
				
			||||||
            commands: self,
 | 
					            commands: self.reborrow(),
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -674,12 +699,12 @@ where
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A list of commands that will be run to modify an [entity](crate::entity).
 | 
					/// A list of commands that will be run to modify an [entity](crate::entity).
 | 
				
			||||||
pub struct EntityCommands<'w, 's, 'a> {
 | 
					pub struct EntityCommands<'a> {
 | 
				
			||||||
    pub(crate) entity: Entity,
 | 
					    pub(crate) entity: Entity,
 | 
				
			||||||
    pub(crate) commands: &'a mut Commands<'w, 's>,
 | 
					    pub(crate) commands: Commands<'a, 'a>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
 | 
					impl EntityCommands<'_> {
 | 
				
			||||||
    /// Returns the [`Entity`] id of the entity.
 | 
					    /// Returns the [`Entity`] id of the entity.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// # Example
 | 
					    /// # Example
 | 
				
			||||||
@ -698,6 +723,15 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
 | 
				
			|||||||
        self.entity
 | 
					        self.entity
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns an [`EntityCommands`] with a smaller lifetime.
 | 
				
			||||||
 | 
					    /// This is useful if you have `&mut EntityCommands` but you need `EntityCommands`.
 | 
				
			||||||
 | 
					    pub fn reborrow(&mut self) -> EntityCommands {
 | 
				
			||||||
 | 
					        EntityCommands {
 | 
				
			||||||
 | 
					            entity: self.entity,
 | 
				
			||||||
 | 
					            commands: self.commands.reborrow(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Adds a [`Bundle`] of components to the entity.
 | 
					    /// Adds a [`Bundle`] of components to the entity.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// This will overwrite any previous value(s) of the same component type.
 | 
					    /// This will overwrite any previous value(s) of the same component type.
 | 
				
			||||||
@ -956,8 +990,8 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns the underlying [`Commands`].
 | 
					    /// Returns the underlying [`Commands`].
 | 
				
			||||||
    pub fn commands(&mut self) -> &mut Commands<'w, 's> {
 | 
					    pub fn commands(&mut self) -> Commands {
 | 
				
			||||||
        self.commands
 | 
					        self.commands.reborrow()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -919,6 +919,14 @@ impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: SystemBuffer> Deferred<'_, T> {
 | 
				
			||||||
 | 
					    /// Returns a [`Deferred<T>`] with a smaller lifetime.
 | 
				
			||||||
 | 
					    /// This is useful if you have `&mut Deferred<T>` but need `Deferred<T>`.
 | 
				
			||||||
 | 
					    pub fn reborrow(&mut self) -> Deferred<T> {
 | 
				
			||||||
 | 
					        Deferred(self.0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SAFETY: Only local state is accessed.
 | 
					// SAFETY: Only local state is accessed.
 | 
				
			||||||
unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
 | 
					unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -274,15 +274,15 @@ impl Command for RemoveParent {
 | 
				
			|||||||
/// });
 | 
					/// });
 | 
				
			||||||
/// # }
 | 
					/// # }
 | 
				
			||||||
/// ```
 | 
					/// ```
 | 
				
			||||||
pub struct ChildBuilder<'w, 's, 'a> {
 | 
					pub struct ChildBuilder<'a> {
 | 
				
			||||||
    commands: &'a mut Commands<'w, 's>,
 | 
					    commands: Commands<'a, 'a>,
 | 
				
			||||||
    push_children: PushChildren,
 | 
					    push_children: PushChildren,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
 | 
					impl ChildBuilder<'_> {
 | 
				
			||||||
    /// Spawns an entity with the given bundle and inserts it into the parent entity's [`Children`].
 | 
					    /// Spawns an entity with the given bundle and inserts it into the parent entity's [`Children`].
 | 
				
			||||||
    /// Also adds [`Parent`] component to the created entity.
 | 
					    /// Also adds [`Parent`] component to the created entity.
 | 
				
			||||||
    pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands<'w, 's, '_> {
 | 
					    pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands {
 | 
				
			||||||
        let e = self.commands.spawn(bundle);
 | 
					        let e = self.commands.spawn(bundle);
 | 
				
			||||||
        self.push_children.children.push(e.id());
 | 
					        self.push_children.children.push(e.id());
 | 
				
			||||||
        e
 | 
					        e
 | 
				
			||||||
@ -290,7 +290,7 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
 | 
					    /// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
 | 
				
			||||||
    /// Also adds [`Parent`] component to the created entity.
 | 
					    /// Also adds [`Parent`] component to the created entity.
 | 
				
			||||||
    pub fn spawn_empty(&mut self) -> EntityCommands<'w, 's, '_> {
 | 
					    pub fn spawn_empty(&mut self) -> EntityCommands {
 | 
				
			||||||
        let e = self.commands.spawn_empty();
 | 
					        let e = self.commands.spawn_empty();
 | 
				
			||||||
        self.push_children.children.push(e.id());
 | 
					        self.push_children.children.push(e.id());
 | 
				
			||||||
        e
 | 
					        e
 | 
				
			||||||
@ -302,7 +302,7 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Adds a command to be executed, like [`Commands::add`].
 | 
					    /// Adds a command to be executed, like [`Commands::add`].
 | 
				
			||||||
    pub fn add_command<C: Command + 'static>(&mut self, command: C) -> &mut Self {
 | 
					    pub fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
 | 
				
			||||||
        self.commands.add(command);
 | 
					        self.commands.add(command);
 | 
				
			||||||
        self
 | 
					        self
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -374,7 +374,7 @@ pub trait BuildChildren {
 | 
				
			|||||||
    fn remove_parent(&mut self) -> &mut Self;
 | 
					    fn remove_parent(&mut self) -> &mut Self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
 | 
					impl BuildChildren for EntityCommands<'_> {
 | 
				
			||||||
    fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self {
 | 
					    fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self {
 | 
				
			||||||
        let parent = self.id();
 | 
					        let parent = self.id();
 | 
				
			||||||
        let mut builder = ChildBuilder {
 | 
					        let mut builder = ChildBuilder {
 | 
				
			||||||
 | 
				
			|||||||
@ -89,7 +89,7 @@ pub trait DespawnRecursiveExt {
 | 
				
			|||||||
    fn despawn_descendants(&mut self) -> &mut Self;
 | 
					    fn despawn_descendants(&mut self) -> &mut Self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'w, 's, 'a> DespawnRecursiveExt for EntityCommands<'w, 's, 'a> {
 | 
					impl DespawnRecursiveExt for EntityCommands<'_> {
 | 
				
			||||||
    /// Despawns the provided entity and its children.
 | 
					    /// Despawns the provided entity and its children.
 | 
				
			||||||
    fn despawn_recursive(mut self) {
 | 
					    fn despawn_recursive(mut self) {
 | 
				
			||||||
        let entity = self.id();
 | 
					        let entity = self.id();
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,7 @@ pub trait BuildChildrenTransformExt {
 | 
				
			|||||||
    /// (during [`apply_deferred`](bevy_ecs::schedule::apply_deferred)).
 | 
					    /// (during [`apply_deferred`](bevy_ecs::schedule::apply_deferred)).
 | 
				
			||||||
    fn remove_parent_in_place(&mut self) -> &mut Self;
 | 
					    fn remove_parent_in_place(&mut self) -> &mut Self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
impl<'w, 's, 'a> BuildChildrenTransformExt for EntityCommands<'w, 's, 'a> {
 | 
					impl BuildChildrenTransformExt for EntityCommands<'_> {
 | 
				
			||||||
    fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self {
 | 
					    fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self {
 | 
				
			||||||
        let child = self.id();
 | 
					        let child = self.id();
 | 
				
			||||||
        self.commands().add(PushChildInPlace { child, parent });
 | 
					        self.commands().add(PushChildInPlace { child, parent });
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user