Skip to content

Commit cf91880

Browse files
add InteriorMutableEntityRef
1 parent 0a64508 commit cf91880

File tree

5 files changed

+253
-88
lines changed

5 files changed

+253
-88
lines changed

crates/bevy_ecs/src/reflect.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,19 +210,14 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
210210
.map(|c| c as &dyn Reflect)
211211
},
212212
reflect_mut: |world, entity| {
213-
// SAFETY: reflect_mut is an unsafe function pointer used by `reflect_unchecked_mut` which promises to never
214-
// produce aliasing mutable references, and reflect_mut, which has mutable world access
213+
// SAFETY: reflect_mut is an unsafe function pointer used by
214+
// 1. `reflect_unchecked_mut` which must be called with an InteriorMutableWorld with access the the component `C` on the `entity`, and
215+
// 2. reflect_mut, which has mutable world access
215216
unsafe {
216-
// SAFETY: entity access through the InteriorMutableWorld is not implemented yet.
217-
// The following code only accesses the component `C` through the entity `entity`
218-
let world = world.world();
219-
world
220-
.get_entity(entity)?
221-
.get_unchecked_mut::<C>(world.last_change_tick(), world.read_change_tick())
222-
.map(|c| Mut {
223-
value: c.value as &mut dyn Reflect,
224-
ticks: c.ticks,
225-
})
217+
world.get_entity(entity)?.get_mut::<C>().map(|c| Mut {
218+
value: c.value as &mut dyn Reflect,
219+
ticks: c.ticks,
220+
})
226221
}
227222
},
228223
})

crates/bevy_ecs/src/system/query.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,7 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
11731173
}
11741174
let world = self.world;
11751175
let entity_ref = world
1176+
.as_interior_mutable()
11761177
.get_entity(entity)
11771178
.ok_or(QueryComponentError::NoSuchEntity)?;
11781179
let component_id = world
@@ -1189,7 +1190,7 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
11891190
.has_write(archetype_component)
11901191
{
11911192
entity_ref
1192-
.get_unchecked_mut::<T>(self.last_change_tick, self.change_tick)
1193+
.get_mut_using_ticks::<T>(self.last_change_tick, self.change_tick)
11931194
.ok_or(QueryComponentError::MissingComponent)
11941195
} else {
11951196
Err(QueryComponentError::MissingWriteAccess)

crates/bevy_ecs/src/world/entity_ref.rs

Lines changed: 23 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -126,39 +126,6 @@ impl<'w> EntityRef<'w> {
126126
)
127127
}
128128
}
129-
130-
/// Gets a mutable reference to the component of type `T` associated with
131-
/// this entity without ensuring there are no other borrows active and without
132-
/// ensuring that the returned reference will stay valid.
133-
///
134-
/// # Safety
135-
///
136-
/// - The returned reference must never alias a mutable borrow of this component.
137-
/// - The returned reference must not be used after this component is moved which
138-
/// may happen from **any** `insert_component`, `remove_component` or `despawn`
139-
/// operation on this world (non-exhaustive list).
140-
#[inline]
141-
pub unsafe fn get_unchecked_mut<T: Component>(
142-
&self,
143-
last_change_tick: u32,
144-
change_tick: u32,
145-
) -> Option<Mut<'w, T>> {
146-
// SAFETY:
147-
// - entity location and entity is valid
148-
// - returned component is of type T
149-
// - the storage type provided is correct for T
150-
self.world
151-
.get_component_and_ticks_with_type(
152-
TypeId::of::<T>(),
153-
T::Storage::STORAGE_TYPE,
154-
self.entity,
155-
self.location,
156-
)
157-
.map(|(value, ticks)| Mut {
158-
value: value.assert_unique().deref_mut::<T>(),
159-
ticks: Ticks::from_tick_cells(ticks, last_change_tick, change_tick),
160-
})
161-
}
162129
}
163130

164131
impl<'w> EntityRef<'w> {
@@ -270,7 +237,23 @@ impl<'w> EntityMut<'w> {
270237
#[inline]
271238
pub fn get_mut<T: Component>(&mut self) -> Option<Mut<'_, T>> {
272239
// SAFETY: world access is unique, and lifetimes enforce correct usage of returned borrow
273-
unsafe { self.get_unchecked_mut::<T>() }
240+
unsafe {
241+
self.world
242+
.get_component_and_ticks_with_type(
243+
TypeId::of::<T>(),
244+
T::Storage::STORAGE_TYPE,
245+
self.entity,
246+
self.location,
247+
)
248+
.map(|(value, cells)| Mut {
249+
value: value.assert_unique().deref_mut::<T>(),
250+
ticks: Ticks::from_tick_cells(
251+
cells,
252+
self.world.last_change_tick,
253+
self.world.read_change_tick(),
254+
),
255+
})
256+
}
274257
}
275258

276259
/// Retrieves the change ticks for the given component. This can be useful for implementing change
@@ -314,39 +297,6 @@ impl<'w> EntityMut<'w> {
314297
}
315298
}
316299

317-
/// Gets a mutable reference to the component of type `T` associated with
318-
/// this entity without ensuring there are no other borrows active and without
319-
/// ensuring that the returned reference will stay valid.
320-
///
321-
/// # Safety
322-
///
323-
/// - The returned reference must never alias a mutable borrow of this component.
324-
/// - The returned reference must not be used after this component is moved which
325-
/// may happen from **any** `insert_component`, `remove_component` or `despawn`
326-
/// operation on this world (non-exhaustive list).
327-
#[inline]
328-
pub unsafe fn get_unchecked_mut<T: Component>(&self) -> Option<Mut<'_, T>> {
329-
// SAFETY:
330-
// - entity location and entity is valid
331-
// - returned component is of type T
332-
// - the storage type provided is correct for T
333-
self.world
334-
.get_component_and_ticks_with_type(
335-
TypeId::of::<T>(),
336-
T::Storage::STORAGE_TYPE,
337-
self.entity,
338-
self.location,
339-
)
340-
.map(|(value, ticks)| Mut {
341-
value: value.assert_unique().deref_mut::<T>(),
342-
ticks: Ticks::from_tick_cells(
343-
ticks,
344-
self.world.last_change_tick(),
345-
self.world.read_change_tick(),
346-
),
347-
})
348-
}
349-
350300
/// Adds a [`Bundle`] of components to the entity.
351301
///
352302
/// This will overwrite any previous value(s) of the same component type.
@@ -694,15 +644,19 @@ impl<'w> EntityMut<'w> {
694644
}
695645
}
696646

697-
fn contains_component_with_type(world: &World, type_id: TypeId, location: EntityLocation) -> bool {
647+
pub(crate) fn contains_component_with_type(
648+
world: &World,
649+
type_id: TypeId,
650+
location: EntityLocation,
651+
) -> bool {
698652
if let Some(component_id) = world.components.get_id(type_id) {
699653
contains_component_with_id(world, component_id, location)
700654
} else {
701655
false
702656
}
703657
}
704658

705-
fn contains_component_with_id(
659+
pub(crate) fn contains_component_with_id(
706660
world: &World,
707661
component_id: ComponentId,
708662
location: EntityLocation,

0 commit comments

Comments
 (0)