Hi folks,
I'm having a problem with some code that does work with a single type but breaks when trying to make it accept two very similar types using generics...
error[E0502]: cannot borrow `*buf` as mutable because it is also borrowed as immutable
--> src/lib.rs:30:21
|
22 | fn wait_next<'a, T>(&'a mut self, stream: &mut TcpStream) -> Result<Option<T>, std::io::Error>
| -- lifetime `'a` defined here
...
28 | match buf[..*n].try_into() {
| --------------------
| |
| immutable borrow occurs here
| argument requires that `*buf` is borrowed for `'a`
29 | Ok(InputGeneric(data, used)) => {
30 | buf.copy_within(used..*n, 0);
| ^^^ mutable borrow occurs here
error[E0502]: cannot borrow `*buf` as mutable because it is also borrowed as immutable
--> src/lib.rs:35:46
|
22 | fn wait_next<'a, T>(&'a mut self, stream: &mut TcpStream) -> Result<Option<T>, std::io::Error>
| -- lifetime `'a` defined here
...
28 | match buf[..*n].try_into() {
| --------------------
| |
| immutable borrow occurs here
| argument requires that `*buf` is borrowed for `'a`
...
35 | let x = stream.read(&mut buf[*n..])?; // read a bit more data.
| ^^^ mutable borrow occurs here
For more information about this error, try `rustc --explain E0502`.
error: could not compile `playground` (lib) due to 2 previous errors
The generic code. I think I need a 'static bound somewhere saying that the returned value does not borrow from the buf, but I've tried everywhere and couldn't make it work:
fn wait_next<'a, T>(&'a mut self, stream: &mut TcpStream) -> Result<Option<T>, std::io::Error>
where
InputGeneric<T>: TryFrom<&'a [u8]>,
{
let DataStream { buf, n, .. } = self;
loop {
match buf[..*n].try_into() {
Ok(InputGeneric(data, used)) => {
buf.copy_within(used..*n, 0);
*n -= used;
return Ok(Some(data));
}
Err(e) => {
let x = stream.read(&mut buf[*n..])?; // read a bit more data.
if x == 0 {
return Ok(None);
}
*n += x;
}
}
}
}
The non-generic code that works. Note they are identical except for the type within the Ok:
fn wait_next(&mut self, stream: &mut TcpStream) -> Result<Option<Data>, std::io::Error> {
let DataStream { buf, n, .. } = self;
loop {
match buf[..*n].try_into() {
Ok(Input(data, used)) => {
buf.copy_within(used..*n, 0);
*n -= used;
return Ok(Some(data));
}
Err(e) => {
let x = stream.read(&mut buf[*n..])?; // read a bit more data.
if x == 0 {
return Ok(None);
}
*n += x;
}
}
}
}
Here is a playground to simulate it. If you comment/uncomment both wait_next()
methods, you can see that the non-generic works and the generic doesn't.
Could you please help me? What am I missing?