bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Incorrect handling of EntityRef/Mut Queries + Resources resulting in false conflicts

Open iiYese opened this issue 10 months ago • 2 comments

Bevy version

0.13

What you did

Have a system with EntityRef & ResMut<T>.

What went wrong

System should not have any access conflicts but it does.

Additional information

Minimal example to reproduce:

use bevy::prelude::*;

#[derive(Resource)]
struct Foo;

fn sys(_: Query<EntityRef>, _: ResMut<Foo>) {}

fn main() {
    App::new()
        .insert_resource(Foo)
        .add_systems(Update, sys)
        .run();
}
thread 'main' panicked at /home/yogii/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/system/system_param.rs:542:13:
error[B0002]: ResMut<bevy_bug::Foo> in system bevy_bug::sys conflicts with a previous Res<bevy_bug::Foo> access. Consider removing the duplicate access.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

iiYese avatar Apr 29 '24 13:04 iiYese

#13120 would help prevent these kinds of bugs & surprises.

iiYese avatar Apr 29 '24 13:04 iiYese

Yeah, I don't think our access model is quite right. We have reads_all and writes_all, but that's inadequately granular: components and resources are distinct.

alice-i-cecile avatar Apr 29 '24 13:04 alice-i-cecile

Probably obvious, but I'd like to point out that the opposite EntityMut and Res will also return the same error.

use bevy::prelude::*;

#[derive(Resource)]
struct Foo;

fn sys(_: Query<EntityMut>, _: Res<Foo>) {}

fn main() {
    App::new()
        .insert_resource(Foo)
        .add_systems(Update, sys)
        .run();
}

Wiwip avatar May 27 '24 21:05 Wiwip

I've encountered this too, is there any progress here?

rendaoer avatar Jul 25 '24 09:07 rendaoer

World::resource_scope is a convenient work-around until the accesses for EntityRef/EntityMut are fixed. Though it does feel quite boilerplate-y:

fn sys(world: &mut World, state: &mut SystemState<Query<EntityRef>>) {
    world.resource_scope(|world, mut foo: Mut<Foo>| {
        let _query = state.get(world);
    });
}

thebluefish avatar Jul 25 '24 10:07 thebluefish

Just hit this as well, I have to switch to Res and queue my resource update with Commands

notmd avatar Jul 25 '24 18:07 notmd