mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 20:53:53 +00:00
Hide UnsafeWorldCell::unsafe_world
(#9741)
# Objective We've done a lot of work to remove the pattern of a `&World` with interior mutability (#6404, #8833). However, this pattern still persists within `bevy_ecs` via the `unsafe_world` method. ## Solution * Make `unsafe_world` private. Adjust any callsites to use `UnsafeWorldCell` for interior mutability. * Add `UnsafeWorldCell::removed_components`, since it is always safe to access the removed components collection through `UnsafeWorldCell`. ## Future Work Remove/hide `UnsafeWorldCell::world_metadata`, once we have provided safe ways of accessing all world metadata. --- ## Changelog + Added `UnsafeWorldCell::removed_components`, which provides read-only access to a world's collection of removed components.
This commit is contained in:
parent
450328d15e
commit
8cc255c2f0
5 changed files with 29 additions and 24 deletions
|
@ -427,8 +427,7 @@ macro_rules! impl_tick_filter {
|
|||
table_ticks: None,
|
||||
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
|
||||
.then(|| {
|
||||
world.unsafe_world()
|
||||
.storages()
|
||||
world.storages()
|
||||
.sparse_sets
|
||||
.get(id)
|
||||
.debug_checked_unwrap()
|
||||
|
|
|
@ -338,10 +338,12 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
|
|||
) -> Result<[ROQueryItem<'w, Q>; N], QueryEntityError> {
|
||||
self.update_archetypes(world);
|
||||
|
||||
// SAFETY: update_archetypes validates the `World` matches
|
||||
// SAFETY:
|
||||
// - We have read-only access to the entire world.
|
||||
// - `update_archetypes` validates that the `World` matches.
|
||||
unsafe {
|
||||
self.get_many_read_only_manual(
|
||||
world,
|
||||
world.as_unsafe_world_cell_readonly(),
|
||||
entities,
|
||||
world.last_change_tick(),
|
||||
world.read_change_tick(),
|
||||
|
@ -633,11 +635,13 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This must be called on the same `World` that the `Query` was generated from:
|
||||
/// * `world` must have permission to read all of the components returned from this call.
|
||||
/// No mutable references may coexist with any of the returned references.
|
||||
/// * This must be called on the same `World` that the `Query` was generated from:
|
||||
/// use `QueryState::validate_world` to verify this.
|
||||
pub(crate) unsafe fn get_many_read_only_manual<'w, const N: usize>(
|
||||
&self,
|
||||
world: &'w World,
|
||||
world: UnsafeWorldCell<'w>,
|
||||
entities: [Entity; N],
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
|
@ -647,12 +651,9 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
|
|||
for (value, entity) in std::iter::zip(&mut values, entities) {
|
||||
// SAFETY: fetch is read-only
|
||||
// and world must be validated
|
||||
let item = self.as_readonly().get_unchecked_manual(
|
||||
world.as_unsafe_world_cell_readonly(),
|
||||
entity,
|
||||
last_run,
|
||||
this_run,
|
||||
)?;
|
||||
let item = self
|
||||
.as_readonly()
|
||||
.get_unchecked_manual(world, entity, last_run, this_run)?;
|
||||
*value = MaybeUninit::new(item);
|
||||
}
|
||||
|
||||
|
|
|
@ -259,8 +259,7 @@ impl<'w, 's, T: Component> RemovedComponents<'w, 's, T> {
|
|||
// SAFETY: Only reads World removed component events
|
||||
unsafe impl<'a> ReadOnlySystemParam for &'a RemovedComponentEvents {}
|
||||
|
||||
// SAFETY: no component value access, removed component events can be read in parallel and are
|
||||
// never mutably borrowed during system execution
|
||||
// SAFETY: no component value access.
|
||||
unsafe impl<'a> SystemParam for &'a RemovedComponentEvents {
|
||||
type State = ();
|
||||
type Item<'w, 's> = &'w RemovedComponentEvents;
|
||||
|
@ -274,6 +273,6 @@ unsafe impl<'a> SystemParam for &'a RemovedComponentEvents {
|
|||
world: UnsafeWorldCell<'w>,
|
||||
_change_tick: Tick,
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.world_metadata().removed_components()
|
||||
world.removed_components()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -874,14 +874,12 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> {
|
|||
&self,
|
||||
entities: [Entity; N],
|
||||
) -> Result<[ROQueryItem<'_, Q>; N], QueryEntityError> {
|
||||
// SAFETY: it is the scheduler's responsibility to ensure that `Query` is never handed out on the wrong `World`.
|
||||
// SAFETY:
|
||||
// - `&self` ensures there is no mutable access to any components accessible to this query.
|
||||
// - `self.world` matches `self.state`.
|
||||
unsafe {
|
||||
self.state.get_many_read_only_manual(
|
||||
self.world.unsafe_world(),
|
||||
entities,
|
||||
self.last_run,
|
||||
self.this_run,
|
||||
)
|
||||
self.state
|
||||
.get_many_read_only_manual(self.world, entities, self.last_run, self.this_run)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::{
|
|||
},
|
||||
entity::{Entities, Entity, EntityLocation},
|
||||
prelude::Component,
|
||||
removal_detection::RemovedComponentEvents,
|
||||
storage::{Column, ComponentSparseSet, Storages},
|
||||
system::Resource,
|
||||
};
|
||||
|
@ -156,7 +157,7 @@ impl<'w> UnsafeWorldCell<'w> {
|
|||
// - caller ensures there is no `&mut World` this makes it okay to make a `&World`
|
||||
// - caller ensures there is no mutable borrows of world data, this means the caller cannot
|
||||
// misuse the returned `&World`
|
||||
unsafe { &*self.0 }
|
||||
unsafe { self.unsafe_world() }
|
||||
}
|
||||
|
||||
/// Gets a reference to the [`World`] this [`UnsafeWorldCell`] belong to.
|
||||
|
@ -185,7 +186,7 @@ impl<'w> UnsafeWorldCell<'w> {
|
|||
/// - must not be used in a way that would conflict with any
|
||||
/// live exclusive borrows on world data
|
||||
#[inline]
|
||||
pub(crate) unsafe fn unsafe_world(self) -> &'w World {
|
||||
unsafe fn unsafe_world(self) -> &'w World {
|
||||
// SAFETY:
|
||||
// - caller ensures that the returned `&World` is not used in a way that would conflict
|
||||
// with any existing mutable borrows of world data
|
||||
|
@ -224,6 +225,13 @@ impl<'w> UnsafeWorldCell<'w> {
|
|||
&unsafe { self.world_metadata() }.components
|
||||
}
|
||||
|
||||
/// Retrieves this world's collection of [removed components](RemovedComponentEvents).
|
||||
pub fn removed_components(self) -> &'w RemovedComponentEvents {
|
||||
// SAFETY:
|
||||
// - we only access world metadata
|
||||
&unsafe { self.world_metadata() }.removed_components
|
||||
}
|
||||
|
||||
/// Retrieves this world's [`Bundles`] collection.
|
||||
#[inline]
|
||||
pub fn bundles(self) -> &'w Bundles {
|
||||
|
|
Loading…
Reference in a new issue