Skip to content

Commit e0a6c71

Browse files
add EntityRef::get_unchecked_mut_by_id
1 parent 49a9517 commit e0a6c71

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

crates/bevy_ecs/src/world/entity_ref.rs

+31-4
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,31 @@ impl<'w> EntityRef<'w> {
126126
// SAFETY: entity_location is valid, component_id is valid as checked by the line above
127127
unsafe { get_component(self.world, component_id, self.entity, self.location) }
128128
}
129+
130+
/// Gets the component of the given [`ComponentId`] from the entity.
131+
///
132+
/// **You should prefer to use the typed API where possible and only
133+
/// use this in cases where the actual component types are not known at
134+
/// compile time.**
135+
///
136+
/// Unlike [`EntityRef::get`], this returns a raw pointer to the component,
137+
/// which is only valid while the `'w` borrow of the lifetime is active.
138+
///
139+
/// # Safety
140+
///
141+
/// - The returned reference must never alias a mutable borrow of this component.
142+
/// - The returned reference must not be used after this component is moved which
143+
/// may happen from **any** `insert_component`, `remove_component` or `despawn`
144+
/// operation on this world (non-exhaustive list).
145+
#[inline]
146+
pub unsafe fn get_unchecked_mut_by_id(
147+
&self,
148+
component_id: ComponentId,
149+
) -> Option<MutUntyped<'w>> {
150+
self.world.components().get_info(component_id)?;
151+
// SAFETY: entity_location is valid, component_id is valid as checked by the line above, world access is promised by the caller
152+
unsafe { get_mut_by_id(self.world, self.entity, self.location, component_id) }
153+
}
129154
}
130155

131156
impl<'w> From<EntityMut<'w>> for EntityRef<'w> {
@@ -555,7 +580,7 @@ impl<'w> EntityMut<'w> {
555580
#[inline]
556581
pub fn get_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
557582
self.world.components().get_info(component_id)?;
558-
// SAFETY: entity_location is valid, component_id is valid as checked by the line above
583+
// SAFETY: entity_location is valid, component_id is valid as checked by the line above, world access is unique
559584
unsafe { get_mut_by_id(self.world, self.entity, self.location, component_id) }
560585
}
561586
}
@@ -889,15 +914,17 @@ pub(crate) unsafe fn get_mut<T: Component>(
889914
)
890915
}
891916

892-
// SAFETY: EntityLocation must be valid, component_id must be valid
917+
// SAFETY:
918+
// - EntityLocation must be valid, component_id must be valid
919+
// - world access to the component must be valid, either because the caller has a `&mut` world or it synchronizes access like systems do
893920
#[inline]
894921
pub(crate) unsafe fn get_mut_by_id(
895-
world: &mut World,
922+
world: &World,
896923
entity: Entity,
897924
location: EntityLocation,
898925
component_id: ComponentId,
899926
) -> Option<MutUntyped> {
900-
// SAFETY: world access is unique, entity location and component_id required to be valid
927+
// SAFETY: world access promised by the caller, entity location and component_id required to be valid
901928
get_component_and_ticks(world, component_id, entity, location).map(|(value, ticks)| {
902929
MutUntyped {
903930
value: value.assert_unique(),

0 commit comments

Comments
 (0)