无法分配给“ node.next”,因为当引用已超出范围时会被借用

时间:2019-08-20 03:21:48

标签: rust

我正在尝试编写一个简单的链表,并且在尝试实现删除时遇到了这个问题。我无法分配给变量,因为即使引用超出范围,它也是借来的。

struct Node<T> {
    next: Option<Box<Node<T>>>,
    value: T,
}
struct LinkedList<T> {
    head: Option<Box<Node<T>>>,
}
fn remove(&mut self) {
    let head = self.head.as_mut().unwrap();
    if let None = head.next {
        self.head = None;
    } else {
        let mut node = head;
        loop {
            let next = node.next.as_mut().unwrap();
            if let None = next.next {
                break;
            } else {
                node = next;
            }
        }
        node.next = None;
    }
}
error[E0506]: cannot assign to `node.next` because it is borrowed
  --> linkedlist.rs:49:13
   |
42 |                 let next = node.next.as_mut().unwrap();
   |                            --------- borrow of `node.next` occurs here
...
49 |             node.next = None;
   |             ^^^^^^^^^
   |             |
   |             assignment to borrowed `node.next` occurs here
   |             borrow later used here

2 个答案:

答案 0 :(得分:0)

这似乎是一个编译器错误,有一个与该问题有关的答案:Rust lifetime issue in loop,可以更好地解释问题的根源:

  

如果只有一个执行路径终止循环,则无法为借项分配正确的生存期。

在您的示例中,从循环内部泄漏借入的值next(通过将其分配给node)会导致此问题,因为存在条件循环终止,因此要解决此问题,请执行以下操作不会泄漏借入的值,而是在分配给node时重新借入:

let mut node = head;
loop {
    let next = node.next.as_mut().unwrap();
    if let None = next.next {
        break;
    } else {
        node = node.next.as_mut().unwrap();
    }
}
node.next = None;

答案 1 :(得分:0)

@Anler是正确的。我正在写另一个答案,因为如果LinkedList为空,您的代码将会崩溃。这是有问题的行:

let head = self.head.as_mut().unwrap();

如果self.headNone(空列表)-> unwrap()会惊慌。这是一个有效的示例(loop-> while):

fn remove(&mut self) {
    let head = match self.head.as_mut() {
        Some(head) => head,
        None => return,
    };

    match head.next {
        None => self.head = None,
        Some(_) => {
            let mut node = head;
            while node.next.as_ref().unwrap().next.is_some() {
                node = node.next.as_mut().unwrap();
            }
            node.next = None;
        }
    };
}