Wie erhalten Sie dieses Beispiel zu kompilieren ohne Array kopieren oder mehrere Aufrufe an b()
pro Iteration - b()
muss einige teure Parsing durchführen?Rust Lebenszeitproblem in Schleife
Dies ist nicht der vollständige Code, den ich geschrieben habe, aber es veranschaulicht das Problem, das ich hatte. Hier versucht Test
eine Art von Streaming-Parsing-Arbeit durchzuführen. c()
ist die Parsing-Funktion, die Some
zurückgibt, wenn das Parsing erfolgreich war. b()
ist eine Funktion, die versucht, mehr Daten aus dem Stream zu lesen, wenn c()
die verfügbaren Daten noch nicht analysieren kann. Der zurückgegebene Wert ist ein Schnitt in self.v
, der den analysierten Bereich enthält.
struct Test {
v: [u8; 10],
index: u8,
}
impl Test {
fn b(&mut self) {
self.index = 1
}
fn c(i: &[u8]) -> Option<&[u8]> {
Some(i)
}
fn a(&mut self) -> &[u8] {
loop {
self.b();
match Test::c(&self.v) {
Some(r) => return r,
_ => continue,
}
}
}
}
fn main() {
let mut q = Test {
v: [0; 10],
index: 0,
};
q.a();
}
Beim Kompilieren, erzeugt es die Checker Fehler folgenden borgen:
error[E0502]: cannot borrow `*self` as mutable because `self.v` is also
borrowed as immutable
--> <anon>:17:13
|
17 | self.b();
| ^^^^ mutable borrow occurs here
18 |
19 | match Test::c(&self.v) {
| ------ immutable borrow occurs here
...
24 | }
| - immutable borrow ends here
Wenn ich a()
zu ändern:
fn a(&mut self) -> Option<&[u8]> {
loop {
self.b();
if let None = Test::c(&self.v) {
continue
}
if let Some(r) = Test::c(&self.v) {
return Some(r);
} else {
unreachable!();
}
}
}
Dann läuft es, aber mit dem offensichtlichen Nachteile des anruf Parsing-Funktion c()
zweimal.
Ich verstehe Art, dass self
Wechsel während des Rückgabewert hängt davon ab, es unsicher ist, aber ich verstehe nicht, warum die unveränderliche borrow für self.v
noch am Leben in der nächsten Iteration ist, wenn wir b()
versuchen erneut anzurufen.
sieht für mich wie ein Compiler-Fehler aus. Ich denke, die zweite Version sollte auch nicht kompilieren (und in der Tat ist es nicht, wenn Sie den Else-Zweig entfernen) –
@ PaoloFalabella, es ist kein Fehler. Der Compiler kann folgern, dass 'self.b()' nicht aufgerufen wird, während das zweite Borrow von 'self.v' aktiv ist, weil die Schleife unbedingt endet, nachdem dieses Borrow genommen wurde. Wenn Sie Else Branch entfernen, ist es nicht mehr wahr. – red75prime
@ red75prim ah du hast recht, danke! –