2014-01-08 10 views
5

Beim Versuch, einen Iterator zu implementieren, der veränderbare refs zu Elementen einer verknüpften Liste ergibt, stolperte ich über ein seltsames Problem.Borrow vs veränderbar borgen seltsamen Fehler in Lebenszeiten

Dies funktioniert:

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

Aber das funktioniert nicht; der Compiler sagt Lebensdauer von self zu kurz ist, seinen Inhalt zu gewährleisten sicher neu aufgenommen werden kann:

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

Ich würde erwarten, dass entweder beide beispielsweise Arbeit oder beides nicht, aber ich kann nicht verstehen, wie Kreditaufnahme etwas wie wandelbar vs not-mutable würde die Art beeinflussen, wie der Compiler nach Lebensdauern sucht. Sicherlich, wenn etwas lange genug lebt, um sicher ausgeliehen zu werden, lebt es lange genug, um sicher umwandelbar geliehen zu werden?

EDIT: Hier ist die Definition der beiden Iteratoren:

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 
} 

für eine komplette Ansicht der Datei finden Sie in https://github.com/TisButMe/rust-algo/blob/mut_iter/LinkedList/linked_list.rs

Antwort

2

Hinweis, die Sie haben habe die Definition (en) von LinkedListMutIterator für die zwei Varianten von Code weggelassen, die für jeden echten Versuch, dein Problem zu reproduzieren und zu analysieren, relevant sein könnten.


Also werde ich versuchen zu erraten, was los ist.

Die Compiler-Fehlermeldung hier könnte Sie irreführen; Es gibt andere Faktoren außerhalb der Lebensdauer von self, die hier relevant sein können.

Insbesondere vermute ich, dass der Borg-Checker sich beschwert, weil es versucht, sicherzustellen, dass Sie nicht mehrere veränderbare-borrows erstellen, die denselben Zustand alias haben.

  • Es ist Klang mehrere unveränderlich-leiht auf das gleiche Stück Zustand ...

  • zu haben ... aber Sie können auf das gleiche Stück Zustand nicht haben mehr änderbaren-borgt (weil wir Möchten Sie sicherstellen, dass, wenn Sie einen &mut Verweis auf einen Zustand haben, dann diese Referenz die einzige Möglichkeit ist, den Status zu ändern).

+0

Die von Ihnen vorgeschlagenen Informationen hinzugefügt. Ich sehe nicht, wo ich anderswo xs irgendwo anders leihen kann? Der einzige andere & mut-Zeiger ist der in der Struktur gespeicherte Zeiger _current_, der auf das vorherige Element in der Liste zeigt, nicht auf xs. –

+0

Ich denke, ein Beweis, dass der Iterationscode jede Zelle der Linked-List * höchstens einmal * besucht, übersteigt die Fähigkeiten des Border-Checkers. Sie und ich wissen, dass "next" den Cursor des Iterators in die verknüpfte Liste bringt und somit sicherstellt, dass Sie nicht denselben '& mut' Zeiger zweimal von" next "zurückgeben (was Alias ​​illegal einführen würde), aber ich denke nicht der Borrow-Checker kann auf diese Weise argumentieren ... aber ich habe den Umgang des Borrow-Checkers mit diesem Fall noch nicht genau verfolgt. – pnkfelix

+0

Einverstanden. Gibt es eine Möglichkeit, das zu umgehen, ohne unsichere Zeiger zu verwenden? –