在& mut self方法中展开成员变量时,不能移出借用的内容 [英] cannot move out of borrowed content when unwrapping a member variable in a &mut self method

查看:115
本文介绍了在& mut self方法中展开成员变量时,不能移出借用的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Rust中创建一个Disjoint-Set数据结构.相关代码为:

I was trying to make a Disjoint-Set data structure in Rust. The relevant code is:

pub struct Set<'a, T: 'a> {
    rank: u32,
    value: T,
    parent: Option<&'a mut Set<'a, T>>,
}

impl<'a, T> Set<'a, T> {
    pub fn find(&'a mut self) -> &'a mut Set<'a, T> {
        match self.parent {
            None => self,
            Some(mut p) => {
                self.parent = Some(p.find());
                self.parent.unwrap()
            }
        }
    }
}

我得到的错误是:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:9:15
   |
9  |         match self.parent {
   |               ^^^^ cannot move out of borrowed content
10 |             None => self,
11 |             Some(mut p) => {
   |                  ----- hint: to prevent move, use `ref p` or `ref mut p`

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:13:17
   |
13 |                 self.parent.unwrap()
   |                 ^^^^ cannot move out of borrowed content

我不确定我是否完全了解借位检查器,但我使用引用来避免对结构本身拥有所有权,以便可以像使用其他语言一样对它们进行指向和重新分配.

I'm not sure I understand the borrow checker fully, but I am using references to avoid taking ownership of structs themselves so that they can be pointed to and reassigned similar to how you would in other languages.

我可以通过从结构中的引用中删除mut来避免这些错误,但是由于它们是不可变的,因此我无法更改每个集合的父级.

I can avoid these errors by removing the mut from the references in the struct, but then I cannot change the parent of each set because they are immutable.

我已经阅读了类似的问题,例如:

I have read through similar questions such as:

  • Rust: "cannot move out of `self` because it is borrowed" error
  • Can't borrow File from &mut self (error msg: cannot move out of borrowed content)

这些并没有帮助我解决如何解决此问题.我还尝试过重构函数find以及使用Rc<RefCell<Set>>Box<Set>的结构本身,但是我总是遇到相同的错误.

These aren't helping me work out how to solve this issue. I have also tried restructuring the function find as well as the struct itself to use Rc<RefCell<Set>> and Box<Set> but I always end up at the same error.

这是什么错误,我该如何解决?

What is this error and how do I fix it?

推荐答案

此匹配臂将按值获取枚举变量组件.由于您的类型不可复制,这意味着该组件将被移出原始位置.这会使您的原始结构部分不确定-在Rust中是一个很大的禁忌.

This match arm is going to take the enum variant components by value. Since your type isn't copyable, that would mean that the component would be moved out of the original place. This would make your original struct partially undefined - a big no-no in Rust.

要解决此问题,请改用引用,如编译器建议的那样:

To fix that, take a reference instead, as suggested by the compiler:

Some(ref mut p) =>

接下来,不要将结果存储在Option中,然后立即将其取出,请尝试将引用保留在变量中,将其放在Option中并返回:

Next up, instead of storing the result in an Option and then immediately taking it back out, try to keep the reference in a variable, put it in the Option and return it:

let z = p.find();
self.parent = Some(z);
z

这导致了整个想法的核心问题:

This leads to the core problem with the whole idea:

error[E0499]: cannot borrow `*z` as mutable more than once at a time
  --> src/main.rs:14:17
   |
13 |                 self.parent = Some(z);
   |                                    - first mutable borrow occurs here
14 |                 z
   |                 ^ second mutable borrow occurs here
15 |             }
   |             - first borrow ends here

您正在尝试存储可变引用,并将其返回.这意味着将有多个并发的对同一项目的可变引用(也称为别名).防止这种情况是Rust安全系统的另一项核心原则,因为那样一来,编译器就很难保证何时何地进行更改.

You are trying to store a mutable reference and return it. This would mean that there would be multiple concurrent mutable references to the same item (also known as aliasing). Preventing this is another core tenet of Rust's safety systems, because then it's harder for the compiler to guarantee when and where things are being changed.

查看此答案,以查看解决该问题的一种方法.

Check out this answer to see one way of working around that.

这篇关于在&amp; mut self方法中展开成员变量时,不能移出借用的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆