Home > Back-end >  Cannot borrow vector as mutable because it is also borrowed as immutable when picking a value from a
Cannot borrow vector as mutable because it is also borrowed as immutable when picking a value from a

Time:08-12

I have this code:

use rand::seq::SliceRandom;
use std::ops::Range;

#[derive(PartialEq)]
struct Stack {
    settings: bool
}

fn generate_random_value(number: u8, cards: &mut Vec<Stack>) -> Vec<&Stack> {
    let mut overflow = vec![];
    for _ in (Range { start: 0, end: number } ) {
        let card = cards.choose(&mut rand::thread_rng()).unwrap();
        overflow.push(card);
        let elem = cards.iter().position(|x| x == card).unwrap();
        cards.remove(elem);
    };
    return overflow
}

fn main() {
    let stack_one = Stack {
        settings: true
    };

    let stack_two = Stack {
        settings: false
    };

    let mut vector = vec![stack_one, stack_two];
    let _gen_num = generate_random_value(2, &mut vector);
}

I need to remove an elem from the vector.

error[E0502]: cannot borrow `*cards` as mutable because it is also borrowed as immutable
  --> src/main.rs:15:9
   |
9  | fn generate_random_value(number: u8, cards: &mut Vec<Stack>) -> Vec<&Stack> {
   |                                             - let's call the lifetime of this reference `'1`
...
12 |         let card = cards.choose(&mut rand::thread_rng()).unwrap();
   |                    ------------------------------------- immutable borrow occurs here
...
15 |         cards.remove(elem);
   |         ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
16 |     };
17 |     return overflow
   |            -------- returning this value requires that `*cards` is borrowed for `'1`

Playground

CodePudding user response:

You are currently trying to store a reference to your card, put that reference into a new Vec, then remove the original card. That would leave an invalid reference. Instead of trying to collect references in your returned vector, push the actual object which was removed:

fn generate_random_value(number: u8, cards: &mut Vec<Stack>) -> Vec<Stack> {
    let mut overflow = vec![];
    for _ in 0..number { // `..` is a shorthand `Range` initialization
        let card = cards.choose(&mut rand::thread_rng()).unwrap();
        let elem = cards.iter().position(|x| x == card).unwrap();

        // `remove` returns the object it removed
        overflow.push(cards.remove(elem));
    };
    overflow
}
  • Related