I’m writing a fn to pop the element from last pos in a LinkedList, but a double mut ref error occurs in this scenario, where I’m trying to get the second last node so that I can chop off the tail
fn pop(&mut self) -> Option<T> {
match self.head {
None => None,
Some(ref mut head) => {
let mut curr = head;
while let Some(ref mut next) = curr.next {
if next.next.is_none() {
break;
}
curr = next;
}
let taken = curr.next.take();
taken.map(|x| x.data)
}
}
}
but the code compiles when there is no check
fn pop(&mut self) -> Option<T> {
match self.head {
None => None,
Some(ref mut head) => {
let mut curr = head;
while let Some(ref mut next) = curr.next {
// if next.next.is_none() {
// break;
// }
curr = next;
}
let taken = curr.next.take();
taken.map(|x| x.data)
}
}
}
Error
error[E0499]: cannot borrow `curr.next` as mutable more than once at a time
--> src\main.rs:70:29
|
62 | while let Some(ref mut next) = curr.next {
| ------------ first mutable borrow occurs here
...
70 | let taken = curr.next.take();
| ^^^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
Can’t seem to figure out the issue as I’m new to rust. any help would be appreciated.
Full Code
use std::fmt::Debug;
#[derive(Debug)]
struct Node<T> {
data: T,
next: Option<Box<Node<T>>>,
}
#[derive(Debug)]
struct LinkedList<T> {
head: Option<Box<Node<T>>>,
len: usize,
}
impl<T: Debug> LinkedList<T> {
fn new() -> Self {
Self { head: None, len: 0 }
}
fn push(&mut self, data: T) {
match self.head {
None => self.head = Some(Box::new(Node::new(data))),
Some(ref mut head) => {
let mut curr = head;
while let Some(ref mut next) = curr.next {
curr = next;
}
curr.next = Some(Box::new(Node::new(data)));
}
}
self.len += 1;
}
// head -> 1 -> 2
fn pop(&mut self) -> Option<T> {
match self.head {
None => None,
Some(ref mut head) => {
let mut curr = head;
while let Some(ref mut next) = curr.next {
// if next.next.is_none() {
// break;
// }
curr = next;
}
let taken = curr.next.take();
taken.map(|x| x.data)
}
}
}
}
impl<T> Node<T> {
fn new(data: T) -> Self {
Node { data, next: None }
}
}
>Solution :
This is a well-known flaw of the borrow checker. Your code compiles with the next-gen Polonius borrow checker.
The fix for this is to not keep a mutable reference in the loop:
while curr.next.is_some() {
curr = curr.next.as_mut().unwrap();
}
This is awkward and ugly, but this is what we can do now.