Search code examples
rustiteratorborrow-checker

Borrow of moved value error, but the value shouldn't have moved, because it's borrowed


I'm trying to make sense of the error that comes up, it says that I can't borrow a moved value, but the value is the borrowed value nurse_list: &mut Vec<Nurse>. So when I use it in the code for nurse in nurse_list { ... } it shouldn't move there, it should be borrowed.

fn assign_nurses_to_schedule(
    nurse_list: &mut Vec<Nurse>,
    fte_budget: &Vec<NursesNeeded>,
    cyclical_rosters: &Vec<Roster>,
    total_incumbent_score: &mut i32,
) -> Vec<Assignment> {
    let mut assignments: Vec<Assignment> = vec![];
    let mut incumbent_score = 1000;
    //let mut total_incumbent_score = 0;
    let mut new_score: i32;
    for schedule in cyclical_rosters {
        let mut taken_nurse: Option<i32> = None;
        for nurse in nurse_list {
            new_score = calculate_score(&schedule, nurse.get_pref_score().to_vec());
            if incumbent_score < new_score {
                incumbent_score = new_score;
                assignments.push(new_assignment(schedule.get_nr(), nurse.get_nr()));
                taken_nurse = Some(nurse.get_nr());
            }
        }
        //add preference penalty to total score
        *total_incumbent_score += incumbent_score;
        //remove the nurse from the list, already assigned to a schedule
        let index = nurse_list
            .iter()
            .position(|x| x.get_nr() == taken_nurse.unwrap());
        nurse_list.remove(index.unwrap());
        // TODO: stop assigning nurses to schedules when fte budget is reached
        // ? do the schedules adhere to the fte budget?
    }
    assignments
}
error[E0382]: borrow of moved value: `nurse_list`
    --> src\main.rs:75:21
     |
53   |       nurse_list: &mut Vec<Nurse>,
     |       ---------- move occurs because `nurse_list` has type `&mut Vec<definitions::Nurse>`, which does not implement the `Copy` trait
...
64   |           for nurse in nurse_list {
     |                        ---------- `nurse_list` moved due to this implicit call to `.into_iter()`
...
75   |           let index = nurse_list
     |  _____________________^
76   | |             .iter()
     | |___________________^ value borrowed here after move
     |
     = note: borrow occurs due to deref coercion to `[definitions::Nurse]`

I tried borrowing the nurse_list again in the for loop for nurse in &nurse_list { ... } which then returns the following error:

src\main.rs:64:22
   |
64 |         for nurse in &nurse_list {
   |                      ^^^^^^^^^^^ `&&mut Vec<definitions::Nurse>` is not an iterator
   |
   = help: the trait `Iterator` is not implemented for `&&mut Vec<definitions::Nurse>`

Solution

  • The type &mut T which is a reference doesn't implement Copy thus the reference moved in the first loop and you can't access it anymore. To get around this you have to reborrow with this:

    for nurse in &mut *nurse_list {…}
    

    in every loop you do not want the nurse_list to move into.