pub struct UnsafeWorldCell<'w>(_, _);
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. 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<'w, 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 world_mut(self) -> &'w mut World

This &mut World counts as a mutable borrow of every resource and component for the purposes of safety invariants that talk about borrows on component/resource data not existing. This is true even for methods that do not explicitly call out &mut World as problematic.

Safety
  • must have permission to access everything mutably
  • there must be no other borrows on world
  • returned borrow must not be used in any way if the world is accessed through other means than the &mut World after this call.

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 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 bundles(self) -> &'w Bundles

Retrieves this world’s Bundles collection

pub fn read_change_tick(self) -> u32

Reads the current change tick of this world.

pub fn last_change_tick(self) -> u32

pub fn increment_change_tick(self) -> u32

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_by_id( self, component_id: ComponentId ) -> Option<Ptr<'w, Aligned>>

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, Aligned>>

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<'w> Copy for UnsafeWorldCell<'w>

§

impl Send for UnsafeWorldCell<'_>

§

impl Sync for UnsafeWorldCell<'_>

Auto Trait Implementations§

§

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 Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T, U> AsBindGroupShaderType<U> for Twhere U: ShaderType, &'a T: for<'a> Into<U>,

§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
source§

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

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

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

const: unstable · source§

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

Mutably borrows from an owned value. Read more
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<T> Downcast for Twhere T: Any,

§

fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>

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 + 'static>

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 Twhere T: Any + Send + Sync,

§

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

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

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

source§

impl<T> Instrument for T

source§

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

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

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 Twhere U: From<T>,

const: unstable · 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.

source§

impl<T> ToOwned for Twhere T: Clone,

§

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, U> ToSample<U> for Twhere U: FromSample<T>,

§

fn to_sample_(self) -> U

source§

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

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

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

Performs the conversion.
source§

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

§

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

The type returned in the event of a conversion error.
const: unstable · source§

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

Performs the conversion.
§

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

§

fn clone_type_data(&self) -> Box<dyn TypeData + 'static, Global>

§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

source§

impl<T> WithSubscriber for T

source§

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
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

impl<S, T> Duplex<S> for Twhere T: FromSample<S> + ToSample<S>,

§

impl<T> Event for Twhere T: Send + Sync + 'static,