-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Fix access checks for DeferredWorld as SystemParam. #17616
Fix access checks for DeferredWorld as SystemParam. #17616
Conversation
Are you sure this is the right fix? My understanding was that DeferredWorld was command-like, and apply_deferred should be applying it. |
This pr won't work as |
Sorry, I'm a little behind on understanding command queues. Are you worried that multiple systems will access the command queue concurrently and have UB from aliased I hadn't thought about flushing the queue at all! Would failing to flush be UB, or just horribly confusing? Would it work correctly if we restore fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
world.flush_commands();
} ? |
I'm a little worried that there might be UB there, but I suspect it should be fine, since you only have one
This would be better, but not quite right still. Consider if we have a |
It sounds like you're arguing that the existing If we wind up just removing it, then I should split off the |
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.
Realized I didn't really understand what DeferredWorld
is used for in systems, so did some research and found out it's because observers aren't allowed to use &mut World
. So this is the closest equivalent for those use cases and so we need to keep the impl around for that.
Fix FilteredAccessSet::read_all() and write_all() to correctly add a FilteredAccess with no filter so that Query is able to detect the conflicts.
Am I understanding correctly that this makes the following system error where it wouldn't before this pr?
fn my_system(_: Query<EntityRefExcept<T>>, _: &World, _:Query<&mut T>) {}
Could we add a test for that if that's the case?
Oh, I hadn't checked There is a test for |
Also, to clarify: Do you want me to make any changes to queue flushing in this PR? I removed the |
I think it's fine to keep the current behavior for now. It's not really meant to be used with scheduled systems. (you should just use exclusive systems.) So probably not the biggest deal that the behavior if you use it the is a little weird. It's probably more trouble than it's worth to fix it properly. |
# Objective Prevent unsound uses of `DeferredWorld` as a `SystemParam`. It is currently unsound because it does not check for existing access, and because it incorrectly registers filtered access. ## Solution Have `DeferredWorld` panic if a previous parameter has conflicting access. Have `DeferredWorld` update `archetype_component_access` so that the multi-threaded executor sees the access. Fix `FilteredAccessSet::read_all()` and `write_all()` to correctly add a `FilteredAccess` with no filter so that `Query` is able to detect the conflicts. Remove redundant `read_all()` call, since `write_all()` already declares read access. Remove unnecessary `set_has_deferred()` call, since `<DeferredWorld as SystemParam>::apply_deferred()` does nothing. Previously we were inserting unnecessary `apply_deferred` systems in the schedule. ## Testing Added unit tests for systems where `DeferredWorld` conflicts with a `Query` in the same system.
# Objective Prevent unsound uses of `DeferredWorld` as a `SystemParam`. It is currently unsound because it does not check for existing access, and because it incorrectly registers filtered access. ## Solution Have `DeferredWorld` panic if a previous parameter has conflicting access. Have `DeferredWorld` update `archetype_component_access` so that the multi-threaded executor sees the access. Fix `FilteredAccessSet::read_all()` and `write_all()` to correctly add a `FilteredAccess` with no filter so that `Query` is able to detect the conflicts. Remove redundant `read_all()` call, since `write_all()` already declares read access. Remove unnecessary `set_has_deferred()` call, since `<DeferredWorld as SystemParam>::apply_deferred()` does nothing. Previously we were inserting unnecessary `apply_deferred` systems in the schedule. ## Testing Added unit tests for systems where `DeferredWorld` conflicts with a `Query` in the same system.
Objective
Prevent unsound uses of
DeferredWorld
as aSystemParam
. It is currently unsound because it does not check for existing access, and because it incorrectly registers filtered access.Solution
Have
DeferredWorld
panic if a previous parameter has conflicting access.Have
DeferredWorld
updatearchetype_component_access
so that the multi-threaded executor sees the access.Fix
FilteredAccessSet::read_all()
andwrite_all()
to correctly add aFilteredAccess
with no filter so thatQuery
is able to detect the conflicts.Remove redundant
read_all()
call, sincewrite_all()
already declares read access.Remove unnecessary
set_has_deferred()
call, since<DeferredWorld as SystemParam>::apply_deferred()
does nothing. Previously we were inserting unnecessaryapply_deferred
systems in the schedule.Testing
Added unit tests for systems where
DeferredWorld
conflicts with aQuery
in the same system.