2014-01-08 9 views
5

リンクリストの要素に対する変更可能な参照を生成するイテレータを実装しようとしているとき、私は奇妙な問題に遭遇しました。借用vs変更可能生涯で奇妙な借用

これは正常に動作します:

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の寿命が安全にreborrowedすることができ、その内容を保証するには短すぎると言う:

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

私は両方の例の仕事のどちらか、または両方がないことを期待するだろうが、私は理解することはできませんどのように借入何かのように変更可能vs not-mutableは、コンパイラが存続期間をチェックする方法に影響します。確かに何かが安全に借りるのに十分な長さであれば、それは安全に変更可能に借りられるほど長く生きるのですか?

EDIT:

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

答えて

2

ノートを参照してください。ここでは、両方のイテレータの定義がありますコードの2つの異形ビットについて、LinkedListMutIteratorの定義を除外しました。これは、問題の再現と解体の実際の試みに関連する可能性があります。


だから私は何が起こっているのかを推測しようとします。

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

特に私は、あなたが同じ状態のエイリアスを持つ複数の可変借用を作成していないことを保証しようとしているため、借用チェッカーが不平を言っていると思われます。

  • 複数の不変-借り状態の同じ部分に...

  • を持っている音です...しかし、あなたは持っていないことができ、複数の可変-借りて(状態の同じ部分に我々理由ある状態への参照が&mutの場合、その参照が状態を変更する唯一の方法であることを確認したい)。

+0

あなたが提案した情報を追加しました。 私はどこにxsをどこからでも借りていますか?唯一の他の&mutポインタは、構造体に格納されている_current_ポインタです。ポインタはxsではなくリストの前の要素を指します。 –

+0

私は、反復コードがリンクリスト*の各セルをたびたび訪問するという証拠は、借用チェッカーの機能を超えていると思います。あなたと私は 'next'がイテレータのカーソルをリンクリストに更新し、' next'から同じ '&mut'ポインタを2回返さないことを保証しています(違法にエイリアシングを導入するでしょう)借りチェッカーはそのように考えることができます...しかし、私は借りチェッカーがこのケースを慎重に処理していることをまだ追跡していません。 – pnkfelix

+0

合意。安全でないポインタを使用しないで回避する方法はありますか? –