I have the following code:
pub fn run_systems(mut self) {
for mut agent in self.agents.iter_mut() {
for mut system_id in agent.systems.iter_mut() {
let system = self.systems.get(system_id).unwrap();
system.simulate(&mut agent, &mut self);
}
}
}
I get the following error on the system.simulate
line:
cannot borrow `agent` as mutable more than once at a time
second mutable borrow occurs here`. Apparently, iterating over the arrays is a borrowing operation.
I have also tried not using the iter
function and iterating directly on owned values (not sure what that does):
pub fn run_systems(mut self) {
for mut agent in self.agents {
for mut system_id in agent.systems {
let system = self.systems.get(&system_id).unwrap();
system.simulate(&mut agent, &mut self);
}
}
}
But as soon as I reference &system_id
, it detects an implicit borrowing in the for mut system_id in agent.systems {
line
borrow of partially moved value: `agent`
partial move occurs because `agent.systems` has type `Vec<String>`, which does not implement the `Copy` traitrustcE0382
lib.rs(72, 34): `agent.systems` partially moved due to this implicit call to `.into_iter()`
collect.rs(233, 18): this function takes ownership of the receiver `self`, which moves `agent.systems`
I have tried all sorts of ways to write this code but can't find a way that works. How can I iterate over those values while also being able to pass mutable references to their content to other functions?
Here's a playground of it:
use std::collections::HashMap;
struct World {
agents: Vec<Agent>,
systems: HashMap<String, Box<dyn System>>,
}
impl World {
pub fn new() -> World {
return World {
agents: Vec::new(),
systems: HashMap::new(),
};
}
pub fn run_systems(mut self) {
for mut agent in self.agents {
for system_id in agent.systems {
let system = self.systems.get(&system_id).unwrap();
system.simulate(&mut agent, &mut self);
}
}
}
/// Adds an agent to the world
pub fn add_agent(&mut self, agent: Agent) -> &Self {
self.agents.push(agent);
return self;
}
/// Adds a system to the available systems
pub fn add_system<S: System + 'static>(&mut self, system: S, id: String) -> &Self {
self.systems.insert(id, Box::new(system));
return self;
}
}
struct Agent {
systems: Vec<String>,
}
trait System {
fn simulate(&self, agent: &mut Agent, world: &mut World);
}
#[derive(Default)]
struct SomeSystem;
impl System for SomeSystem {
fn simulate(&self, agent: &mut Agent, world: &mut World) {
// Code here
}
}
fn main() {
let system_id = String::from("SOME_SYSTEM");
let world = World::new();
world.add_system(SomeSystem::default(), system_id);
let agent = Agent {
systems: vec![system_id],
};
world.add_agent(agent);
world.run_systems();
}
error[E0382]: borrow of partially moved value: `agent`
--> src/main.rs:18:33
|
16 | for system_id in agent.systems {
| -------------
| |
| `agent.systems` partially moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&agent.systems`
17 | let system = self.systems.get(&system_id).unwrap();
18 | system.simulate(&mut agent, &mut self);
| ^^^^^^^^^^ value borrowed here after partial move
|
note: this function takes ownership of the receiver `self`, which moves `agent.systems`
= note: partial move occurs because `agent.systems` has type `Vec<String>`, which does not implement the `Copy` trait
error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable
--> src/main.rs:18:45
|
17 | let system = self.systems.get(&system_id).unwrap();
| ------------ immutable borrow occurs here
18 | system.simulate(&mut agent, &mut self);
| -------- ^^^^^^^^^ mutable borrow occurs here
| |
| immutable borrow later used by call
error[E0382]: borrow of partially moved value: `self`
--> src/main.rs:18:45
|
15 | for mut agent in self.agents {
| -----------
| |
| `self.agents` partially moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&self.agents`
...
18 | system.simulate(&mut agent, &mut self);
| ^^^^^^^^^ value borrowed here after partial move
|
= note: partial move occurs because `self.agents` has type `Vec<Agent>`, which does not implement the `Copy` trait
error[E0596]: cannot borrow `world` as mutable, as it is not declared as mutable
--> src/main.rs:54:5
|
53 | let world = World::new();
| ----- help: consider changing this to be mutable: `mut world`
54 | world.add_system(SomeSystem::default(), system_id);
| ^^^^^ cannot borrow as mutable
error[E0382]: use of moved value: `system_id`
--> src/main.rs:56:23
|
52 | let system_id = String::from("SOME_SYSTEM");
| --------- move occurs because `system_id` has type `String`, which does not implement the `Copy` trait
53 | let world = World::new();
54 | world.add_system(SomeSystem::default(), system_id);
| --------- value moved here
55 | let agent = Agent {
56 | systems: vec![system_id],
| ^^^^^^^^^ value used here after move
error[E0596]: cannot borrow `world` as mutable, as it is not declared as mutable
--> src/main.rs:58:5
|
53 | let world = World::new();
| ----- help: consider changing this to be mutable: `mut world`
...
58 | world.add_agent(agent);
| ^^^^^ cannot borrow as mutable