-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
constrain WorldQuery::get_state to only use &Components #13343
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
constrain WorldQuery::get_state to only use &Components #13343
Conversation
|
Welcome, new contributor! Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨ |
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.
In terms of trait design, I don't think this is appropriate, given that init_state, the infallible version of get_state requires a &mut World, there may be WorldQuery implementations that may read other state in the world (i.e. resources, other metadata, etc).
If we were to seal WorldQuery so that it cannot be externally implemented, this change may make more sense, and it does seem like something that @maniwani was looking into for ABI compatibility. However, without those changes, I don't think this is a limitation we should be imposing without also limiting the scope of init_state.
|
That is true, I added this change in the second commit. |
|
I realized that because |
|
Since the |
f4a2b5a to
0637ee4
Compare
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.
I agree with this as an immediately actionable step to address UB. The restriction on get_state fundamentally makes sense to me: queries should generally not be accessing non-component data. I can see a world where additional data (like indexes) are requested, but I would rather lock this down now and then add more careful access.
init_state should be changed to match, but that doesn't have to happen right now, and frankly probably shouldn't, given that it will require more careful design thought.
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.
OK, deferring to a later PR SGTM, so long as both make it into 0.14.
…3442) # Objective In #13343, `WorldQuery::get_state` was constrained from `&World` as the argument to `&Components`, but `WorldQuery::init_state` hasn't yet been changed from `&mut World` to match. Fixes #13358 ## Solution Create a wrapper around `&mut Components` and `&mut Storages` that can be obtained from `&mut World` with a `component_initializer` method. This new `ComponentInitializer` re-exposes the API on `&mut Components` minus the `&mut Storages` parameter where it was present. For the `&Components` API, it simply derefs to its `components` field. ## Changelog ### Added The `World::component_initializer` method. The `ComponentInitializer` struct that re-exposes `Components` API. ### Changed `WorldQuery::init_state` now takes `&mut ComponentInitializer` instead of `&mut World`. ## Migration Guide Instead of passing `&mut World` to `WorldQuery::init_state` directly, pass in a mutable reference to the struct returned from `World::component_initializer`.
# Objective Implement a new `AssetChanged` query filter that allows users to query for entities whose related assets may have changed. - Closes #5069 - Unblocks #16420. Currently, `cold-specialization`, a key rendering optimization for unlocking ancillary benefits of the retained render world, is blocked on being unable detect all scenarios in which an entity's mesh/material changes using events and observers. An `AssetChanged` filter will drastically simplify our implementation and be more robust to future changes. Originally implemented by @nicopap in #5080. ## Solution - Adds a new `AssetChanged` query filter that initializes a `AssetChanges<A>` resource that tracks changed assets and ticks in `asset_events`. - ~Reverts #13343 and changes the api of `get_state` to accept `impl Into<UnsafeWorldCell<'w>>` to allow accessing the `AssetChanges<A>` resource.~ - Adds a `AsAssetId` trait used for newtype handle wrappers (e.g. `Mesh3d`) that allows associating a component with the underlying `Asset` it represents. ## Testing - Tests are added for `AssetChanged`. - TBD on performance. We are going to add this `Mesh3d` and `MeshMaterial3d` (etc) in the renderer. Long term wins in render performance this unblocks should swamp tracking overhead for any realistic workload. ## Migration Guide - The `asset_events` system is no longer public. Users should order their systems relative to the `AssetEvents` system set. --------- Co-authored-by: Nicola Papale <[email protected]> Co-authored-by: Patrick Walton <[email protected]> Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: Chris Russell <[email protected]>
# Objective Implement a new `AssetChanged` query filter that allows users to query for entities whose related assets may have changed. - Closes bevyengine#5069 - Unblocks bevyengine#16420. Currently, `cold-specialization`, a key rendering optimization for unlocking ancillary benefits of the retained render world, is blocked on being unable detect all scenarios in which an entity's mesh/material changes using events and observers. An `AssetChanged` filter will drastically simplify our implementation and be more robust to future changes. Originally implemented by @nicopap in bevyengine#5080. ## Solution - Adds a new `AssetChanged` query filter that initializes a `AssetChanges<A>` resource that tracks changed assets and ticks in `asset_events`. - ~Reverts bevyengine#13343 and changes the api of `get_state` to accept `impl Into<UnsafeWorldCell<'w>>` to allow accessing the `AssetChanges<A>` resource.~ - Adds a `AsAssetId` trait used for newtype handle wrappers (e.g. `Mesh3d`) that allows associating a component with the underlying `Asset` it represents. ## Testing - Tests are added for `AssetChanged`. - TBD on performance. We are going to add this `Mesh3d` and `MeshMaterial3d` (etc) in the renderer. Long term wins in render performance this unblocks should swamp tracking overhead for any realistic workload. ## Migration Guide - The `asset_events` system is no longer public. Users should order their systems relative to the `AssetEvents` system set. --------- Co-authored-by: Nicola Papale <[email protected]> Co-authored-by: Patrick Walton <[email protected]> Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: Chris Russell <[email protected]>
# Objective Implement a new `AssetChanged` query filter that allows users to query for entities whose related assets may have changed. - Closes bevyengine#5069 - Unblocks bevyengine#16420. Currently, `cold-specialization`, a key rendering optimization for unlocking ancillary benefits of the retained render world, is blocked on being unable detect all scenarios in which an entity's mesh/material changes using events and observers. An `AssetChanged` filter will drastically simplify our implementation and be more robust to future changes. Originally implemented by @nicopap in bevyengine#5080. ## Solution - Adds a new `AssetChanged` query filter that initializes a `AssetChanges<A>` resource that tracks changed assets and ticks in `asset_events`. - ~Reverts bevyengine#13343 and changes the api of `get_state` to accept `impl Into<UnsafeWorldCell<'w>>` to allow accessing the `AssetChanges<A>` resource.~ - Adds a `AsAssetId` trait used for newtype handle wrappers (e.g. `Mesh3d`) that allows associating a component with the underlying `Asset` it represents. ## Testing - Tests are added for `AssetChanged`. - TBD on performance. We are going to add this `Mesh3d` and `MeshMaterial3d` (etc) in the renderer. Long term wins in render performance this unblocks should swamp tracking overhead for any realistic workload. ## Migration Guide - The `asset_events` system is no longer public. Users should order their systems relative to the `AssetEvents` system set. --------- Co-authored-by: Nicola Papale <[email protected]> Co-authored-by: Patrick Walton <[email protected]> Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: Chris Russell <[email protected]>
Objective
Passing
&Worldin theWorldQuery::get_statemethod is unnecessary, as all implementations of this method in the engine either only accessComponentsin&World, or do nothing with it.It can introduce UB by necessitating the creation of a
&Worldfrom aUnsafeWorldCell.This currently happens in
Query::transmute_lens, which obtains a&Worldfrom the internalUnsafeWorldCellsolely to pass toget_state.Query::joinsuffers from the same issue.Other cases of UB come from allowing implementors of
WorldQueryto freely access&World, like in thebevy-trait-querycrate, where a reference to a resource is obtained inside ofget_state, potentially aliasing with aResMutparameter in the same system.WorldQuery::init_statecurrently requires&mut World, which doesn't suffer from these issues.But that too can be changed to receive a wrapper around
&mut Componentsand&mut Storagesfor consistency in a follow-up PR.Solution
Replace the
&Worldparameter inget_statewith&Components.Changelog
WorldQuery::get_statenow takes&Componentsinstead of&World.The
transmute,transmute_filtered,joinandjoin_filteredmethods onQueryStatenow similarly take&Componentsinstead of&World.Migration Guide
Users of
WorldQuery::get_stateortransmute,transmute_filtered,joinandjoin_filteredmethods onQueryStatenow need to pass&Componentsinstead of&World.&Componentscan be trivially obtained from eithercomponentsmethod on&WorldorUnsafeWorldCell.For implementors of
WorldQuery::get_statethat were accessing more than theComponentsinside&Worldand its methods, this is no longer allowed.