我有一个Parent
,其中包含一个Option<Child>
,每个Child
,其中包含一个Target
。
struct MyError {}
struct Target {}
struct Child {
target: Target,
}
struct Parent {
child: Option<Child>,
}
创建Parent
或Child
可能会失败:
impl Child {
fn allocate_self() -> Result<Self, MyError> {
Ok(Self { target: Target {} }) // could fail
}
}
impl Parent {
fn allocate_self() -> Result<Self, MyError> {
Ok(Self { child: None }) // could fail
}
}
我的目标是:
Parent
,失败时返回错误。Child
,返回失败错误并释放Parent
。&mut Target
。到目前为止,我有:
impl Child {
fn retrieve_target(this_opt: &mut Option<Self>) -> Result<&mut Target, MyError> {
if this_opt.is_none() {
*this_opt = Some(Self::allocate_self()?);
}
Ok(&mut this_opt.as_mut().unwrap().target)
}
}
impl Parent {
fn retrieve_target(this_opt: &mut Option<Self>) -> Result<&mut Target, MyError> {
if this_opt.is_none() {
*this_opt = Some(Self::allocate_self()?)
}
let this = this_opt.as_mut().unwrap();
let result = Child::retrieve_target(&mut this.child);
// GOAL: if Child::retrieve_target succeeds,
// return the result, otherwise turn ourselves back into a None
if result.is_err() {
drop(this_opt.take());
}
result
}
}
问题是Parent::retrieve_target
失败,并出现编译器错误:
error[E0499]: cannot borrow `*this_opt` as mutable more than once at a time
--> src/lib.rs:44:18
|
35 | fn retrieve_target(this_opt: &mut Option<Self>) -> Result<&mut Target, MyError> {
| - let's call the lifetime of this reference `'1`
...
39 | let this = this_opt.as_mut().unwrap();
| -------- first mutable borrow occurs here
...
44 | drop(this_opt.take());
| ^^^^^^^^ second mutable borrow occurs here
45 | }
46 | result
| ------ returning this value requires that `*this_opt` is borrowed for `'1`
我尝试了各种方法来告诉编译器:Err
的{{1}}部分不是借用Result
而是没有成功。
一种解决方案是先执行分配,然后检索目标。但是,在我的用例中,我有多层(4层页表),因此理想情况下,一旦到达this_opt
就可以返回。由于每一层都必须做大致相同的事情,因此我希望有可能使用一些简单的名称替换宏来创建多层结构。
这种书写方式(理想情况下安全,简洁)是可能的吗?