Skip to content

Commit b5b72aa

Browse files
maniwaniProfLander
authored andcommitted
EntityMut: rename remove_intersection to remove and remove to take (bevyengine#7810)
# Objective - A more intuitive distinction between the two. `remove_intersection` is verbose and unclear. - `EntityMut::remove` and `Commands::remove` should match. ## Solution - What the title says. --- ## Migration Guide Before ```rust fn clear_children(parent: Entity, world: &mut World) { if let Some(children) = world.entity_mut(parent).remove::<Children>() { for &child in &children.0 { world.entity_mut(child).remove_intersection::<Parent>(); } } } ``` After ```rust fn clear_children(parent: Entity, world: &mut World) { if let Some(children) = world.entity_mut(parent).take::<Children>() { for &child in &children.0 { world.entity_mut(child).remove::<Parent>(); } } } ```
1 parent 52ece5f commit b5b72aa

File tree

8 files changed

+46
-54
lines changed

8 files changed

+46
-54
lines changed

crates/bevy_ecs/src/archetype.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl BundleComponentStatus for SpawnBundleStatus {
150150
pub struct Edges {
151151
add_bundle: SparseArray<BundleId, AddBundle>,
152152
remove_bundle: SparseArray<BundleId, Option<ArchetypeId>>,
153-
remove_bundle_intersection: SparseArray<BundleId, Option<ArchetypeId>>,
153+
take_bundle: SparseArray<BundleId, Option<ArchetypeId>>,
154154
}
155155

156156
impl Edges {
@@ -222,32 +222,28 @@ impl Edges {
222222
}
223223

224224
/// Checks the cache for the target archetype when removing a bundle to the
225-
/// source archetype. For more information, see [`EntityMut::remove_intersection`].
225+
/// source archetype. For more information, see [`EntityMut::remove`].
226226
///
227227
/// If this returns `None`, it means there has not been a transition from
228228
/// the source archetype via the provided bundle.
229229
///
230-
/// [`EntityMut::remove_intersection`]: crate::world::EntityMut::remove_intersection
230+
/// [`EntityMut::remove`]: crate::world::EntityMut::remove
231231
#[inline]
232-
pub fn get_remove_bundle_intersection(
233-
&self,
234-
bundle_id: BundleId,
235-
) -> Option<Option<ArchetypeId>> {
236-
self.remove_bundle_intersection.get(bundle_id).cloned()
232+
pub fn get_take_bundle(&self, bundle_id: BundleId) -> Option<Option<ArchetypeId>> {
233+
self.take_bundle.get(bundle_id).cloned()
237234
}
238235

239236
/// Caches the target archetype when removing a bundle to the source archetype.
240-
/// For more information, see [`EntityMut::remove_intersection`].
237+
/// For more information, see [`EntityMut::take`].
241238
///
242-
/// [`EntityMut::remove_intersection`]: crate::world::EntityMut::remove_intersection
239+
/// [`EntityMut::take`]: crate::world::EntityMut::take
243240
#[inline]
244-
pub(crate) fn insert_remove_bundle_intersection(
241+
pub(crate) fn insert_take_bundle(
245242
&mut self,
246243
bundle_id: BundleId,
247244
archetype_id: Option<ArchetypeId>,
248245
) {
249-
self.remove_bundle_intersection
250-
.insert(bundle_id, archetype_id);
246+
self.take_bundle.insert(bundle_id, archetype_id);
251247
}
252248
}
253249

crates/bevy_ecs/src/lib.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ mod tests {
191191
assert_eq!(world.get::<SparseStored>(e2).unwrap().0, 42);
192192

193193
assert_eq!(
194-
world.entity_mut(e1).remove::<FooBundle>().unwrap(),
194+
world.entity_mut(e1).take::<FooBundle>().unwrap(),
195195
FooBundle {
196196
x: TableStored("xyz"),
197197
y: SparseStored(123),
@@ -240,7 +240,7 @@ mod tests {
240240
assert_eq!(world.get::<A>(e3).unwrap().0, 1);
241241
assert_eq!(world.get::<B>(e3).unwrap().0, 2);
242242
assert_eq!(
243-
world.entity_mut(e3).remove::<NestedBundle>().unwrap(),
243+
world.entity_mut(e3).take::<NestedBundle>().unwrap(),
244244
NestedBundle {
245245
a: A(1),
246246
foo: FooBundle {
@@ -283,7 +283,7 @@ mod tests {
283283
assert_eq!(world.get::<Ignored>(e4), None);
284284

285285
assert_eq!(
286-
world.entity_mut(e4).remove::<BundleWithIgnored>().unwrap(),
286+
world.entity_mut(e4).take::<BundleWithIgnored>().unwrap(),
287287
BundleWithIgnored {
288288
c: C,
289289
ignored: Ignored,
@@ -596,7 +596,7 @@ mod tests {
596596
&[(e1, A(1), B(3)), (e2, A(2), B(4))]
597597
);
598598

599-
assert_eq!(world.entity_mut(e1).remove::<A>(), Some(A(1)));
599+
assert_eq!(world.entity_mut(e1).take::<A>(), Some(A(1)));
600600
assert_eq!(
601601
world
602602
.query::<(Entity, &A, &B)>()
@@ -656,7 +656,7 @@ mod tests {
656656
}
657657

658658
for (i, entity) in entities.iter().cloned().enumerate() {
659-
assert_eq!(world.entity_mut(entity).remove::<A>(), Some(A(i)));
659+
assert_eq!(world.entity_mut(entity).take::<A>(), Some(A(i)));
660660
}
661661
}
662662

@@ -675,7 +675,7 @@ mod tests {
675675

676676
for (i, entity) in entities.iter().cloned().enumerate() {
677677
assert_eq!(
678-
world.entity_mut(entity).remove::<SparseStored>(),
678+
world.entity_mut(entity).take::<SparseStored>(),
679679
Some(SparseStored(i as u32))
680680
);
681681
}
@@ -685,7 +685,7 @@ mod tests {
685685
fn remove_missing() {
686686
let mut world = World::new();
687687
let e = world.spawn((TableStored("abc"), A(123))).id();
688-
assert!(world.entity_mut(e).remove::<B>().is_none());
688+
assert!(world.entity_mut(e).take::<B>().is_none());
689689
}
690690

691691
#[test]
@@ -1187,7 +1187,7 @@ mod tests {
11871187
}
11881188

11891189
#[test]
1190-
fn remove_intersection() {
1190+
fn remove() {
11911191
let mut world = World::default();
11921192
let e1 = world.spawn((A(1), B(1), TableStored("a"))).id();
11931193

@@ -1201,7 +1201,7 @@ mod tests {
12011201
"C is not in the entity, so it should not exist"
12021202
);
12031203

1204-
e.remove_intersection::<(A, B, C)>();
1204+
e.remove::<(A, B, C)>();
12051205
assert_eq!(
12061206
e.get::<TableStored>(),
12071207
Some(&TableStored("a")),
@@ -1225,7 +1225,7 @@ mod tests {
12251225
}
12261226

12271227
#[test]
1228-
fn remove() {
1228+
fn take() {
12291229
let mut world = World::default();
12301230
world.spawn((A(1), B(1), TableStored("1")));
12311231
let e2 = world.spawn((A(2), B(2), TableStored("2"))).id();
@@ -1238,7 +1238,7 @@ mod tests {
12381238
.collect::<Vec<_>>();
12391239
assert_eq!(results, vec![(1, "1"), (2, "2"), (3, "3"),]);
12401240

1241-
let removed_bundle = world.entity_mut(e2).remove::<(B, TableStored)>().unwrap();
1241+
let removed_bundle = world.entity_mut(e2).take::<(B, TableStored)>().unwrap();
12421242
assert_eq!(removed_bundle, (B(2), TableStored("2")));
12431243

12441244
let results = query

crates/bevy_ecs/src/reflect.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,6 @@ impl ReflectComponent {
9999
}
100100

101101
/// Removes this [`Component`] type from the entity. Does nothing if it doesn't exist.
102-
///
103-
/// # Panics
104-
///
105-
/// Panics if there is no [`Component`] of the given type.
106102
pub fn remove(&self, entity: &mut EntityMut) {
107103
(self.0.remove)(entity);
108104
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -951,9 +951,7 @@ where
951951
{
952952
fn write(self, world: &mut World) {
953953
if let Some(mut entity_mut) = world.get_entity_mut(self.entity) {
954-
// remove intersection to gracefully handle components that were removed before running
955-
// this command
956-
entity_mut.remove_intersection::<T>();
954+
entity_mut.remove::<T>();
957955
}
958956
}
959957
}

crates/bevy_ecs/src/world/entity_ref.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,13 @@ impl<'w> EntityMut<'w> {
279279
self
280280
}
281281

282-
// TODO: move to BundleInfo
283-
/// Removes a [`Bundle`] of components from the entity and returns the bundle.
282+
/// Removes all components in the [`Bundle`] from the entity and returns their previous values.
284283
///
285-
/// Returns `None` if the entity does not contain the bundle.
286-
pub fn remove<T: Bundle>(&mut self) -> Option<T> {
284+
/// **Note:** If the entity does not have every component in the bundle, this method will not
285+
/// remove any of them.
286+
// TODO: BundleRemover?
287+
#[must_use]
288+
pub fn take<T: Bundle>(&mut self) -> Option<T> {
287289
let archetypes = &mut self.world.archetypes;
288290
let storages = &mut self.world.storages;
289291
let components = &mut self.world.components;
@@ -408,9 +410,9 @@ impl<'w> EntityMut<'w> {
408410
entities.set(entity.index(), new_location);
409411
}
410412

411-
// TODO: move to BundleInfo
412-
/// Remove any components in the bundle that the entity has.
413-
pub fn remove_intersection<T: Bundle>(&mut self) {
413+
/// Removes any components in the [`Bundle`] from the entity.
414+
// TODO: BundleRemover?
415+
pub fn remove<T: Bundle>(&mut self) -> &mut Self {
414416
let archetypes = &mut self.world.archetypes;
415417
let storages = &mut self.world.storages;
416418
let components = &mut self.world.components;
@@ -435,7 +437,7 @@ impl<'w> EntityMut<'w> {
435437
};
436438

437439
if new_archetype_id == old_location.archetype_id {
438-
return;
440+
return self;
439441
}
440442

441443
let old_archetype = &mut archetypes[old_location.archetype_id];
@@ -469,6 +471,8 @@ impl<'w> EntityMut<'w> {
469471
new_archetype_id,
470472
);
471473
}
474+
475+
self
472476
}
473477

474478
pub fn despawn(self) {
@@ -647,11 +651,9 @@ unsafe fn remove_bundle_from_archetype(
647651
let remove_bundle_result = {
648652
let current_archetype = &mut archetypes[archetype_id];
649653
if intersection {
650-
current_archetype
651-
.edges()
652-
.get_remove_bundle_intersection(bundle_info.id)
653-
} else {
654654
current_archetype.edges().get_remove_bundle(bundle_info.id)
655+
} else {
656+
current_archetype.edges().get_take_bundle(bundle_info.id)
655657
}
656658
};
657659
let result = if let Some(result) = remove_bundle_result {
@@ -679,7 +681,7 @@ unsafe fn remove_bundle_from_archetype(
679681
// graph
680682
current_archetype
681683
.edges_mut()
682-
.insert_remove_bundle(bundle_info.id, None);
684+
.insert_take_bundle(bundle_info.id, None);
683685
return None;
684686
}
685687
}
@@ -718,11 +720,11 @@ unsafe fn remove_bundle_from_archetype(
718720
if intersection {
719721
current_archetype
720722
.edges_mut()
721-
.insert_remove_bundle_intersection(bundle_info.id, result);
723+
.insert_remove_bundle(bundle_info.id, result);
722724
} else {
723725
current_archetype
724726
.edges_mut()
725-
.insert_remove_bundle(bundle_info.id, result);
727+
.insert_take_bundle(bundle_info.id, result);
726728
}
727729
result
728730
}

crates/bevy_ecs_compile_fail_tests/tests/ui/entity_ref_mut_lifetime_safety.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ fn main() {
1414

1515
{
1616
let gotten: &A = e_mut.get::<A>().unwrap();
17-
let gotten2: A = e_mut.remove::<A>().unwrap();
17+
let gotten2: A = e_mut.take::<A>().unwrap();
1818
assert_eq!(gotten, &gotten2); // oops UB
1919
}
2020

2121
e_mut.insert(A(Box::new(12_usize)));
2222

2323
{
2424
let mut gotten: Mut<A> = e_mut.get_mut::<A>().unwrap();
25-
let mut gotten2: A = e_mut.remove::<A>().unwrap();
25+
let mut gotten2: A = e_mut.take::<A>().unwrap();
2626
assert_eq!(&mut *gotten, &mut gotten2); // oops UB
2727
}
2828

crates/bevy_ecs_compile_fail_tests/tests/ui/entity_ref_mut_lifetime_safety.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ error[E0502]: cannot borrow `e_mut` as mutable because it is also borrowed as im
33
|
44
16 | let gotten: &A = e_mut.get::<A>().unwrap();
55
| ---------------- immutable borrow occurs here
6-
17 | let gotten2: A = e_mut.remove::<A>().unwrap();
7-
| ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
6+
17 | let gotten2: A = e_mut.take::<A>().unwrap();
7+
| ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
88
18 | assert_eq!(gotten, &gotten2); // oops UB
99
| ---------------------------- immutable borrow later used here
1010

@@ -13,8 +13,8 @@ error[E0499]: cannot borrow `e_mut` as mutable more than once at a time
1313
|
1414
24 | let mut gotten: Mut<A> = e_mut.get_mut::<A>().unwrap();
1515
| -------------------- first mutable borrow occurs here
16-
25 | let mut gotten2: A = e_mut.remove::<A>().unwrap();
17-
| ^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
16+
25 | let mut gotten2: A = e_mut.take::<A>().unwrap();
17+
| ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
1818
26 | assert_eq!(&mut *gotten, &mut gotten2); // oops UB
1919
| ------ first borrow later used here
2020

crates/bevy_hierarchy/src/child_builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ fn remove_children(parent: Entity, children: &[Entity], world: &mut World) {
141141
}
142142

143143
fn clear_children(parent: Entity, world: &mut World) {
144-
if let Some(children) = world.entity_mut(parent).remove::<Children>() {
144+
if let Some(children) = world.entity_mut(parent).take::<Children>() {
145145
for &child in &children.0 {
146146
world.entity_mut(child).remove::<Parent>();
147147
}
@@ -532,7 +532,7 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
532532

533533
fn remove_parent(&mut self) -> &mut Self {
534534
let child = self.id();
535-
if let Some(parent) = self.remove::<Parent>().map(|p| p.get()) {
535+
if let Some(parent) = self.take::<Parent>().map(|p| p.get()) {
536536
self.world_scope(|world| {
537537
remove_from_children(world, parent, child);
538538
push_events(world, [HierarchyEvent::ChildRemoved { child, parent }]);

0 commit comments

Comments
 (0)