2014-01-08 39 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不可變會影響編譯器檢查生命週期的方式。當然,如果有足夠長的時間可以安全借用,它的壽命足夠長,以便能夠安全地進行可變借用?

編輯:這裏是兩個迭代器的定義:

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

請注意,已對於代碼的兩個不同位來說,忽略了LinkedListMutIterator的定義,這可能與任何真正的重現和剖析問題的嘗試有關。


所以,我會嘗試猜測發生了什麼。

這裏的編譯器錯誤信息可能會誤導你;在self的生命週期之外還有其他因素可能與此處有關。

特別是我懷疑借用檢查器是抱怨,因爲它試圖確保您沒有創建多個可變的藉口,別名相同的狀態。

  • 它的聲音有多個不可改變借用到同一狀態的...

  • ...但你不能有多個可變的,借到同一狀態的(因爲我們要確保如果你有一個&mut引用某個狀態,那麼該引用是改變狀態的唯一方法)。

+0

添加了您建議的信息。 我不明白我在哪裏可變地借用XS在其他地方?唯一的其他&mut指針是存儲在結構中的_current_指針,它指向列表中的前一個元素,而不是xs。 –

+0

我認爲迭代代碼最多訪問鏈表*的每個單元*的證明超出了借用檢查器的功能。你和我知道'next'會將迭代器的光標更新到鏈表中,從而確保你不會從'next'返回兩次'&mut'指針(這會引入非法的混淆),但我不認爲借款支票可以這種方式推理......但我還沒有仔細檢查借款支票對此案件的處理情況。 – pnkfelix

+0

同意。那麼有沒有什麼辦法可以避免使用不安全的指針呢? –

相關問題