rust &mut归还后自己借用生命[副本]

vnzz0bqm  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(149)

此问题已在此处有答案

Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?(1个答案)
20天前关闭。
我正在处理一段代码,其中有一些结构体包含相互引用,我遇到了一个问题,我似乎无法弄清楚。

// demonstration of what the problem is

struct State<T>(T);
struct Query<'a, T>(&'a T);

impl<T> State<T> {
    fn query(&mut self) -> Option<Query<'_, T>> {
        unimplemented!()
    }
}

struct Container<T>(Vec<State<T>>);

impl<T> Container<T> {
    fn query(&mut self) -> Option<Query<'_, T>> {
        let query = self.0.last_mut()?.query();

        if let Some(query) = query {
            return Some(query);
        }

        // i feel like i should be able to use &mut self again here but i can't :(

        self.0.pop(); 
        // error[E0499]: cannot borrow `*self` as mutable more than once at a time
        return self.query();
        // error[E0499]: cannot borrow `*self` as mutable more than once at a time
    }
}

字符串
在这个例子中,为什么在if块之后我不能再次借款?为什么借款的生命周期在归还后继续?

t3irkdon

t3irkdon1#

这是电流借位检查器的已知限制。这将是固定的引进新的波洛纽斯借用检查。
目前,有两种方法可以解决这个问题:

  • 使用unsafe
  • 改写代码以便借用检查器理解它

unsafe路由通常可以通过使用polonius_the_crab crate来抽象,以确保您的问题实际上适合此用例,并保持Rusts编译时安全保证。
在您的示例中,使用polonius_the_crab的情况如下所示:

use polonius_the_crab::prelude::*;

struct State<T>(T);
struct Query<'a, T>(&'a T);

impl<T> State<T> {
    fn query(&mut self) -> Option<Query<'_, T>> {
        unimplemented!()
    }
}

struct Container<T>(Vec<State<T>>);

impl<T> Container<T> {
    fn query(&mut self) -> Option<Query<'_, T>> {
        let mut this = self;

        polonius!(|this| -> Option<Query<'polonius, T>> {
            match this.0.last_mut() {
                None => polonius_return!(None),
                Some(state) => {
                    if let Some(query) = state.query() {
                        polonius_return!(Some(query));
                    }
                }
            };
        });

        this.0.pop();
        return this.query();
    }
}

字符串
我们需要let mut this = self;的原因是因为在内部,polonius!宏获得this的所有权,使用它,然后在最后将this写回变量。而&mut self不能写入。遗憾的是,没有办法将&mut self写成mut self: &mut Self,所以我们需要将它存储在一个临时变量中,我选择将其命名为this
基本上,你写的是:
我觉得我应该能够在这里再次使用&mut self,但我不能
这正是这个板条箱所修复的。
关于这个问题的更深入的解释和其他可能的解决方案可以在polonius_the_crab文档中找到。

ubof19bj

ubof19bj2#

由于query()被调用了两次,这个解决方案是可行的:

impl<T> Container<T> {
    fn query(&mut self) -> Option<Query<'_, T>> {
        if self.0.is_empty() { return None; }
        if self.0.last_mut().unwrap().query().is_some() {
            self.0.last_mut().unwrap().query()
        } else {
            self.0.pop();
            self.query()
        }
    }
}

字符串

相关问题