6

Rust で Disjoint-Set データ構造を作成しようとしていました。関連するコードは次のとおりです。

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

ボローチェッカーを完全に理解しているかどうかはわかりませんが、参照を使用して、構造体自体の所有権を取得しないようにして、他の言語と同じように構造体を指して再割り当てできるようにしています。

構造体の参照からを削除することでこれらのエラーを回避できますmutが、各セットの親は不変であるため変更できません。

次のような同様の質問を読みました。

これらは、この問題を解決する方法を見つけるのに役立ちません。findまた、使用する構造体だけでなく関数も再構築しようとRc<RefCell<Set>>Box<Set>ましたが、常に同じエラーが発生します。

このエラーは何ですか?どうすれば修正できますか?

4

2 に答える 2

4

このマッチ アームは、enum バリアント コンポーネントを値で取得します。タイプはコピーできないため、コンポーネントが元の場所から移動されることを意味します。これにより、元の構造体が部分的に未定義になります-Rustでは大したことではありません。

これを修正するには、コンパイラが提案するように、代わりに参照を使用します。

Some(ref mut p) =>

次に、結果を に保存してOptionすぐに取り出すのではなく、参照を変数に保持し、 に入れ、それOptionを返すようにします。

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

これは、アイデア全体の核となる問題につながります。

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 の安全システムのもう 1 つの中心的な原則です。なぜなら、いつ、どこで変更が行われるかをコンパイラが保証するのが難しくなるためです。

この回答をチェックして、それを回避する1つの方法を確認してください。

于 2015-01-28T14:50:00.193 に答える