5

リンクされたリストの要素への変更可能な参照を生成する反復子を実装しようとしているときに、奇妙な問題に遭遇しました。

これはうまくいきます:

impl<'a, T> Iterator<&'a T> for LinkedListIterator<'a, T>{
    fn next(&mut self) -> Option<&'a T> {
        match self.current {
            &Cell(ref x, ref xs) => {self.current = &**xs; Some(x)},
            &End                 => None
        }
    }
}

しかし、これはうまくいきません。コンパイラは、 の有効期間がself短すぎて、内容を安全に再借用できることを保証できないと言います:

impl<'a, T> Iterator<&'a mut T> for LinkedListMutIterator<'a, T>{
    fn next(&mut self) -> Option<&'a mut T> {
        match self.current {
            &Cell(ref mut x, ref mut xs) => {self.current = &mut **xs; Some(x)},
            &End                         => None
        }
    }
}

両方の例が機能するか、または両方が機能しないことを期待しますが、変更可能と変更不可として何かを借用すると、コンパイラが寿命をチェックする方法にどのように影響するか理解できません。確かに何かが安全に借用できるほど長生きするなら、それは安全に可変的に借用できるほど長生きするでしょうか?

編集: 両方のイテレータの定義は次のとおりです。

pub struct LinkedListIterator<'a, T> 
    current: &'a LinkedList<T>
}

pub struct LinkedListMutIterator<'a, T> {
    current: &'a mut LinkedList<T>
}

LinkedLisk:

#[deriving(Eq, Clone)]
pub enum LinkedList<T> {
    Cell(T, ~LinkedList<T>),
    End
}

ファイルの完全なビューについては、 https://github.com/TisButMe/rust-algo/blob/mut_iter/LinkedList/linked_list.rsを参照してください。

4

1 に答える 1

2

LinkedListMutIterator問題を再現して分析する実際の試みに関連する可能性のある、コードの 2 つのバリアント ビットの定義を省略していることに注意してください。


というわけで、どうなるか予想してみます。

ここでのコンパイラ エラー メッセージは誤解を招く可能性があります。selfここで関連する可能性のある の寿命を超えた他の要因があります。

特に、ボローチェッカーが不平を言っていると思われます。これは、同じ状態に別名を付ける複数の可変ボローを作成していないことを確認しようとしているからです。

  • 同じ状態に対して複数の不変借用があるのは健全です...

  • ...しかし、同じ状態に対して複数の変更可能な借用を行うことはできません (&mut何らかの状態への参照がある場合、その参照が状態を変更する唯一の方法であることを確認したいため)。

于 2014-01-09T00:44:06.080 に答える