Rust抱怨作用域后的借用



我试图在Rust中创建一个链表,并在最后附加值,我需要遍历它,然后添加这个新值。我避免递归,因为在大列表中它会很糟糕,加上试图更好地理解Box逻辑。

问题是,遍历后,我的变量'current'是对列表最后一个节点的可变引用。但是我不能修改它,Rust抱怨引用已经是

struct Node {
valor: Option<String>,
next: Option<Box<Node>>,
}
impl Node {
fn new(valor: Option<String>) -> Node {
Node { valor, next: None }
}
}
struct NodeList {
head: Option<Box<Node>>,
}
impl NodeList {
fn new() -> NodeList {
NodeList { head: None }
}
fn append(&mut self, novo: Node) {
if self.head.is_none() {
self.head = Some(Box::new(novo));
} else {
let mut current: &mut Option<Box<Node>> = &mut self.head;
loop {
let after: &mut Option<Box<Node>> = &mut (current.as_mut().unwrap()).next;
if after.is_none() {
break;
} else {
current = after;
}
}
current.as_mut().unwrap().next = Some(Box::new(novo));
}
}
}
fn main() {
let mut lista = NodeList::new();
for c in "açafrão".chars() {
let s = String::from(c);
lista.append(Node::new(Some(s)));
}
}

错误信息:

error[E0499]: cannot borrow `*current` as mutable more than once at a time
--> srcmain.rs:32:13
|
25 |                 let after: &mut Option<Box<Node>> = &mut (current.as_mut().unwrap()).next;
|                                                           ---------------- first mutable borrow occurs here
...
32 |             current.as_mut().unwrap().next = Some(Box::new(novo));
|             ^^^^^^^^^^^^^^^^
|             |
|             second mutable borrow occurs here
|             first borrow later used here

我做错了什么,我该如何解决这个问题?

假设在您的特殊情况下,您遇到了一个未解决的借阅检查器的角落情况。您的代码将在将来编译,但目前没有。

更多信息可以在这里看到:https://docs.rs/polonius-the-crab/

为了证明这是事实,您的代码构建和工作良好的实验(还不稳定)polonius借用检查器:

RUSTFLAGS="-Zpolonius" cargo +nightly run

解决这个问题的最好方法是重新排列调用的顺序,以便编译器更好地理解它们,像这样:

#[derive(Debug)]
struct Node {
valor: Option<String>,
next: Option<Box<Node>>,
}
impl Node {
fn new(valor: Option<String>) -> Node {
Node { valor, next: None }
}
}
#[derive(Debug)]
struct NodeList {
head: Option<Box<Node>>,
}
impl NodeList {
fn new() -> NodeList {
NodeList { head: None }
}
fn append(&mut self, novo: Node) {
if self.head.is_none() {
self.head = Some(Box::new(novo));
} else {
let mut current: &mut Node = &mut self.head.as_mut().unwrap();
loop {
if current.next.is_none() {
current.next = Some(Box::new(novo));
break;
}
current = current.next.as_mut().unwrap().as_mut();
}
}
}
}
fn main() {
let mut lista = NodeList::new();
for c in "açafrão".chars() {
let s = String::from(c);
lista.append(Node::new(Some(s)));
}
println!("{:#?}", lista);
}
NodeList { head: Some(Node { valor: Some("a"), next: Some(Node { valor: Some("ç"), next: Some(Node { valor: Some("a"), next: Some(Node { valor: Some("f"), next: Some(Node { valor: Some("r"), next: Some(Node { valor: Some("ã"), next: Some(Node { valor: Some("o"), next: None }) }) }) }) }) }) }) }

注:

不要试图通过实现链表来学习Rust。链表与rust的所有权模型高度不兼容。

如果你坚持这样做,这篇文章绝对是强制性的指导:

https://rust-unofficial.github.io/too-many-lists/

最新更新