-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
use UnsafeWorldCell internally
#6972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use UnsafeWorldCell internally
#6972
Conversation
|
@jakobhellermann can you rebase this? I'd like to prioritize this for review and merging due to its impact on ECS internals clarity. |
5ce7cbe to
7cc5b86
Compare
7cc5b86 to
ebc7198
Compare
8abb3cf to
93dbca5
Compare
InteriorMutableWorld internallyUnsafeWorldCell internally
93dbca5 to
f7606e9
Compare
|
I'm unsure if we can get this reviewed and merged appropriately without stopping the train. Impact is mostly internal, so I've bumped it from the 0.10 milestone. |
| } | ||
| } | ||
|
|
||
| fn update_archetypes_unsafe_world_cell(&mut self, world: UnsafeWorldCell<'_>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| fn update_archetypes_unsafe_world_cell(&mut self, world: UnsafeWorldCell<'_>) { | |
| pub fn update_archetypes_unsafe_world_cell(&mut self, world: UnsafeWorldCell<'_>) { |
and also implement update_archetypes in terms of this method rather than the way it is now perhaps
| self.validate_world_unsafe_world_cell(world.as_unsafe_world_cell_readonly()) | ||
| } | ||
| #[inline] | ||
| pub fn validate_world_unsafe_world_cell(&self, world: UnsafeWorldCell<'_>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| pub fn validate_world_unsafe_world_cell(&self, world: UnsafeWorldCell<'_>) { | |
| pub fn validate_unsafe_world_cell(&self, world: UnsafeWorldCell<'_>) { |
| break; | ||
| } | ||
|
|
||
| // TODO: do this earlier? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you want to replace the cell: &'scope SyncUnsafeCell<World> with cell: UnsafeWorldCell<'scope> I believe.
| .sparse_sets | ||
| .get(component_id) | ||
| .debug_checked_unwrap() | ||
| // SAFETY: TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be a non-TODO comment.
| .sparse_sets | ||
| .get(component_id) | ||
| .debug_checked_unwrap() | ||
| // SAFETY: world has access to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This placeholder needs to be fully written.
| #[inline] | ||
| pub fn validate_world(&self, world: &World) { | ||
| self.validate_world_unsafe_world_cell(world.as_unsafe_world_cell_readonly()) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } | |
| } | |
| self.validate_world_unsafe_world_cell(world.as_unsafe_world_cell_readonly()) | ||
| } | ||
| #[inline] | ||
| pub fn validate_world_unsafe_world_cell(&self, world: UnsafeWorldCell<'_>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is to be public, please document what this function does. Alternatively, we could just have validate_world take a WorldId instead, which should be accessible from both.
|
Closing in favor of #8833. |
# Objective Follow-up to #6404 and #8292. Mutating the world through a shared reference is surprising, and it makes the meaning of `&World` unclear: sometimes it gives read-only access to the entire world, and sometimes it gives interior mutable access to only part of it. This is an up-to-date version of #6972. ## Solution Use `UnsafeWorldCell` for all interior mutability. Now, `&World` *always* gives you read-only access to the entire world. --- ## Changelog TODO - do we still care about changelogs? ## Migration Guide Mutating any world data using `&World` is now considered unsound -- the type `UnsafeWorldCell` must be used to achieve interior mutability. The following methods now accept `UnsafeWorldCell` instead of `&World`: - `QueryState`: `get_unchecked`, `iter_unchecked`, `iter_combinations_unchecked`, `for_each_unchecked`, `get_single_unchecked`, `get_single_unchecked_manual`. - `SystemState`: `get_unchecked_manual` ```rust let mut world = World::new(); let mut query = world.query::<&mut T>(); // Before: let t1 = query.get_unchecked(&world, entity_1); let t2 = query.get_unchecked(&world, entity_2); // After: let world_cell = world.as_unsafe_world_cell(); let t1 = query.get_unchecked(world_cell, entity_1); let t2 = query.get_unchecked(world_cell, entity_2); ``` The methods `QueryState::validate_world` and `SystemState::matches_world` now take a `WorldId` instead of `&World`: ```rust // Before: query_state.validate_world(&world); // After: query_state.validate_world(world.id()); ``` The methods `QueryState::update_archetypes` and `SystemState::update_archetypes` now take `UnsafeWorldCell` instead of `&World`: ```rust // Before: query_state.update_archetypes(&world); // After: query_state.update_archetypes(world.as_unsafe_world_cell_readonly()); ```
builds on #6404 (and #6402)
important commits:
SystemandParamStateQueryState/QueryObjective
UnsafeWorldCellabstraction #6404 and the issue Abstraction for working with a&Worldand interior mutability #5956, but the TLDR is:&Worldis sometimes used internally to mean "world that is shared with others but the access is distinct"get_resourcethat is unsound because the&Worlddoesn't actually give accessSolution
UnsafeWorldCellwhenever we use&Worldas shared mutableSystemmachinery and forQuery/WorldQueryChangelog
bevy now uses the
UnsafeWorldCelltype in places where we previously used&Worldto mean "shared mutable access, but ensured to be distinct by systems".This means that systems and queries now get a
UnsafeWorldCellwhere every method is unsafe, so you need to reason correctly about every access.Usually this is done like