Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot borrow `*x` as mutable because it is also borrowed as immutable

I'm making a Combinatory Optimization project to learn Rust and I've got a problem I cannot resolve myself...

I've got 2 functions :

pub fn get_pareto_front_offline<'a>(scheduling_jobs: &'a Vec<Vec<u32>>, costs_vector: &'a Vec<(u32, u32)>) -> Vec<(&'a Vec<u32>, &'a (u32, u32))> {
    // ...
}

and

pub fn pareto_approach_offline<'a>(list_of_jobs: &'a mut Vec<Vec<u32>>, neighborhood: &'a mut Vec<Vec<u32>>, costs: &'a Vec<(u32, u32)>) -> Vec<(&'a Vec<u32>, &'a (u32, u32))> {
    let pareto_front = get_pareto_front_offline(neighborhood, costs);

    loop {
        if pareto_front == vec![] {
            break;
        }

        neighborhood.clear();

        for front in pareto_front.iter() {
            neighborhood.push((front.0).clone());
        }
    }

    pareto_front
}

I've got a problem because the compiler tells me:

cannot borrow '*neighborhood' as mutable because it is also borrowed as immutableat line 15 col 9
cannot borrow '*neighborhood' as mutable because it is also borrowed as immutableat line 19 col 13
like image 418
WebTogz Avatar asked Dec 19 '22 21:12

WebTogz


1 Answers

You're trying to do something fundamentally impossible.

When you call get_pareto_front_offline, you pass a re-borrowing of neighborhood into that function. This re-borrow must be maintained in order for pareto_front to remain valid. In other words, as long as pareto_front exists, the compiler will not allow you to access neighborhood in any fashion whatsoever.

This is a good thing, because you then proceed to try and clear our neighborhood, which would almost certainly invalidate pareto_front, likely leading to use-after-free and corrupting your program's state.

It's not clear what it is you're attempting to do; but you cannot do it this way.

As an aside, even if it compiled, that loop would probably never finish running: your termination condition (pareto_front == vec![]) will never be satisfied because you never modify pareto_front; it'll either stop immediately, or run forever.

The simplest way to get out from under borrowing problems is to make copies of things, so that you don't need a long-lived borrow; if get_pareto_front_offline returned a Vec<(Vec<u32>, (u32, u32))> instead, you wouldn't have this issue. That, or modify to code to not touch neighborhood once you call get_pareto_front_offline.

like image 58
DK. Avatar answered May 16 '23 04:05

DK.