Reputation: 73
for tower in &mut game.towers {
tower.towers_attack(&mut game)
};
gives cannot borrow game as mutable more than once at a time [E0499]
My code was working however I was refactoring for it to make more sense.
What did work was (main point to note is it is fine with looping twice mutably over the game object, however this is because function has ownership of 'game'?)
impl Attack for Game {
fn towers_attack(&mut self) {
for tower in &mut self.towers {
tower.attacked = false;
if tower.hp.is_positive() {
for creep in &mut self.lane_creeps {
if tower.position.distance_between(creep.position) < 12.0 &&
creep.side != tower.side && !tower.attacked {
creep.hp -= tower.attack_damage as i32;
tower.attacked = true;
break;
}
}
}
}
}
}
game.towers_attack();
Moving the first loop to outside the function and implementing on tower
rather than game.tower
causes the issue.
I've confused myself a lot, I believe I just need to give ownership of game
to for tower in &mut game.towers { tower.towers_attack(&mut game) };
then return ownership when it exits, therefore no borrowing occurs if I explicitly give ownership, however I'm not sure if this is possible or makes sense.
The towers_attack
function is
impl TowerAttack for Tower {
fn towers_attack(&mut self, game: &mut Game) {
self.attacked = false;
if self.hp.is_positive() {
for creep in &mut game.lane_creeps {
if self.position.distance_between(creep.position) < 12.0 &&
creep.side != self.side && !self.attacked {
creep.hp -= self.attack_damage as i32;
self.attacked = true;
break;
}
}
}
}
}
Upvotes: 2
Views: 106
Reputation: 430721
for tower in &mut game.towers {
tower.towers_attack(&mut game)
}
Rust prevents this call because the implementation of towers_attack
might be:
fn towers_attack(game: &mut Game) {
game.towers.clear()
}
or maybe
fn towers_attack(game: &mut Game) {
game.towers.push(...)
}
which causes the vector to be reallocated and thus the iterator to be invalidated, which would cause Bad Things To Happen.
Instead, pass the subset of items you need to towers_attack
. For example:
fn towers_attack(lane_creeps: &mut Vec<Creeps>) { ... }
I just need to give ownership of game to
for tower in &mut game.towers { tower.towers_attack(&mut game) };
You always transfer ownership of the expression to the for
loop. In this case, you are passing ownership of a mutable reference to towers
.
then return ownership when it exits
There's no way to do that; for
loops do not return anything.
Upvotes: 4