rustborrow-checkerentity-component-system

Multiple mutable queries with Legion ECS


I am using the Legion ECS and trying to use multiple mutable queries and running into some borrow checker constraints.

I basically want to update the state of components by comparing with all of the other components.

In essence - make components blue if they are adjacent to another component.

let components = <&Component>::query()
  .iter(world)
  .collect();

<&Component>::query()
  .iter_mut(world)
  .for_each(|component| {
     // for each c in components 
     // make component blue if c is adjacent to this component
   })

Error with above is cannot borrow *ecs as mutable more than once at a time

    |
128 |             .iter(&ecs)
    |                   ---- immutable borrow occurs here
...
134 |             .iter_mut(&mut ecs)
    |                       ^^^^^^^^ mutable borrow occurs here
135 |             .for_each(|(_, fov)| {
136 |                 let fovs: HashSet<Point> = components
    |                                            --- immutable borrow later captured here by closure

Is there another way to do the above? I've thought that cloning the initial collection would decouple me from the World/ecs. But even with a clone, iterating through the component collection is an immutable borrow.


Solution

  • The issue is that your components vector is a vector containing references to Component, which borrows from world and means you can't mutably borrow it later when you go to edit the component.

    You can resolve this a couple of ways: