Struct valence::ecs::world::unsafe_world_cell::UnsafeWorldCell

pub struct UnsafeWorldCell<'w>(/* private fields */);
Expand description

Variant of the World where resource and component accesses take &self, and the responsibility to avoid aliasing violations are given to the caller instead of being checked at compile-time by rust’s unique XOR shared rule.

§Rationale

In rust, having a &mut World means that there are absolutely no other references to the safe world alive at the same time, without exceptions. Not even unsafe code can change this.

But there are situations where careful shared mutable access through a type is possible and safe. For this, rust provides the UnsafeCell escape hatch, which allows you to get a *mut T from a &UnsafeCell<T> and around which safe abstractions can be built.

Access to resources and components can be done uniquely using World::resource_mut and World::entity_mut, and shared using World::resource and World::entity. These methods use lifetimes to check at compile time that no aliasing rules are being broken.

This alone is not enough to implement bevy systems where multiple systems can access disjoint parts of the world concurrently. For this, bevy stores all values of resources and components (and ComponentTicks) in UnsafeCells, and carefully validates disjoint access patterns using APIs like System::component_access.

A system then can be executed using System::run_unsafe with a &World and use methods with interior mutability to access resource values.

§Example Usage

UnsafeWorldCell can be used as a building block for writing APIs that safely allow disjoint access into the world. In the following example, the world is split into a resource access half and a component access half, where each one can safely hand out mutable references.

use bevy_ecs::world::World;
use bevy_ecs::change_detection::Mut;
use bevy_ecs::system::Resource;
use bevy_ecs::world::unsafe_world_cell::UnsafeWorldCell;

// INVARIANT: existence of this struct means that users of it are the only ones being able to access resources in the world
struct OnlyResourceAccessWorld<'w>(UnsafeWorldCell<'w>);
// INVARIANT: existence of this struct means that users of it are the only ones being able to access components in the world
struct OnlyComponentAccessWorld<'w>(UnsafeWorldCell<'w>);

impl<'w> OnlyResourceAccessWorld<'w> {
    fn get_resource_mut<T: Resource>(&mut self) -> Option<Mut<'_, T>> {
        // SAFETY: resource access is allowed through this UnsafeWorldCell
        unsafe { self.0.get_resource_mut::<T>() }
    }
}
// impl<'w> OnlyComponentAccessWorld<'w> {
//     ...
// }

// the two `UnsafeWorldCell`s borrow from the `&mut World`, so it cannot be accessed while they are live
fn split_world_access(world: &mut World) -> (OnlyResourceAccessWorld<'_>, OnlyComponentAccessWorld<'_>) {
    let unsafe_world_cell = world.as_unsafe_world_cell();
    let resource_access = OnlyResourceAccessWorld(unsafe_world_cell);
    let component_access = OnlyComponentAccessWorld(unsafe_world_cell);
    (resource_access, component_access)
}

Implementations§

§

impl<'w> UnsafeWorldCell<'w>

pub unsafe fn into_deferred(self) -> DeferredWorld<'w>

Turn self into a DeferredWorld

§Safety

Caller must ensure there are no outstanding mutable references to world and no outstanding references to the world’s command queue, resource or component data

§

impl<'w> UnsafeWorldCell<'w>

pub unsafe fn world_mut(self) -> &'w mut World

Gets a mutable reference to the World this UnsafeWorldCell belongs to. This is an incredibly error-prone operation and is only valid in a small number of circumstances.

§Safety
  • self must have been obtained from a call to World::as_unsafe_world_cell (not as_unsafe_world_cell_readonly or any other method of construction that does not provide mutable access to the entire world).
    • This means that if you have an UnsafeWorldCell that you didn’t create yourself, it is likely unsound to call this method.
  • The returned &mut World must be unique: it must never be allowed to exist at the same time as any other borrows of the world or any accesses to its data. This includes safe ways of accessing world data, such as UnsafeWorldCell::archetypes.
    • Note that the &mut World may exist at the same time as instances of UnsafeWorldCell, so long as none of those instances are used to access world data in any way while the mutable borrow is active.
// Make an UnsafeWorldCell.
let world_cell = world.as_unsafe_world_cell();

// SAFETY: `world_cell` was originally created from `&mut World`.
// We must be sure not to access any world data while `world_mut` is active.
let world_mut = unsafe { world_cell.world_mut() };

// We can still use `world_cell` so long as we don't access the world with it.
store_but_dont_use(world_cell);

// !!This is unsound!! Even though this method is safe, we cannot call it until
// `world_mut` is no longer active.
let tick = world_cell.change_tick();

// Use mutable access to spawn an entity.
world_mut.spawn(Player);

// Since we never use `world_mut` after this, the borrow is released
// and we are once again allowed to access the world using `world_cell`.
let archetypes = world_cell.archetypes();

pub unsafe fn world(self) -> &'w World

Gets a reference to the &World this UnsafeWorldCell belongs to. This can be used for arbitrary shared/readonly access.

§Safety
  • must have permission to access the whole world immutably
  • there must be no live exclusive borrows on world data
  • there must be no live exclusive borrow of world

pub unsafe fn world_metadata(self) -> &'w World

Gets a reference to the World this UnsafeWorldCell belong to. This can be used for arbitrary read only access of world metadata

You should attempt to use various safe methods on UnsafeWorldCell for metadata access before using this method.

§Safety
  • must only be used to access world metadata

pub fn id(self) -> WorldId

Retrieves this world’s unique ID.

pub fn entities(self) -> &'w Entities

Retrieves this world’s Entities collection.

pub fn archetypes(self) -> &'w Archetypes

Retrieves this world’s Archetypes collection.

pub fn components(self) -> &'w Components

Retrieves this world’s Components collection.

pub fn removed_components(self) -> &'w RemovedComponentEvents

Retrieves this world’s collection of removed components.

pub fn bundles(self) -> &'w Bundles

Retrieves this world’s Bundles collection.

pub fn change_tick(self) -> Tick

Gets the current change tick of this world.

pub fn last_change_tick(self) -> Tick

Returns the Tick indicating the last time that World::clear_trackers was called.

If this UnsafeWorldCell was created from inside of an exclusive system (a System that takes &mut World as its first parameter), this will instead return the Tick indicating the last time the system was run.

See World::last_change_tick().

pub fn increment_change_tick(self) -> Tick

Increments the world’s current change tick and returns the old value.

pub unsafe fn storages(self) -> &'w Storages

Provides unchecked access to the internal data stores of the World.

§Safety

The caller must ensure that this is only used to access world data that this UnsafeWorldCell is allowed to. As always, any mutable access to a component must not exist at the same time as any other accesses to that same component.

pub fn get_entity(self, entity: Entity) -> Option<UnsafeEntityCell<'w>>

Retrieves an UnsafeEntityCell that exposes read and write operations for the given entity. Similar to the UnsafeWorldCell, you are in charge of making sure that no aliasing rules are violated.

pub unsafe fn get_resource<R>(self) -> Option<&'w R>
where R: Resource,

Gets a reference to the resource of the given type if it exists

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource
  • no mutable reference to the resource exists at the same time

pub unsafe fn get_resource_ref<R>(self) -> Option<Res<'w, R>>
where R: Resource,

Gets a reference including change detection to the resource of the given type if it exists.

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource
  • no mutable reference to the resource exists at the same time

pub unsafe fn get_resource_by_id( self, component_id: ComponentId, ) -> Option<Ptr<'w>>

Gets a pointer to the resource with the id ComponentId if it exists. The returned pointer must not be used to modify the resource, and must not be dereferenced after the borrow of the World ends.

You should prefer to use the typed API UnsafeWorldCell::get_resource where possible and only use this in cases where the actual types are not known at compile time.

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource
  • no mutable reference to the resource exists at the same time

pub unsafe fn get_non_send_resource<R>(self) -> Option<&'w R>
where R: 'static,

Gets a reference to the non-send resource of the given type if it exists

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource
  • no mutable reference to the resource exists at the same time

pub unsafe fn get_non_send_resource_by_id( self, component_id: ComponentId, ) -> Option<Ptr<'w>>

Gets a !Send resource to the resource with the id ComponentId if it exists. The returned pointer must not be used to modify the resource, and must not be dereferenced after the immutable borrow of the World ends.

You should prefer to use the typed API UnsafeWorldCell::get_non_send_resource where possible and only use this in cases where the actual types are not known at compile time.

§Panics

This function will panic if it isn’t called from the same thread that the resource was inserted from.

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource
  • no mutable reference to the resource exists at the same time

pub unsafe fn get_resource_mut<R>(self) -> Option<Mut<'w, R>>
where R: Resource,

Gets a mutable reference to the resource of the given type if it exists

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource mutably
  • no other references to the resource exist at the same time

pub unsafe fn get_resource_mut_by_id( self, component_id: ComponentId, ) -> Option<MutUntyped<'w>>

Gets a pointer to the resource with the id ComponentId if it exists. The returned pointer may be used to modify the resource, as long as the mutable borrow of the UnsafeWorldCell is still valid.

You should prefer to use the typed API UnsafeWorldCell::get_resource_mut where possible and only use this in cases where the actual types are not known at compile time.

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource mutably
  • no other references to the resource exist at the same time

pub unsafe fn get_non_send_resource_mut<R>(self) -> Option<Mut<'w, R>>
where R: 'static,

Gets a mutable reference to the non-send resource of the given type if it exists

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource mutably
  • no other references to the resource exist at the same time

pub unsafe fn get_non_send_resource_mut_by_id( self, component_id: ComponentId, ) -> Option<MutUntyped<'w>>

Gets a !Send resource to the resource with the id ComponentId if it exists. The returned pointer may be used to modify the resource, as long as the mutable borrow of the World is still valid.

You should prefer to use the typed API UnsafeWorldCell::get_non_send_resource_mut where possible and only use this in cases where the actual types are not known at compile time.

§Panics

This function will panic if it isn’t called from the same thread that the resource was inserted from.

§Safety

It is the callers responsibility to ensure that

  • the UnsafeWorldCell has permission to access the resource mutably
  • no other references to the resource exist at the same time

Trait Implementations§

§

impl<'w> Clone for UnsafeWorldCell<'w>

§

fn clone(&self) -> UnsafeWorldCell<'w>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for UnsafeWorldCell<'_>

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl<'w> Copy for UnsafeWorldCell<'w>

§

impl Send for UnsafeWorldCell<'_>

§

impl Sync for UnsafeWorldCell<'_>

Auto Trait Implementations§

§

impl<'w> Freeze for UnsafeWorldCell<'w>

§

impl<'w> !RefUnwindSafe for UnsafeWorldCell<'w>

§

impl<'w> Unpin for UnsafeWorldCell<'w>

§

impl<'w> !UnwindSafe for UnsafeWorldCell<'w>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T> Conv for T

§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
§

impl<T> FmtForward for T

§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pipe for T
where T: ?Sized,

§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
§

impl<T> Tap for T

§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
source§

impl<T> ToOwned for T
where T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> TryConv for T

§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

§

fn clone_type_data(&self) -> Box<dyn TypeData>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ConditionalSend for T
where T: Send,