Reputation: 44807
The loop:
impl State {
pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)> {
vec!()
}
}
fn main_loop(mut state: State) {
let mut packets = Vec::<(&[u8], SocketAddr)>::new();
loop {
let new = state.exec();
packets.extend(new);
}
}
gives the error:
error[E0499]: cannot borrow `state` as mutable more than once at a time
--> src/main.rs:93:14
|
93 | let new = state.exec();
| ^^^^^ `state` was mutably borrowed here in the previous iteration of the loop
Yet if I comment-out the packets.extend(new);
line, there is no error.
I think the problem is that the returned vector is owned by state
, as if new
is dropped before the loop iterates, it's fine. I'm happy for the returned vector to be copied, if this would fix it.
I expected that adding .clone()
to either new
or state.exec()
would have fixed it, but it doesn't.
Is there a simple way of fixing this?
Or do I need to structure single-threaded application state in a different way?
Upvotes: 1
Views: 2290
Reputation: 44807
One solution is:
impl State {
pub fn exec(&mut self) -> Vec<(Vec<u8>, SocketAddr)> {
vec!()
}
}
fn main_loop(mut state: State) {
let mut packets = Vec::<(Vec<u8>, SocketAddr)>::new();
loop {
let new = state.exec();
packets.extend(new);
}
}
I'm not sure that this is the best solution, so I'll leave the question open for a while.
Upvotes: 1
Reputation: 28025
Just changing the function signature so that the returned &[u8]
does not borrow from *self
will allow the example code to compile:
pub fn exec<'a>(&mut self) -> Vec<(&'a [u8], SocketAddr)> {
vec![]
}
Note that 'a
is a free lifetime parameter, so the caller can supply anything there (including 'static
) and whatever references exec
returns will have to satisfy the caller-supplied lifetime. In practice, this means that the Vec
can only contain 'static
references, because 'static
is the only lifetime that is a subtype of every other lifetime.
It's unlikely this is what you want. However, it might be, or the [u8]
might be borrowed from some other argument (not *self
), or re-borrowed from a reference contained in *self
. This shows that simply changing the signature to more accurately represent the lifetime relationships between inputs and outputs can sometimes fix errors like this one without any other changes.
Upvotes: 2
Reputation: 70347
pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)>
Let's add in the implicit lifetimes
pub fn exec<'a>(&'a mut self) -> Vec<(&'a [u8], SocketAddr)>
So the returned slice must have the same lifetime as the mutable borrow. Now, what do you do with the returned slice?
let new = state.exec();
packets.extend(new);
We store it in packets
. So the borrow of state
must last at least at long as the type of packets
, which is the whole function. Hence, from the first iteration of the loop to the very end of the function, we can never borrow state
again, since the mutable borrow lasts until the end of the function.
The first question to ask yourself is: do you really need a mutable borrow? If you can get down to &self
, then do that and your problem is solved. Otherwise, you'll need to restructure things somehow. The type &[u8]
is inherently unowned. It's a reference to someone else's data. If the only way you have to get that data is through &mut self
, then you'll never be able to loop the way you want. So to clone the data, you'll need to use to_vec
, which turns &[u8]
into Vec<u8>
(your type signatures will have to change to reflect this).
Upvotes: 13