Wie erstelle ich in Rust einen veränderlichen Iterator? [Duplikat]
Ich habe Schwierigkeiten mit der Lebensdauer, wenn ich versuche, einen veränderlichen Iterator in Safe Rust zu erstellen.
Folgendes habe ich auf Folgendes reduziert:
struct DataStruct<T> {
inner: Box<[T]>,
}
pub struct IterMut<'a, T> {
obj: &'a mut DataStruct<T>,
cursor: usize,
}
impl<T> DataStruct<T> {
fn iter_mut(&mut self) -> IterMut<T> {
IterMut { obj: self, cursor: 0 }
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let i = f(self.cursor);
self.cursor += 1;
self.obj.inner.get_mut(i)
}
}
fn f(i: usize) -> usize {
// some permutation of i
}
Die Struktur meines DataStruct
Willens ändert sich nie, aber ich muss in der Lage sein, den Inhalt der darin gespeicherten Elemente zu mutieren. Zum Beispiel,
let mut ds = DataStruct{ inner: vec![1,2,3].into_boxed_slice() };
for x in ds {
*x += 1;
}
Der Compiler gibt mir einen Fehler bezüglich widersprüchlicher Lebensdauern für die Referenz, die ich zurückgeben möchte. Die Lebensdauer, die ich nicht erwarte, ist der Umfang der next(&mut self)
Funktion.
Wenn ich versuche, die Lebensdauer zu kommentieren next()
, teilt mir der Compiler stattdessen mit, dass ich das Iterator-Merkmal nicht erfüllt habe. Ist das in sicherem Rost lösbar?
Hier ist der Fehler:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/iter_mut.rs:25:24
|
25 | self.obj.inner.get_mut(i)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:5...
--> src/iter_mut.rs:22:5
|
22 | / fn next(&mut self) -> Option<Self::Item> {
23 | | let i = self.cursor;
24 | | self.cursor += 1;
25 | | self.obj.inner.get_mut(i)
26 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/iter_mut.rs:25:9
|
25 | self.obj.inner.get_mut(i)
| ^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 19:6...
--> src/iter_mut.rs:19:6
|
19 | impl<'a, T> Iterator for IterMut<'a, T> {
| ^^
note: ...so that the types are compatible
--> src/iter_mut.rs:22:46
|
22 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
23 | | let i = self.cursor;
24 | | self.cursor += 1;
25 | | self.obj.inner.get_mut(i)
26 | | }
| |_____^
= note: expected `std::iter::Iterator`
found `std::iter::Iterator`
Änderungen :
- Die Implementierung wurde
next()
so geändert , dass die Iterationsreihenfolge eine Permutation der ursprünglichen Sequenz ist.
Antworten
Der Leihprüfer kann nicht nachweisen, dass nachfolgende Aufrufe next()
nicht auf dieselben Daten zugreifen. Der Grund, warum dies ein Problem ist, liegt darin, dass die Lebensdauer des Ausleihens für die Dauer des Iterators gilt. Daher kann nicht nachgewiesen werden, dass nicht zwei veränderbare Verweise auf dieselben Daten gleichzeitig vorhanden sind.
Es gibt wirklich keine Möglichkeit, dies ohne unsicheren Code zu lösen - oder Ihre Datenstrukturen zu ändern. Sie könnten das Äquivalent von tun slice::split_at_mut
, aber da Sie die Originaldaten nicht mutieren können, müssten Sie dies trotzdem in unsicherem Code implementieren. Eine unsichere Implementierung könnte ungefähr so aussehen:
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let i = self.cursor;
self.cursor += 1;
if i < self.obj.inner.len() {
let ptr = self.obj.inner.as_mut_ptr();
unsafe {
Some(&mut *ptr.add(i))
}
} else {
None
}
}
}