Capturing validation doesn't suit when conditionally popping elements from the binary heap

I am trying to write a simple function that would pop elements from a BinaryHeap that satisfy a certain condition. The function looks like this:

fn check_the_queue(mut queue: BinaryHeap<i32>) {
while !queue.is_empty() {
    let entry = queue.peek().unwrap();
    if *entry <= 0 {
        queue.pop();
    } 
}

      

When compiling, the borrower starts to complain:

src/main.rs:52:13: 52:18 error: cannot borrow `queue` as mutable because it is also borrowed as immutable

      

How can I get around this problem and make the loan verification program happy?

+3


source to share


1 answer


The error message is descriptive enough:

<anon>:8:13: 8:18 error: cannot borrow `queue` as mutable because it is also borrowed as immutable
<anon>:8             queue.pop();
                     ^~~~~
<anon>:5:21: 5:26 note: previous borrow of `queue` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `queue` until the borrow ends
<anon>:5         let entry = queue.peek().unwrap();
                             ^~~~~
<anon>:10:6: 10:6 note: previous borrow ends here
<anon>:4     while !queue.is_empty() {
...
<anon>:10     }
              ^

      

The problem is that it takes queue

:

let entry = queue.peek().unwrap();

      

peek()

returns Option<&T>

, that is, a parameter with a reference to a value of the type T

. The loan is valid as long as it is entry

alive, until the end of the function. It points to what is stored inside the heap, so it always occupies the heap. In other words, as long as it is entry

alive (until the end of the function), the heap is invariably borrowed.

queue.pop()

changes the heap fluidly, so by the time you get to that, the heap will invariably be borrowed, and you try to borrow it easily at the same time.



The check validation rules say you cannot take something changeable and invariable at the same time, so you have a problem.

To fix this, find a way to avoid borrowing twice at the same time. For example, you can do this instead:

fn check_the_queue(mut queue: BinaryHeap<i32>) {
    while !queue.is_empty() {
        if *queue.peek().unwrap() <= 0 {
            queue.pop();
        } 
    }
}

      

That is, just drop the variable entry

. This works because by the time you reach queue.pop()

there are no other active bookmarks and the credit check is happy :)

Lifetimes and borrowing rules can be tricky at first, but a steep learning curve is calculated over time.

+5


source







All Articles