Skip to content

Disallow requesting write resource access in Queries #17116

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

Merged
merged 6 commits into from
Jan 6, 2025

Conversation

vil-mo
Copy link
Contributor

@vil-mo vil-mo commented Jan 3, 2025

Related to #16843

Since WorldQuery::Fetch is Clone, it can't store mutable references to resources, so it doesn't make sense to mutably access resources. In that sense, it is hard to find usecases of mutably accessing resources and to clearly define, what mutably accessing resources would mean, so it's been decided to disallow write resource access.
Also changed documentation of safety requirements of WorldQuery::init_fetch and WorldQuery::fetch to clearly state to the caller, what safety invariants they need to uphold.

@@ -60,11 +60,14 @@ pub unsafe trait WorldQuery {
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort>;

/// Creates a new instance of this fetch.
/// Readonly accesses resourses registered in [`update_component_access`].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Readonly accesses resourses registered in [`update_component_access`].
/// Readonly accesses resources registered in [`update_component_access`].

@IQuick143 IQuick143 added A-ECS Entities, components, systems, and events S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jan 4, 2025
Copy link
Contributor

@chescock chescock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think this is the right move. I only added the code for mutable resources because it looked simple and not because we had a real use case, and it's clear that I was wrong about it being simple.

We should also remove the has_resource_write() check in AssetChanged. It's the only first-party use of resource access in queries, so users might use it as an example, and leaving that check there might trick them into thinking that mutable resource access is supported.

@@ -199,14 +199,6 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
}
}

if state.component_access.access().has_write_all_resources() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth adding a check like

debug_assert!(!state.component_access.access().has_any_resource_write());

so that anyone who tries it gets an error.

@vil-mo
Copy link
Contributor Author

vil-mo commented Jan 5, 2025

We should also remove the has_resource_write() check in AssetChanged. It's the only first-party use of resource access in queries, so users might use it as an example, and leaving that check there might trick them into thinking that mutable resource access is supported.

It should not be removed, because user could request write access to the resource in the SystemParam prior to the query

@chescock
Copy link
Contributor

chescock commented Jan 5, 2025

It should not be removed, because user could request write access to the resource in the SystemParam prior to the query

I believe that's checked in <Query as SystemParam>::init_state() after the whole query is built. The check in <AssetChanged as WorldQuery>::update_component_access() only has the FilteredAccess from the current query, not the FilteredAccessSet that includes other system params' access.

@vil-mo
Copy link
Contributor Author

vil-mo commented Jan 5, 2025

I believe that's checked in <Query as SystemParam>::init_state() after the whole query is built

It's not checked there

fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
    let state = QueryState::new_with_access(world, &mut system_meta.archetype_component_access);
    init_query_param(world, system_meta, &state);
    state
}

@chescock
Copy link
Contributor

chescock commented Jan 5, 2025

The check is in init_query_param. It's in a method so it can be shared by QueryParamBuilder.

@chescock chescock added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jan 6, 2025
@alice-i-cecile alice-i-cecile added C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Unsafe Touches with unsafe code in some way labels Jan 6, 2025
@alice-i-cecile
Copy link
Member

Note that write access to resources during queries may be useful for certain index updating strategies. That said, it doesn't seem to actually work, so we should clean this up for now and re-add it later when we have clearer requirements.

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Jan 6, 2025
Merged via the queue into bevyengine:main with commit b30ee2d Jan 6, 2025
31 checks passed
mrchantey pushed a commit to mrchantey/bevy that referenced this pull request Feb 4, 2025
Related to bevyengine#16843

Since `WorldQuery::Fetch` is `Clone`, it can't store mutable references
to resources, so it doesn't make sense to mutably access resources. In
that sense, it is hard to find usecases of mutably accessing resources
and to clearly define, what mutably accessing resources would mean, so
it's been decided to disallow write resource access.
Also changed documentation of safety requirements of
`WorldQuery::init_fetch` and `WorldQuery::fetch` to clearly state to the
caller, what safety invariants they need to uphold.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Unsafe Touches with unsafe code in some way S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants