I want to write parser almost without copying bytes around, but I meet very strange error (the code bellow is senseless because of I try to make example as short as possible):
The strange thing that it allows only one call of it.next(), if leave only one it.next() call all works fine.
But why, all references should be dropped because of it.next() surrounded by {} ?
error[E0499]: cannot borrow `it` as mutable more than once at a time
--> src/main.rs:54:9
|
51 | it.next();
| -- first mutable borrow occurs here
...
54 | it.next();
| ^^
| |
| second mutable borrow occurs here
| first borrow later used here
When member function next is called on it. it will be borrowed until it is dropped. (Code lies a bit since this will always be less than whatever is borrowed by lifetime 'c.)
This is because you've defined that the lifetime of the returned value must be identical to the lifetime of self (with exclusive borrows there's no subtyping flexibility). Because mut is an exclusive borrow, and you can have only one exclusive self, you can have only one excusive returned value existing.
There is never anything good happening from adding a lifetime on &self, so don't do that.
Mutable iterators can't be proven correct by the borrow checker. It has to ensure that returned mutable references don't overlap, but can't reason about the logic. It means you will have to use unsafe, or sometimes leverage some other (unsafe internally) construct like an other mutable iterator or split_at_mut (but if I remember correctly, even that is tricky and needs some unintuitive mem::swap).
I think it would fit Iterator, because the iterator only borrows the buffer, not owns it. But if you need to own it, then try using the interface of streaming_iterator - Rust
The problem is that your interface — and the borrow checker only looks at interfaces, not implementations — allows unsafe behavior.
next(&mut self) {
if random() { self.buf.clear() }
…
}
would compile with this interface, but invalidate all references you've given out. That's why mutable iterators in general need a bit of unsafe code, e.g transmute lifetimes, to convince the borrow checker that they won't mutate the references they give out.
Wait a minute! It's not a mutable iterator! You have &mut buf for no reason! Make it shared &buf and it will all work just fine.