Skip to content

Commit de1dcb9

Browse files
authored
Provide access to world storages via UnsafeWorldCell (#8987)
# Objective Title. This is necessary in order to update [`bevy-trait-query`](https://crates.io/crates/bevy-trait-query) to Bevy 0.11. --- ## Changelog Added the unsafe function `UnsafeWorldCell::storages`, which provides unchecked access to the internal data stores of a `World`.
1 parent e29981d commit de1dcb9

File tree

4 files changed

+30
-29
lines changed

4 files changed

+30
-29
lines changed

crates/bevy_ecs/src/query/fetch.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,6 @@ unsafe impl<T: Component> WorldQuery for &T {
662662
// which we are allowed to access since we registered it in `update_archetype_component_access`.
663663
// Note that we do not actually access any components in this function, we just get a shared
664664
// reference to the sparse set, which is used to access the components in `Self::fetch`.
665-
.unsafe_world()
666665
.storages()
667666
.sparse_sets
668667
.get(component_id)
@@ -810,7 +809,6 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
810809
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
811810
world
812811
// SAFETY: See &T::init_fetch.
813-
.unsafe_world()
814812
.storages()
815813
.sparse_sets
816814
.get(component_id)
@@ -974,7 +972,6 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
974972
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
975973
world
976974
// SAFETY: See &T::init_fetch.
977-
.unsafe_world()
978975
.storages()
979976
.sparse_sets
980977
.get(component_id)

crates/bevy_ecs/src/query/iter.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIter<'w, 's, Q, F> {
3434
QueryIter {
3535
query_state,
3636
// SAFETY: We only access table data that has been registered in `query_state`.
37-
tables: &world.unsafe_world().storages().tables,
37+
tables: &world.storages().tables,
3838
archetypes: world.archetypes(),
3939
cursor: QueryIterationCursor::init(world, query_state, last_run, this_run),
4040
}
@@ -107,7 +107,7 @@ where
107107
archetypes: world.archetypes(),
108108
// SAFETY: We only access table data that has been registered in `query_state`.
109109
// This means `world` has permission to access the data we use.
110-
tables: &world.unsafe_world().storages.tables,
110+
tables: &world.storages().tables,
111111
fetch,
112112
filter,
113113
entity_iter: entity_list.into_iter(),
@@ -316,7 +316,7 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery, const K: usize>
316316
QueryCombinationIter {
317317
query_state,
318318
// SAFETY: We only access table data that has been registered in `query_state`.
319-
tables: &world.unsafe_world().storages().tables,
319+
tables: &world.storages().tables,
320320
archetypes: world.archetypes(),
321321
cursors: array.assume_init(),
322322
}

crates/bevy_ecs/src/query/state.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,6 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
462462
let mut filter = F::init_fetch(world, &self.filter_state, last_run, this_run);
463463

464464
let table = world
465-
.unsafe_world()
466465
.storages()
467466
.tables
468467
.get(location.table_id)
@@ -973,7 +972,7 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
973972
let mut fetch = Q::init_fetch(world, &self.fetch_state, last_run, this_run);
974973
let mut filter = F::init_fetch(world, &self.filter_state, last_run, this_run);
975974

976-
let tables = &world.unsafe_world().storages().tables;
975+
let tables = &world.storages().tables;
977976
if Q::IS_DENSE && F::IS_DENSE {
978977
for table_id in &self.matched_table_ids {
979978
let table = tables.get(*table_id).debug_checked_unwrap();
@@ -1048,7 +1047,7 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
10481047
ComputeTaskPool::get().scope(|scope| {
10491048
if Q::IS_DENSE && F::IS_DENSE {
10501049
// SAFETY: We only access table data that has been registered in `self.archetype_component_access`.
1051-
let tables = &world.unsafe_world().storages().tables;
1050+
let tables = &world.storages().tables;
10521051
for table_id in &self.matched_table_ids {
10531052
let table = &tables[*table_id];
10541053
if table.is_empty() {
@@ -1064,7 +1063,7 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
10641063
Q::init_fetch(world, &self.fetch_state, last_run, this_run);
10651064
let mut filter =
10661065
F::init_fetch(world, &self.filter_state, last_run, this_run);
1067-
let tables = &world.unsafe_world().storages().tables;
1066+
let tables = &world.storages().tables;
10681067
let table = tables.get(*table_id).debug_checked_unwrap();
10691068
let entities = table.entities();
10701069
Q::set_table(&mut fetch, &self.fetch_state, table);
@@ -1108,7 +1107,7 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
11081107
Q::init_fetch(world, &self.fetch_state, last_run, this_run);
11091108
let mut filter =
11101109
F::init_fetch(world, &self.filter_state, last_run, this_run);
1111-
let tables = &world.unsafe_world().storages().tables;
1110+
let tables = &world.storages().tables;
11121111
let archetype =
11131112
world.archetypes().get(*archetype_id).debug_checked_unwrap();
11141113
let table = tables.get(archetype.table_id()).debug_checked_unwrap();

crates/bevy_ecs/src/world/unsafe_world_cell.rs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
},
1313
entity::{Entities, Entity, EntityLocation},
1414
prelude::Component,
15-
storage::{Column, ComponentSparseSet},
15+
storage::{Column, ComponentSparseSet, Storages},
1616
system::Resource,
1717
};
1818
use bevy_ptr::Ptr;
@@ -271,6 +271,20 @@ impl<'w> UnsafeWorldCell<'w> {
271271
unsafe { self.world_metadata() }.increment_change_tick()
272272
}
273273

274+
/// Provides unchecked access to the internal data stores of the [`World`].
275+
///
276+
/// # Safety
277+
///
278+
/// The caller must ensure that this is only used to access world data
279+
/// that this [`UnsafeWorldCell`] is allowed to.
280+
/// As always, any mutable access to a component must not exist at the same
281+
/// time as any other accesses to that same component.
282+
#[inline]
283+
pub unsafe fn storages(self) -> &'w Storages {
284+
// SAFETY: The caller promises to only access world data allowed by this instance.
285+
&unsafe { self.unsafe_world() }.storages
286+
}
287+
274288
/// Shorthand helper function for getting the [`ArchetypeComponentId`] for a resource.
275289
#[inline]
276290
pub(crate) fn get_resource_archetype_component_id(
@@ -342,8 +356,7 @@ impl<'w> UnsafeWorldCell<'w> {
342356
pub unsafe fn get_resource_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
343357
// SAFETY: caller ensures that `self` has permission to access `R`
344358
// caller ensures that no mutable reference exists to `R`
345-
unsafe { self.unsafe_world() }
346-
.storages
359+
unsafe { self.storages() }
347360
.resources
348361
.get(component_id)?
349362
.get_data()
@@ -385,8 +398,7 @@ impl<'w> UnsafeWorldCell<'w> {
385398
pub unsafe fn get_non_send_resource_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
386399
// SAFETY: we only access data on world that the caller has ensured is unaliased and we have
387400
// permission to access.
388-
unsafe { self.unsafe_world() }
389-
.storages
401+
unsafe { self.storages() }
390402
.non_send_resources
391403
.get(component_id)?
392404
.get_data()
@@ -429,8 +441,7 @@ impl<'w> UnsafeWorldCell<'w> {
429441
) -> Option<MutUntyped<'w>> {
430442
// SAFETY: we only access data that the caller has ensured is unaliased and `self`
431443
// has permission to access.
432-
let (ptr, ticks) = unsafe { self.unsafe_world() }
433-
.storages
444+
let (ptr, ticks) = unsafe { self.storages() }
434445
.resources
435446
.get(component_id)?
436447
.get_with_ticks()?;
@@ -492,8 +503,7 @@ impl<'w> UnsafeWorldCell<'w> {
492503
let change_tick = self.change_tick();
493504
// SAFETY: we only access data that the caller has ensured is unaliased and `self`
494505
// has permission to access.
495-
let (ptr, ticks) = unsafe { self.unsafe_world() }
496-
.storages
506+
let (ptr, ticks) = unsafe { self.storages() }
497507
.non_send_resources
498508
.get(component_id)?
499509
.get_with_ticks()?;
@@ -526,8 +536,7 @@ impl<'w> UnsafeWorldCell<'w> {
526536
// - caller ensures there is no `&mut World`
527537
// - caller ensures there are no mutable borrows of this resource
528538
// - caller ensures that we have permission to access this resource
529-
unsafe { self.unsafe_world() }
530-
.storages
539+
unsafe { self.storages() }
531540
.resources
532541
.get(component_id)?
533542
.get_with_ticks()
@@ -551,8 +560,7 @@ impl<'w> UnsafeWorldCell<'w> {
551560
// - caller ensures there is no `&mut World`
552561
// - caller ensures there are no mutable borrows of this resource
553562
// - caller ensures that we have permission to access this resource
554-
unsafe { self.unsafe_world() }
555-
.storages
563+
unsafe { self.storages() }
556564
.non_send_resources
557565
.get(component_id)?
558566
.get_with_ticks()
@@ -878,7 +886,7 @@ impl<'w> UnsafeWorldCell<'w> {
878886
) -> Option<&'w Column> {
879887
// SAFETY: caller ensures returned data is not misused and we have not created any borrows
880888
// of component/resource data
881-
unsafe { self.unsafe_world() }.storages.tables[location.table_id].get_column(component_id)
889+
unsafe { self.storages() }.tables[location.table_id].get_column(component_id)
882890
}
883891

884892
#[inline]
@@ -889,10 +897,7 @@ impl<'w> UnsafeWorldCell<'w> {
889897
unsafe fn fetch_sparse_set(self, component_id: ComponentId) -> Option<&'w ComponentSparseSet> {
890898
// SAFETY: caller ensures returned data is not misused and we have not created any borrows
891899
// of component/resource data
892-
unsafe { self.unsafe_world() }
893-
.storages
894-
.sparse_sets
895-
.get(component_id)
900+
unsafe { self.storages() }.sparse_sets.get(component_id)
896901
}
897902
}
898903

0 commit comments

Comments
 (0)