Skip to content
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

Cannot access additional components while iterating query #135

Closed
smokku opened this issue Apr 26, 2020 · 7 comments
Closed

Cannot access additional components while iterating query #135

smokku opened this issue Apr 26, 2020 · 7 comments

Comments

@smokku
Copy link

smokku commented Apr 26, 2020

Before 3ee0bb9 change the following code (edited for brevity) used to work:

    SystemBuilder::new("monster_ai")
        .with_query(<(Write<Viewshed>, Write<Position>)>::query().filter(tag::<Monster>()))
        .write_component::<Confusion>()
        .build(
            |command_buffer, world, _, query| {
                for (entity, (mut viewshed, mut pos)) in query.iter_entities_mut(world) {
                    let mut can_act = true;

                    if let Some(mut confused) = world.get_component_mut::<Confusion>(entity) {
                        confused.turns -= 1;
                        can_act = false;
                    }

                    if can_act {

After 3ee0bb9 it fails to compile:

error[E0499]: cannot borrow `*world` as mutable more than once at a time
  --> src/monster_ai_system.rs:28:49
   |
25 |                 for (entity, (mut viewshed, mut pos)) in query.iter_entities_mut(world) {
   |                                                          ------------------------------
   |                                                          |                       |
   |                                                          |                       first mutable borrow occurs here
   |                                                          first borrow later used here
...
28 |                     if let Some(mut confused) = world.get_component_mut::<Confusion>(entity) {
   |                                                 ^^^^^ second mutable borrow occurs here

Is this access pattern not supported by Legion?

If so, what is the designed use of read/write_component() function?
Any tips on changing my code?

@TomGillen
Copy link
Collaborator

TomGillen commented Apr 28, 2020

If you know for certain that your loop will never access the same component as your get_component_mut call (which in this case you do as the two are accessing different component types), then you can use Query::iter_entities_unchecked(&world) and SubWorld::get_component_mut_unchecked(&self, entity). These are unsafe functions. You will get some debug-only runtime checks as an attempt to catch mistakes here, but ultimately you will be responsible for ensuring that the code does not produce any mutable aliases. You only need to worry about aliasing within the system, as the scheduler will ensure safety between systems.

@smokku
Copy link
Author

smokku commented Apr 28, 2020

OK. Got it. :-)

Thanks.

@smokku smokku closed this as completed Apr 28, 2020
@smokku
Copy link
Author

smokku commented Apr 29, 2020

What about tags? There is no .get_tag_unchecked.

@smokku smokku reopened this Apr 29, 2020
@TomGillen
Copy link
Collaborator

There is no need for a get_tag_unchecked. Tags are read-only, so the signature would be identical.

@smokku
Copy link
Author

smokku commented Apr 30, 2020

The problem stays. I cannot have a second, immutable borrow, while already having world borrowed mutably by Query Iterator.

@TomGillen
Copy link
Collaborator

You need to use _unchecked for both the outer loop and the inner get_component.

@smokku
Copy link
Author

smokku commented May 1, 2020

Oh sorry. It works indeed if I use .get_component (not mut) and .get_tag inside .iter_entities_unchecked.

I don't know why it didn't compile previously, as I cannot reproduce it now.
baka me

@smokku smokku closed this as completed May 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants