我正在编写一个fn来从LinkedList中的最后一个位置弹出元素,但是在这个场景中发生了一个双mut引用错误,我试图获取倒数第二个 node ,这样我就可以砍掉 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)
            }
        }
    }

但代码会在没有判断的情况下编译

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[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


因为我对Rust 还不熟悉,所以我好像搞不清楚这个问题.任何帮助都将不胜感激.

完整代码

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 }
    }
}

推荐答案

这是借阅判断器的一个众所周知的缺陷.您的代码将使用下一代Polonius借入判断器进行编译.

解决此问题的方法是不在循环中保留可变引用:

while curr.next.is_some() {
    curr = curr.next.as_mut().unwrap();
}

这是尴尬和丑陋的,但这是我们现在能做的.

Rust相关问答推荐

程序退出后只写入指定管道的数据

在自身功能上实现类似移动的行为,以允许通过大小的所有者进行呼叫(&;mut;self)?

通过解引用将值移出Box(以及它被脱糖到什么地方)?

在决定使用std::Sync::Mutex还是使用Tokio::Sync::Mutex时,操作系统线程调度是考虑因素吗?

像这样的铁 rust 图案除了‘选项’之外,还有其他 Select 吗?

定义只有一些字段可以缺省的 struct

使用关联类型重写时特征的实现冲突

&'a T 是否意味着 T: 'a?

如何从宏调用闭包?

tokio::spawn 有和没有异步块

当没有实际结果时,如何在 Rust 中强制执行错误处理?

sha256 摘要仅适用于 &*

为什么不能在 Rust 中声明静态或常量 std::path::Path 对象?

由特征键控的不同 struct 的集合

&self 参数在 trait 的功能中是必需的吗?

Rust Serde 为 Option:: 创建反序列化器

为什么数组不像向量那样在 for 块之后移动?

如何使用 rust bindgen 生成的 std_vector

将 (T, ()) 转换为 T 安全吗?

为什么可以从不可变 struct 的字段中移动?