首页 > 解决方案 > 如何向编译器传达借用仅发生在枚举的一半中

问题描述

我有一个Parent包含一个Option<Child>,每个都Child包含一个Target

struct MyError {}

struct Target {}

struct Child {
    target: Target,
}

struct Parent {
    child: Option<Child>,
}

创建ParentorChild可能会失败:

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

我的目标是:

  1. 分配Parent,失败时返回错误。
  2. 分配Child,在失败时返回错误并释放Parent.
  3. 返回&mut Targeton 成功。

到目前为止,我有:

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部分Result没有借用this_opt但没有成功。

一种解决方案是首先执行分配,然后检索目标。Target但是,在我的用例中,我有多个图层(4 层页表),所以理想情况下,一旦我到达它,我就能够返回它。由于每一层都必须做大致相同的事情,我希望一个带有一些简单名称替换的宏能够创建一个多层结构。

这是否可以编写(理想情况下安全且简洁),如果可以,如何编写?

标签: rustborrow-checker

解决方案


推荐阅读