How to get this example to compile without array copying or multiple calls to b() per iteration — b() has to perform some expensive parsing?
This is not the full code that I wrote, but it illustrates the problem I had. Here, Test is attempting to perform some kind of streaming parsing work. c() is the parsing function, it returns Some when parsing was successful. b() is a function that attempts to read more data from the stream when c() can not parse using the available data yet. The returned value is a slice into the self.v containing the parsed range.
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();
}
When compiling, it produces the following borrow checker error:
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
If I change a() to:
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!();
}
}
}
Then it runs, but with the obvious drawback of calling the parsing function c() twice.
I kind of understand that changing self while the return value depends on it is unsafe, however, I do not understand why is the immutable borrow for self.v is still alive in the next iteration, when we attempted to call b() again.