Consider the following code (also available on the playground)
pub trait TextStream {
fn next_str(&mut self) -> Option<&str>;
}
pub struct FilterTextStream<T: TextStream> {
inner: T,
maxlen: usize,
}
impl<T: TextStream> TextStream for FilterTextStream<T> {
fn next_str(&mut self) -> Option<&str> {
match self.inner.next_str() {
None => None,
Some(txt) if txt.len() <= self.maxlen => {
Some(txt) // <-- this does not compile
//Some(unsafe {&*(txt as *const str)}) // <-- this fixes the problem
}
_ => self.next_str()
}
}
}
The TextStream
trait works like an iterator, except that the &str
's it yields do not have overlapping lifetimes. FilterTextStream
works like a (specialized) filter iterator.
However, this code fails to compile, with the following error:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:18:18
|
11 | fn next_str(&mut self) -> Option<&str> {
| - let's call the lifetime of this reference `'1`
12 | match self.inner.next_str() {
| ---------- first mutable borrow occurs here
...
15 | Some(txt)
| --------- returning this value requires that `self.inner` is borrowed for `'1`
...
18 | _ => self.next_str()
| ^^^^ second mutable borrow occurs here
What surprises me is that I don't see how this is borrowing self
twice. Either we return in line 15, or we return in line 18, so only one of the two will ever happen. My assumption is that this is nor a real problem, but one of these cases were the borrow-checker is not smart enough. Am I missing something?
Assuming I am right, I managed to circumvent this error using an unsafe
block (see the commented-out line 16) by artificially "breaking" the lifetime dependency. Can anyone see a better way (i.e. without any unsafe
block) to make this code compile?