Skip to content

Commit 051cf16

Browse files
authored
Try #7381:
2 parents 8f81be9 + e51cf50 commit 051cf16

File tree

5 files changed

+506
-524
lines changed

5 files changed

+506
-524
lines changed

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
446446
change_tick: u32,
447447
) -> Self::Item<'w, 's> {
448448
let (ptr, ticks) = world
449+
.as_unsafe_world_cell_migration_internal()
449450
.get_resource_with_ticks(component_id)
450451
.unwrap_or_else(|| {
451452
panic!(
@@ -486,6 +487,7 @@ unsafe impl<'a, T: Resource> SystemParam for Option<Res<'a, T>> {
486487
change_tick: u32,
487488
) -> Self::Item<'w, 's> {
488489
world
490+
.as_unsafe_world_cell_migration_internal()
489491
.get_resource_with_ticks(component_id)
490492
.map(|(ptr, ticks)| Res {
491493
value: ptr.deref(),
@@ -540,7 +542,7 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
540542
) -> Self::Item<'w, 's> {
541543
let value = world
542544
.as_unsafe_world_cell_migration_internal()
543-
.get_resource_mut_with_id(component_id)
545+
.get_resource_mut_by_id(component_id)
544546
.unwrap_or_else(|| {
545547
panic!(
546548
"Resource requested by {} does not exist: {}",
@@ -549,7 +551,7 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
549551
)
550552
});
551553
ResMut {
552-
value: value.value,
554+
value: value.value.deref_mut::<T>(),
553555
ticks: TicksMut {
554556
added: value.ticks.added,
555557
changed: value.ticks.changed,
@@ -578,9 +580,9 @@ unsafe impl<'a, T: Resource> SystemParam for Option<ResMut<'a, T>> {
578580
) -> Self::Item<'w, 's> {
579581
world
580582
.as_unsafe_world_cell_migration_internal()
581-
.get_resource_mut_with_id(component_id)
583+
.get_resource_mut_by_id(component_id)
582584
.map(|value| ResMut {
583-
value: value.value,
585+
value: value.value.deref_mut::<T>(),
584586
ticks: TicksMut {
585587
added: value.ticks.added,
586588
changed: value.ticks.changed,
@@ -889,6 +891,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
889891
change_tick: u32,
890892
) -> Self::Item<'w, 's> {
891893
let (ptr, ticks) = world
894+
.as_unsafe_world_cell_migration_internal()
892895
.get_non_send_with_ticks(component_id)
893896
.unwrap_or_else(|| {
894897
panic!(
@@ -927,6 +930,7 @@ unsafe impl<T: 'static> SystemParam for Option<NonSend<'_, T>> {
927930
change_tick: u32,
928931
) -> Self::Item<'w, 's> {
929932
world
933+
.as_unsafe_world_cell_migration_internal()
930934
.get_non_send_with_ticks(component_id)
931935
.map(|(ptr, ticks)| NonSend {
932936
value: ptr.deref(),
@@ -979,6 +983,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
979983
change_tick: u32,
980984
) -> Self::Item<'w, 's> {
981985
let (ptr, ticks) = world
986+
.as_unsafe_world_cell_migration_internal()
982987
.get_non_send_with_ticks(component_id)
983988
.unwrap_or_else(|| {
984989
panic!(
@@ -1011,6 +1016,7 @@ unsafe impl<'a, T: 'static> SystemParam for Option<NonSendMut<'a, T>> {
10111016
change_tick: u32,
10121017
) -> Self::Item<'w, 's> {
10131018
world
1019+
.as_unsafe_world_cell_migration_internal()
10141020
.get_non_send_with_ticks(component_id)
10151021
.map(|(ptr, ticks)| NonSendMut {
10161022
value: ptr.assert_unique().deref_mut(),

crates/bevy_ecs/src/world/entity_ref.rs

Lines changed: 17 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use crate::{
22
archetype::{Archetype, ArchetypeId, Archetypes},
33
bundle::{Bundle, BundleInfo},
4-
change_detection::{MutUntyped, TicksMut},
5-
component::{
6-
Component, ComponentId, ComponentStorage, ComponentTicks, Components, StorageType,
7-
},
4+
change_detection::MutUntyped,
5+
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
86
entity::{Entities, Entity, EntityLocation},
97
removal_detection::RemovedComponentEvents,
108
storage::Storages,
@@ -79,12 +77,14 @@ impl<'w> EntityRef<'w> {
7977

8078
#[inline]
8179
pub fn contains_id(&self, component_id: ComponentId) -> bool {
82-
contains_component_with_id(self.world, component_id, self.location)
80+
self.as_unsafe_world_cell_readonly()
81+
.contains_id(component_id)
8382
}
8483

8584
#[inline]
8685
pub fn contains_type_id(&self, type_id: TypeId) -> bool {
87-
contains_component_with_type(self.world, type_id, self.location)
86+
self.as_unsafe_world_cell_readonly()
87+
.contains_type_id(type_id)
8888
}
8989

9090
#[inline]
@@ -209,12 +209,14 @@ impl<'w> EntityMut<'w> {
209209

210210
#[inline]
211211
pub fn contains_id(&self, component_id: ComponentId) -> bool {
212-
contains_component_with_id(self.world, component_id, self.location)
212+
self.as_unsafe_world_cell_readonly()
213+
.contains_id(component_id)
213214
}
214215

215216
#[inline]
216217
pub fn contains_type_id(&self, type_id: TypeId) -> bool {
217-
contains_component_with_type(self.world, type_id, self.location)
218+
self.as_unsafe_world_cell_readonly()
219+
.contains_type_id(type_id)
218220
}
219221

220222
#[inline]
@@ -600,19 +602,10 @@ impl<'w> EntityMut<'w> {
600602
/// which is only valid while the [`EntityMut`] is alive.
601603
#[inline]
602604
pub fn get_by_id(&self, component_id: ComponentId) -> Option<Ptr<'_>> {
603-
let info = self.world.components().get_info(component_id)?;
604605
// SAFETY:
605-
// - entity_location is valid
606-
// - component_id is valid as checked by the line above
607-
// - the storage type is accurate as checked by the fetched ComponentInfo
608-
unsafe {
609-
self.world.get_component(
610-
component_id,
611-
info.storage_type(),
612-
self.entity,
613-
self.location,
614-
)
615-
}
606+
// - `&self` ensures that no mutable references exist to this entity's components.
607+
// - `as_unsafe_world_cell_readonly` gives read only permission for all components on this entity
608+
unsafe { self.as_unsafe_world_cell_readonly().get_by_id(component_id) }
616609
}
617610

618611
/// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.
@@ -625,32 +618,13 @@ impl<'w> EntityMut<'w> {
625618
/// which is only valid while the [`EntityMut`] is alive.
626619
#[inline]
627620
pub fn get_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
628-
self.world.components().get_info(component_id)?;
629-
// SAFETY: entity_location is valid, component_id is valid as checked by the line above
630-
unsafe { get_mut_by_id(self.world, self.entity, self.location, component_id) }
631-
}
632-
}
633-
634-
pub(crate) fn contains_component_with_type(
635-
world: &World,
636-
type_id: TypeId,
637-
location: EntityLocation,
638-
) -> bool {
639-
if let Some(component_id) = world.components.get_id(type_id) {
640-
contains_component_with_id(world, component_id, location)
641-
} else {
642-
false
621+
// SAFETY:
622+
// - `&mut self` ensures that no references exist to this entity's components.
623+
// - `as_unsafe_world_cell` gives mutable permission for all components on this entity
624+
unsafe { self.as_unsafe_world_cell().get_mut_by_id(component_id) }
643625
}
644626
}
645627

646-
pub(crate) fn contains_component_with_id(
647-
world: &World,
648-
component_id: ComponentId,
649-
location: EntityLocation,
650-
) -> bool {
651-
world.archetypes[location.archetype_id].contains(component_id)
652-
}
653-
654628
/// Removes a bundle from the given archetype and returns the resulting archetype (or None if the
655629
/// removal was invalid). in the event that adding the given bundle does not result in an Archetype
656630
/// change. Results are cached in the Archetype Graph to avoid redundant work.
@@ -768,59 +742,6 @@ fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
768742
});
769743
}
770744

771-
// SAFETY: EntityLocation must be valid
772-
#[inline]
773-
pub(crate) unsafe fn get_mut<T: Component>(
774-
world: &mut World,
775-
entity: Entity,
776-
location: EntityLocation,
777-
) -> Option<Mut<'_, T>> {
778-
let change_tick = world.change_tick();
779-
let last_change_tick = world.last_change_tick();
780-
// SAFETY:
781-
// - world access is unique
782-
// - entity location is valid
783-
// - returned component is of type T
784-
world
785-
.get_component_and_ticks_with_type(
786-
TypeId::of::<T>(),
787-
T::Storage::STORAGE_TYPE,
788-
entity,
789-
location,
790-
)
791-
.map(|(value, ticks)| Mut {
792-
// SAFETY:
793-
// - world access is unique and ties world lifetime to `Mut` lifetime
794-
// - `value` is of type `T`
795-
value: value.assert_unique().deref_mut::<T>(),
796-
ticks: TicksMut::from_tick_cells(ticks, last_change_tick, change_tick),
797-
})
798-
}
799-
800-
// SAFETY: EntityLocation must be valid, component_id must be valid
801-
#[inline]
802-
pub(crate) unsafe fn get_mut_by_id(
803-
world: &mut World,
804-
entity: Entity,
805-
location: EntityLocation,
806-
component_id: ComponentId,
807-
) -> Option<MutUntyped<'_>> {
808-
let change_tick = world.change_tick();
809-
// SAFETY: component_id is valid
810-
let info = world.components.get_info_unchecked(component_id);
811-
// SAFETY:
812-
// - world access is unique
813-
// - entity location is valid
814-
// - returned component is of type T
815-
world
816-
.get_component_and_ticks(component_id, info.storage_type(), entity, location)
817-
.map(|(value, ticks)| MutUntyped {
818-
// SAFETY: world access is unique and ties world lifetime to `MutUntyped` lifetime
819-
value: value.assert_unique(),
820-
ticks: TicksMut::from_tick_cells(ticks, world.last_change_tick(), change_tick),
821-
})
822-
}
823-
824745
/// Moves component data out of storage.
825746
///
826747
/// This function leaves the underlying memory unchanged, but the component behind

0 commit comments

Comments
 (0)