For-loop moves a mutable vector borrow


#1

Hi all,

I’m trying to understand the difference between these two ways of iterating over a mutably borrowed Vector of structs.

What I’m trying to accomplish:
I have an infinite loop, the first step of the loop iterates over all my Particle objects, and calls the tick() method on each one which modifies the Particle’s contents. I then do some math to figure out whether I’m done and break out of the infinite loop.

Question:
When I write the first part as for particle in particles { particle.tick(); } I get an error, saying that particles moved in the previous iteration of the loop, and cannot be used again. If I change it to iterate over particles.iter_mut() the error goes away.

I was under the impression that for x in some_vec {...} was just syntactic sugar for iterating over an iterator. Is my understanding correct, or am I missing something?

Code:

  // inside of Particle's impl block
  fn tick(&mut self) {
    let (p1,p2,p3) = self.p;
    let (v1,v2,v3) = self.v;
    let (a1,a2,a3) = self.a;
    self.v = (v1+a1,v2+a2,v3+a3);
    self.p = (p1+self.v.0, p2+self.v.1, p3+self.v.2)
  }

  // some function
fn nearest_particle_simulation(particles: &mut Vec<Particle>) -> usize {
  let mut nearest = particles[0].id;
  let mut nearest_streak = 0;
  let streak_req = 1000;

  loop {
    for particle in particles {
      particle.tick();
    }

    let this_nearest = nearest_to_origin(particles);

    // new nearest, reset the streak
    if nearest != this_nearest {
      nearest = this_nearest;
      nearest_streak = 0;
    }
    else {
      nearest_streak += 1;
    }

    // streak has completed. we're done
    if nearest_streak == streak_req {
      break;
    }
  }

  nearest
}


#2

This is a subtle difference between moving a mutable borrow (what’s happening in for particle in particles vs reborrowing, which is what’s happening in for particle in particles.iter_mut()). There was some recent discussion of this and @bluss gave a nice summary: What’s the difference between ‘for x in b’ and ‘for x in b.into_iter()’?.