Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Simplify lifetimes for Commands and related types #11445

Merged
merged 8 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/reflect/entity_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub trait ReflectCommandExt {
) -> &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 {
self.commands.add(InsertReflect {
entity: self.entity,
Expand Down
60 changes: 47 additions & 13 deletions crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
pub fn append(&mut self, other: &mut CommandQueue) {
self.queue.append(other);
Expand Down Expand Up @@ -186,11 +211,11 @@ impl<'w, 's> Commands<'w, 's> {
///
/// - [`spawn`](Self::spawn) to spawn an entity with a bundle.
/// - [`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();
EntityCommands {
entity,
commands: self,
commands: self.reborrow(),
}
}

Expand All @@ -208,13 +233,13 @@ impl<'w, 's> Commands<'w, 's> {
/// [`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
/// 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| {
world.get_or_spawn(entity);
});
EntityCommands {
entity,
commands: self,
commands: self.reborrow(),
}
}

Expand Down Expand Up @@ -268,7 +293,7 @@ impl<'w, 's> Commands<'w, 's> {
///
/// - [`spawn_empty`](Self::spawn_empty) to spawn an entity without any components.
/// - [`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();
e.insert(bundle);
e
Expand Down Expand Up @@ -310,7 +335,7 @@ impl<'w, 's> Commands<'w, 's> {
/// - [`get_entity`](Self::get_entity) for the fallible version.
#[inline]
#[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)]
#[cold]
#[track_caller]
Expand Down Expand Up @@ -359,10 +384,10 @@ impl<'w, 's> Commands<'w, 's> {
/// - [`entity`](Self::entity) for the panicking version.
#[inline]
#[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 {
entity,
commands: self,
commands: self.reborrow(),
})
}

Expand Down Expand Up @@ -674,12 +699,12 @@ where
}

/// 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) 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.
///
/// # Example
Expand All @@ -698,6 +723,15 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
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.
///
/// This will overwrite any previous value(s) of the same component type.
Expand Down Expand Up @@ -956,8 +990,8 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
}

/// Returns the underlying [`Commands`].
pub fn commands(&mut self) -> &mut Commands<'w, 's> {
self.commands
pub fn commands(&mut self) -> Commands {
JoJoJet marked this conversation as resolved.
Show resolved Hide resolved
self.commands.reborrow()
}
}

Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,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.
unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}

Expand Down
14 changes: 7 additions & 7 deletions crates/bevy_hierarchy/src/child_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,23 +274,23 @@ impl Command for RemoveParent {
/// });
/// # }
/// ```
pub struct ChildBuilder<'w, 's, 'a> {
commands: &'a mut Commands<'w, 's>,
pub struct ChildBuilder<'a> {
commands: Commands<'a, 'a>,
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`].
/// 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);
self.push_children.children.push(e.id());
e
}

/// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
/// 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();
self.push_children.children.push(e.id());
e
Expand All @@ -302,7 +302,7 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
}

/// 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
}
Expand Down Expand Up @@ -374,7 +374,7 @@ pub trait BuildChildren {
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 {
let parent = self.id();
let mut builder = ChildBuilder {
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_hierarchy/src/hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub trait DespawnRecursiveExt {
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.
fn despawn_recursive(mut self) {
let entity = self.id();
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_transform/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub trait BuildChildrenTransformExt {
/// (during [`apply_deferred`](bevy_ecs::schedule::apply_deferred)).
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 {
let child = self.id();
self.commands().add(PushChildInPlace { child, parent });
Expand Down