Skip to content

Commit

Permalink
use InteriorMutableEntityRef for Query and ReflectComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobhellermann committed Nov 15, 2022
1 parent 967a011 commit 211747c
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 80 deletions.
19 changes: 7 additions & 12 deletions crates/bevy_ecs/src/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,19 +210,14 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
.map(|c| c as &dyn Reflect)
},
reflect_mut: |world, entity| {
// SAFETY: reflect_mut is an unsafe function pointer used by `reflect_unchecked_mut` which promises to never
// produce aliasing mutable references, and reflect_mut, which has mutable world access
// SAFETY: reflect_mut is an unsafe function pointer used by
// 1. `reflect_unchecked_mut` which must be called with an InteriorMutableWorld with access the the component `C` on the `entity`, and
// 2. reflect_mut, which has mutable world access
unsafe {
// SAFETY: entity access through the InteriorMutableWorld is not implemented yet.
// The following code only accesses the component `C` through the entity `entity`
let world = world.world();
world
.get_entity(entity)?
.get_unchecked_mut::<C>(world.last_change_tick(), world.read_change_tick())
.map(|c| Mut {
value: c.value as &mut dyn Reflect,
ticks: c.ticks,
})
world.get_entity(entity)?.get_mut::<C>().map(|c| Mut {
value: c.value as &mut dyn Reflect,
ticks: c.ticks,
})
}
},
})
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_ecs/src/system/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
}
let world = self.world;
let entity_ref = world
.as_interior_mutable()
.get_entity(entity)
.ok_or(QueryComponentError::NoSuchEntity)?;
let component_id = world
Expand All @@ -1189,7 +1190,7 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
.has_write(archetype_component)
{
entity_ref
.get_unchecked_mut::<T>(self.last_change_tick, self.change_tick)
.get_mut_using_ticks::<T>(self.last_change_tick, self.change_tick)
.ok_or(QueryComponentError::MissingComponent)
} else {
Err(QueryComponentError::MissingWriteAccess)
Expand Down
86 changes: 19 additions & 67 deletions crates/bevy_ecs/src/world/entity_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,41 +108,6 @@ impl<'w> EntityRef<'w> {
.map(|ticks| ticks.deref())
}
}

/// Gets a mutable reference to the component of type `T` associated with
/// this entity without ensuring there are no other borrows active and without
/// ensuring that the returned reference will stay valid.
///
/// # Safety
///
/// - The returned reference must never alias a mutable borrow of this component.
/// - The returned reference must not be used after this component is moved which
/// may happen from **any** `insert_component`, `remove_component` or `despawn`
/// operation on this world (non-exhaustive list).
#[inline]
pub unsafe fn get_unchecked_mut<T: Component>(
&self,
last_change_tick: u32,
change_tick: u32,
) -> Option<Mut<'w, T>> {
self.world
.storages
.get_component_and_ticks_with_type(
&self.world.archetypes,
&self.world.components,
TypeId::of::<T>(),
self.entity,
self.location,
)
.map(|(value, ticks)| Mut {
value: value.assert_unique().deref_mut::<T>(),
ticks: Ticks {
component_ticks: ticks.deref_mut(),
last_change_tick,
change_tick,
},
})
}
}

impl<'w> EntityRef<'w> {
Expand Down Expand Up @@ -254,7 +219,25 @@ impl<'w> EntityMut<'w> {
#[inline]
pub fn get_mut<T: Component>(&mut self) -> Option<Mut<'_, T>> {
// SAFETY: world access is unique, and lifetimes enforce correct usage of returned borrow
unsafe { self.get_unchecked_mut::<T>() }
unsafe {
self.world
.storages
.get_component_and_ticks_with_type(
&self.world.archetypes,
&self.world.components,
TypeId::of::<T>(),
self.entity,
self.location,
)
.map(|(value, ticks)| Mut {
value: value.assert_unique().deref_mut::<T>(),
ticks: Ticks {
component_ticks: ticks.deref_mut(),
last_change_tick: self.world.last_change_tick(),
change_tick: self.world.read_change_tick(),
},
})
}
}

/// Retrieves the change ticks for the given component. This can be useful for implementing change
Expand All @@ -280,37 +263,6 @@ impl<'w> EntityMut<'w> {
}
}

/// Gets a mutable reference to the component of type `T` associated with
/// this entity without ensuring there are no other borrows active and without
/// ensuring that the returned reference will stay valid.
///
/// # Safety
///
/// - The returned reference must never alias a mutable borrow of this component.
/// - The returned reference must not be used after this component is moved which
/// may happen from **any** `insert_component`, `remove_component` or `despawn`
/// operation on this world (non-exhaustive list).
#[inline]
pub unsafe fn get_unchecked_mut<T: Component>(&self) -> Option<Mut<'_, T>> {
self.world
.storages
.get_component_and_ticks_with_type(
&self.world.archetypes,
&self.world.components,
TypeId::of::<T>(),
self.entity,
self.location,
)
.map(|(value, ticks)| Mut {
value: value.assert_unique().deref_mut::<T>(),
ticks: Ticks {
component_ticks: ticks.deref_mut(),
last_change_tick: self.world.last_change_tick(),
change_tick: self.world.read_change_tick(),
},
})
}

#[deprecated(
since = "0.9.0",
note = "Use `insert` instead, which now accepts bundles, components, and tuples of bundles and components."
Expand Down

0 comments on commit 211747c

Please sign in to comment.