bevy icon indicating copy to clipboard operation
bevy copied to clipboard

get `unchecked_mut` variants to `by_id` methods

Open jakobhellermann opened this issue 1 year ago • 4 comments

Objective

The World stores its components and resources in UnsafeCells, which means that (with the necessary care) you can get a &mut T from a &World soundly. Having two &mut Worlds however is unsound.

To support use cases like bevy's systems where multiple callers share a &World but mutably access different parts of it, there are _unchecked versions of many functions:

  • EntityRef::get_unchecked_mut
  • World::get_resource_unchecked_mut
  • Query:.get_unchecked
  • ... (https://docs.rs/bevy_ecs/latest/bevy_ecs/?search=unchecked_mut)

I have a use case where I have two &Worlds where one may access resources and the other one may access components, and I would like to use untyped by_id methods there.

Solution

  • add World::get_resource_unchecked_mut_by_id
  • add EntityRef::get_unchecked_mut_by_id

both with safety comments like the by_id variant.

Changelog

  • add World::get_resource_unchecked_mut_by_id and EntityRef::get_unchecked_mut_by_id for manually synchronized mutable world access with untyped pointers

jakobhellermann avatar Sep 09 '22 09:09 jakobhellermann

We should be moving in the opposite direction here, removing EntityRef::get_unchecked_mut not adding a _by_id variant

BoxyUwU avatar Sep 09 '22 13:09 BoxyUwU

Isn't this pretty central to the design of the bevy world? The world contains UnsafeCells in the storages, so multiple systems can share a &World while carefully making sure that their access patterns are disjoint.

How would that work without &World -> &mut T methods?

jakobhellermann avatar Sep 09 '22 13:09 jakobhellermann

&World means shared access to components, we may use &World for interior mutability in places but this is a terrible idea as we also use &World to actually mean "shared access to all components".

BoxyUwU avatar Sep 09 '22 13:09 BoxyUwU

I opened #6404 implementing my thoughts in #5956 on how to split our usages of &World to mean "shared access to the world" and &World to mean "manually synchronized through a mechanism like systems, but can actually mutably use specific things".

I rebased this PR anyways in hopes that if #6404 does not get merged in time for 0.9, that we can merge this PR instead as a stop gap solution.

I agree that we should be moving into a direction where get_unchecked_mut does not exist, but until then I would much prefer

fn World::get_resource_unchecked_mut
fn World::get_resource_unchecked_mut_by_id
fn EntityRef::get_unchecked_mut
fn EntityRef::get_unchecked_mut_by_id

over

fn World::get_resource_unchecked_mut
fn EntityRef::get_unchecked_mut

which already exists but is incomplete and makes certain things unimplementable as third-party crate authors.

jakobhellermann avatar Oct 29 '22 15:10 jakobhellermann

Closing in favor of #6404, which resolves the same issues.

james7132 avatar Jan 27 '23 00:01 james7132