我的树结构:
struct Tree {
true_branch: Option<Box<Tree>>,
false_branch: Option<Box<Tree>>,
}
要在第一次访问时进行延迟初始化,我想返回一个
Result<&mut Tree, &mut Tree>
,如果节点已经初始化,则返回 Ok(requested_node)
,或者返回 Err(last_initialized_on_the_path_to_requested_node)
,以便延迟初始化可以从该节点继续。
获取一个节点,如果它初始化可以与
get_mut
正常工作,但我无法获取 Result
版本 get_last_initialized_mut
进行编译。
impl Tree {
fn get_mut(&mut self, mut directions: impl Iterator<Item = bool>) -> Option<&mut Self> {
let mut current = self;
loop {
match directions.next() {
None => break,
Some(true) => {
current = current.true_branch.as_deref_mut()?;
}
Some(false) => {
current = current.false_branch.as_deref_mut()?;
}
}
}
Some(current)
}
/// This does not compile
fn get_last_initialized_mut(&mut self, mut directions: impl Iterator<Item = bool>) -> Result<&mut Self, &mut Self> {
let mut current = self;
loop {
match directions.next() {
None => break,
Some(true) => {
let next = current.true_branch.as_deref_mut();
if next.is_none() {
drop(next);
return Err(current);
} else {
current = next.unwrap();
}
}
Some(false) => {
let next = current.false_branch.as_deref_mut();
if next.is_none() {
drop(next);
return Err(current);
} else {
current = next.unwrap();
}
}
}
}
Ok(current)
}
}
error[E0499]: cannot borrow `*current` as mutable more than once at a time
--> src/lib.rs:36:36
|
27 | fn get_last_initialized_mut(&mut self, mut directions: impl Iterator<Item = bool>) -> Result<&mut Self, &mut Self> {
| - let's call the lifetime of this reference `'1`
...
33 | let next = current.true_branch.as_deref_mut();
| ---------------------------------- first mutable borrow occurs here
...
36 | return Err(current);
| ^^^^^^^ second mutable borrow occurs here
...
52 | Ok(current)
| ----------- returning this value requires that `current.true_branch` is borrowed for `'1`
我没有得到的是,我在第 35 行删除了
next
,然后它说 current
仍然在第 36 行借用,由第 33 行的 next
借用。
我尝试使用枚举进行中断,并根据中断类型返回循环外部,删除变量。他们都没有工作。
在原始程序的每个匹配臂中,借用
next
的 current
的生命周期至少会在匹配臂块结束之前结束:
let next = current.true_branch.as_deref_mut();
// borrow starts
if next.is_none() {
drop(next);
return Err(current);
} else {
current = next.unwrap();
}
// borrow ends
我们可以通过将 next 的生命周期限制为
if let
语句来解决此问题,因为我们会检查 Option
枚举:
if let Some(ref mut next) = current.true_branch {
next
} else {
return Err(current);
}
现在,
current
的借用仅跨越if let
语句的真实分支。在 else
分支中,current
不是借用的。这意味着我们可以安全地在 current
分支中返回 else
。