# How to mutably loop over vector in a nested loop

I want to implement collision on each enemy between each other. I want the enemies to hit each other and statically resolve the collision which means moving both enemy pairs once collision is found - mutable references.

``````for i in 0..enemies_len {
let enemy = &mut self.enemies[i];
// Register enemy collision on player
if enemy.rect.collision_other(&self.player.rect) {
return Ok(crate::State::GameOver)
}
for j in 0..enemies_len {
let other_enemy = &self.enemies[j];
}

// Move enemies
enemy.rect.offset_x(-enemy.rect.facing.cos() * dt as f32 * enemy.speed);
enemy.rect.offset_y(-enemy.rect.facing.sin() * dt as f32 * enemy.speed);
}
``````

This leads to having both mutable and immutable borrows.

``````error[E0502]: cannot borrow `self.enemies` as immutable because it is also borrowed as mutable
--> src\GameStates\playing\mod.rs:167:24
|
160 |             let enemy = &mut self.enemies[i];
|                              ------------ mutable borrow occurs here
...
167 |                 let other_enemy = &self.enemies[j];
|                                    ^^^^^^^^^^^^ immutable borrow occurs here
...
171 |             enemy.rect.offset_x(-enemy.rect.facing.cos() * dt as f32 * enemy.speed);
|             ---------- mutable borrow later used here
``````

How can this be accomplished?

Not that easy to do directly, given the â€śgranularityâ€ť of Rust borrows; but you can use `split_at_mut` to circumvent it:

``````type ImplIteratorMut<'a, Item> =
::std::iter::Chain<
::std::slice::IterMut<'a, Item>,
::std::slice::IterMut<'a, Item>,
>
;
trait SplitOneMut {
type Item;

fn split_one_mut (
self: &'_ mut Self,
i: usize,
) -> (&'_ mut Self::Item, ImplIteratorMut<'_, Self::Item>);
}

impl<T> SplitOneMut for [T] {
type Item = T;

fn split_one_mut (
self: &'_ mut Self,
i: usize,
) -> (&'_ mut Self::Item, ImplIteratorMut<'_, Self::Item>)
{
let (prev, current_and_end) = self.split_at_mut(i);
let (current, end) = current_and_end.split_at_mut(1);
(
&mut current[0],
prev.iter_mut().chain(end),
)
}
}

#[derive(Debug)]
struct Enemy(usize);

fn main ()
{
let mut enemies: Vec<Enemy> = (0 .. 5).map(Enemy).collect();

for i in 0 .. enemies.len() {
let (enemy, other_enemies) = enemies.split_one_mut(i);
dbg!(enemy);
for other_enemy in other_enemies {
let _: &mut Enemy = other_enemy;
dbg!(other_enemy);
}
}
}
``````
2 Likes

`split_at_mut` is your friend, in general, for this kind of thing.

The other thing you can do is build a separate queue of changes to apply â€“ which is parallelizable and only needs shared reads â€“ and apply all the collision resolutions afterwards. Thatâ€™s how some of the MIR optimizations work in rustc, for example:

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.