Cannot borrow as mutable in loop - rust

I have the following code:
pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
loop {
read_exact(buf);
if let Some(packet) = to_packet(buf) {
return packet;
}
}
}
fn read_exact(_: &mut [u8]) {
todo!()
}
fn to_packet<'a>(_: &'a [u8]) -> Option<&'a [u8]> {
todo!()
}
I get the following error:
error[E0502]: cannot borrow `*buf` as mutable because it is also borrowed as immutable
--> src/lib.rs:3:9
|
1 | pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
| -- lifetime `'a` defined here
2 | loop {
3 | read_exact(buf);
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
4 |
5 | if let Some(packet) = to_packet(buf) {
| --- immutable borrow occurs here
6 | return packet;
| ------ returning this value requires that `*buf` is borrowed for `'a`
I think it should work because:
The mutable borrow in read_exact completes on line 3.
If to_packet returns Some then the value is returned to the caller.
If not, the immutable borrow of to_packet is over at the end of the loop. So it is free to be taken mutable borrow of in the next iteration.
Can somebody please let me know why this doesn't work?
EDIT:
It seems like a current borrow checker limitation. I tried using Polonius in the nightly and it works fine with
RUSTFLAGS=-Zpolonius cargo +nightly check

It is a compiler limitation atm.
You could refactor to something like:
pub fn read_packet<'a>(buf: &'a mut [u8]) {
loop {
if read_exact(buf) {
break;
}
}
}
fn is_packet(a: &[u8]) -> bool {
true
}
fn read_exact<'a>(a: &'a mut [u8]) -> bool {
is_packet(a)
}
fn to_packet<'a>(_: &'a [u8]) -> Option<&'a [u8]> {
todo!()
}
fn process_packet<'a>(buf: &'a mut [u8]) {
read_packet(buf);
let _packet = to_packet(buf);
}
Playground

pub fn read_packet<'a>(buffer: &'a mut [u8]) -> &'a [u8] { |
let buf = buffer; |
loop { |
read_exact(buf); \/
if let Some(packet) = to_packet(buf) { 'a _
return packet; |
} |
} |
}
fn read_exact(_: &mut [u8]) {
todo!()
}
fn to_packet<'b>(_from: &'b [u8]) -> Option<&'b [u8]> {
todo!()
}
Compile error:
|
1 | pub fn read_packet<'a>(buffer: &'a mut [u8]) -> &'a [u8] {
| -- lifetime `'a` defined here
...
4 | read_exact(buf);
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
5 | if let Some(packet) = to_packet(buf) {
| --- immutable borrow occurs here
6 | return packet;
| ------ returning this value requires that `*buf` is borrowed for `'a`
With Non Lexical Lifetime (NLL):
The return statement constrains the packet lifetime to be 'a.
If packet is 'a, so buf (to_packet) has to be also 'a.
'a is valid for the entire function. The loop makes the shared reference lifetime conflicts with the exclusive reference lifetime at the next iteration.
The conflict can be reproduced without the loop. This snippet doesn't compile for the same reason that buff is 'a. And we see that the root cause is the conditional return. Again 'a has to be valid for the entire function.
pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
if let Some(packet) = to_packet(buf) { 'a _
return packet; |
} |
read_exact(buf); |
return &[0]; \/
}
fn read_exact(_: &mut [u8]) {
todo!()
}
fn to_packet<'b>(_: &'b [u8]) -> Option<&'b [u8]> {
todo!()
}
Compile error:
|
1 | pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
| -- lifetime `'a` defined here
2 | if let Some(packet) = to_packet(buf) {
| --- immutable borrow occurs here
3 | return packet;
| ------ returning this value requires that `*buf` is borrowed for `'a`
4 | }
5 | read_exact(buf);
| ^^^^^^^^^^^^^^^ mutable borrow occurs here
With NLL, the lifetime is infered like you thought it would be.
pub fn read_packet<'a>(buffer: &'a mut [u8]) -> &'a [u8] {
let buf = buffer;
loop {
read_exact(buf);
if let Some(packet) = to_packet(buf) { 'x _
return packet; |
} \/
}
}
fn read_exact(_: &mut [u8]) {
todo!()
}
fn to_packet<'b>(_from: &'b [u8]) -> Option<&'b [u8]> {
todo!()
}

Related

`*buf` was mutably borrowed here in the previous iteration of the loop?

This code:
pub struct Event<'a> {
_p: std::marker::PhantomData<&'a ()>,
}
pub fn foo<'a>(_buf: &'a mut Vec<u8>) -> Event<'a> {
todo!()
}
pub fn bar<'a>(buf: &'a mut Vec<u8>, event: &'a mut Event<'a>) {
loop {
*event = foo(buf);
}
}
Compile error:
error[E0499]: cannot borrow `*buf` as mutable more than once at a time
--> src/lib.rs:11:22
|
9 | pub fn bar<'a>(buf: &'a mut Vec<u8>, event: &'a mut Event<'a>) {
| -- lifetime `'a` defined here
10 | loop {
11 | *event = foo(buf);
| ----^^^-
| | |
| | `*buf` was mutably borrowed here in the previous iteration of the loop
| argument requires that `*buf` is borrowed for `'a`
For more information about this error, try `rustc --explain E0499`.
But remove the loop, the code will be passed, I want to know why to fix this compile error.
In the example you give, the compiler error is correct in terms of safety. In the first iteration, the buffer is passed into Event and then stored in *event. The next iteration cannot loan the buffer to as it is still owned by *event.
If however Event doesn't actually reference the buffer after the fact, you can introduce a new lifetime to show that:
pub struct Event<'a> {
_p: std::marker::PhantomData<&'a ()>,
}
pub fn foo<'a, 'b>(_buf: &'a mut Vec<u8>) -> Event<'b> {
todo!()
}
pub fn bar<'a>(buf: &'a mut Vec<u8>, event: &'a mut Event<'a>) {
loop {
*event = foo(buf);
}
}

Multiple mutable borrows in Rust

I'm playing around with building a very simple stack based evaluator in Rust. I want the user to be able to define functions later, so I'm storing all operators in a HashMap with closures as values.
use std::collections::HashMap;
pub type Value = i32;
pub struct Evaluator<'a> {
stack: Vec<Value>,
ops: HashMap<String, &'a dyn FnMut(&'a mut Vec<Value>)>,
}
impl<'a> Evaluator<'a> {
pub fn new() -> Evaluator<'a> {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, &'a dyn FnMut(&'a mut Vec<Value>)> = HashMap::new();
ops.insert("+".to_string(), &|stack: &'a mut Vec<Value>| {
if let (Some(x), Some(y)) = (stack.pop(), stack.pop()) {
stack.push(y + x);
}
});
Evaluator { stack, ops }
}
pub fn stack(&self) -> &[Value] {
&self.stack
}
pub fn eval(&'a mut self, input: &str) {
let symbols = input
.split_ascii_whitespace()
.collect::<Vec<_>>();
for sym in symbols {
if let Ok(n) = sym.parse::<i32>() {
self.stack.push(n);
} else {
let s = sym.to_ascii_lowercase();
if let Some(f) = self.ops.get(&s) {
f(&mut self.stack);
} else {
println!("error");
}
}
}
}
}
fn main() {
let mut e = Evaluator::new();
e.eval("1 2 +")
}
I'm currently getting two errors:
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time
--> src/sample.rs:34:17
|
10 | impl<'a> Evaluator<'a> {
| -- lifetime `'a` defined here
...
34 | self.stack.push(n);
| ^^^^^^^^^^ second mutable borrow occurs here
...
38 | f(&mut self.stack);
| ------------------
| | |
| | first mutable borrow occurs here
| argument requires that `self.stack` is borrowed for `'a`
error[E0596]: cannot borrow `**f` as mutable, as it is behind a `&` reference
--> src/sample.rs:38:21
|
38 | f(&mut self.stack);
| ^ cannot borrow as mutable
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time
--> src/sample.rs:38:23
|
10 | impl<'a> Evaluator<'a> {
| -- lifetime `'a` defined here
...
38 | f(&mut self.stack);
| --^^^^^^^^^^^^^^^-
| | |
| | `self.stack` was mutably borrowed here in the previous iteration of the loop
| argument requires that `self.stack` is borrowed for `'a`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0499, E0596.
For more information about an error, try `rustc --explain E0499`.
My concern is the first one. I'm not sure what I'm doing wrong as I'm not borrowing them at the same time. Can I tell Rust the previous borrow (self.stack.pop()) is done? Any help appreciated.
I think I solved my problem. The thing I kept coming back to is, "What owns the closures?" In this case I'm using references, but nothing is taking ownership of the data. When I refactored (below) with Box to take ownership, it worked.
I'm curious if there is a way to do this with with just references and/or if my explanation is wrong?
Working code:
use std::collections::HashMap;
pub type Value = i32;
pub struct Evaluator {
stack: Vec<Value>,
ops: HashMap<String, Box<dyn FnMut(&mut Vec<Value>)>>,
}
impl Evaluator {
pub fn new() -> Evaluator {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, Box<dyn FnMut(&mut Vec<Value>)>> = HashMap::new();
ops.insert("+".to_string(), Box::new(|stack: &mut Vec<Value>| {
if let (Some(x), Some(y)) = (stack.pop(), stack.pop()) {
stack.push(y + x);
}
}));
Evaluator { stack, ops }
}
pub fn stack(&self) -> &[Value] {
&self.stack
}
pub fn eval(&mut self, input: &str) {
let symbols = input
.split_ascii_whitespace()
.collect::<Vec<_>>();
for sym in symbols {
if let Ok(n) = sym.parse::<i32>() {
self.stack.push(n);
} else {
let s = sym.to_ascii_lowercase();
if let Some(f) = self.ops.get_mut(&s) {
f(&mut self.stack);
} else {
println!("error");
}
}
}
}
}
fn main() {
let mut e = Evaluator::new();
e.eval("1 2 +")
}
You have borrows with conflicting lifetimes:
You are defining a lifetime 'a for the struct in line 5: pub struct Evaluator<'a> {
In line 7, you are stating that ops is a HashMap that holds functions that receive mutable borrows for the whole duration of 'a
Then, in line 28, you are defining an eval method that holds a mutable reference to self for the whole duration of the struct ('a)
The conflict can be solved if you use two different lifetimes, since the time that an operation borrows self should be inherently shorter than the lifetime for the whole evaluation, since in eval you are running a loop and multiple invocations to the operations.
This should fix the issues mentioned above:
pub struct Evaluator<'a, 'b> {
stack: Vec<Value>,
ops: HashMap<String, &'b dyn FnMut(&'b mut Vec<Value>)>,
}
impl<'a, 'b> Evaluator<'a, 'b> {
pub fn new() -> Evaluator<'a> {
let stack: Vec<Value> = vec![];
let mut ops: HashMap<String, &'b dyn FnMut(&'b mut Vec<Value>)> = HashMap::new();

Rust: how to bound the lifetime of Iterator::next()?

The following code doesn't compile:
struct Things {
things: Vec<usize>
}
struct ThingsIterMut<'a> {
contents: &'a mut Vec<usize>,
indices: std::slice::Iter<'a, usize>
}
impl<'a> Iterator for ThingsIterMut<'a> {
type Item = &'a mut usize;
fn next(&mut self) -> Option<Self::Item> {
match self.indices.next() {
None => None,
Some(i) => self.contents.get_mut(*i)
}
}
}
impl Things {
pub fn iter_mut<'a>(&'a mut self) -> ThingsIterMut<'a> {
ThingsIterMut {
contents: &mut self.things,
indices: self.things.iter()
}
}
}
fn main() {
println!("Hello, world!");
}
It complains:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:16:24
|
16 | Some(i) => self.contents.get_mut(*i)
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 13:5...
--> src/main.rs:13:5
|
13 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:16:24
|
16 | Some(i) => self.contents.get_mut(*i)
| ^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 10:6...
--> src/main.rs:10:6
|
10 | impl<'a> Iterator for ThingsIterMut<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:13:46
|
13 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
14 | | match self.indices.next() {
15 | | None => None,
16 | | Some(i) => self.contents.get_mut(*i)
17 | | }
18 | | }
| |_____^
= note: expected `std::iter::Iterator`
found `std::iter::Iterator`
Changing next to next(&'a mut self) dose not work (signature mismatch), neither does change self.contents.get_mut() to self.contents.get_mut::<'a>().
What's the correct way to address this issue?
I see two problems. The first is that your iter_mut function tries to return both a mutable and an immutable reference to self.things.
It is easier to see why the borrow checker doesn't allow this by simplifying it:
fn main() {
let mut things = vec![1, 2, 3];
let contents = &mut things;
let indices = things.iter(); // borrows self_things immutably
let things_iter_mut = (contents, indices);
}
The second problem that you are trying to return a longer reference than you pass into the next function.
struct Things<'things> {
contents: &'things mut Vec<usize>,
}
impl<'things> Things<'things> {
// This won't compile! The 'borrow lifetime is implied.
// But here you can see that the borrow might be shorter than
// what we are returning.
fn next(&'borrow mut self) -> &'things mut Vec<usize> {
self.contents
}
// This will compile. Because the returned reference lives
// just as long as the argument.
fn next(&'things mut self) -> &'things mut Vec<usize> {
self.contents
}
}

Nested async function call causes lifetime issue

I feel like I am totally lost; what does "'1" mean in the error message?
error[E0597]: `o` does not live long enough
--> src/main.rs:32:19
|
31 | async fn foo6(&mut self, mut o: &'a mut Outer) {
| --------- lifetime `'1` appears in the type of `self`
32 | self.foo5(&mut o).await
| ----------^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `o` is borrowed for `'1`
33 | }
| - `o` dropped here while still borrowed
What can I do to make o live long enough? I think I'm using futures 03.
use futures::future::BoxFuture;
use futures::FutureExt;
use futures::stream::FuturesOrdered;
struct Inner {}
impl Inner {
async fn foo3(&mut self) -> Result<u32, ()> {
Ok(8)
}
}
// --- 1
struct Outer {
i: Inner,
}
impl Outer {
fn foo4(&mut self) -> BoxFuture<'_, Result<u32, ()>> {
self.i.foo3().boxed()
}
}
/// --- 2
struct Outer2<'a> {
futures_list: FuturesOrdered<BoxFuture<'a, Result<u32, ()>>>,
}
impl <'a> Outer2<'a> {
async fn foo6(&mut self, mut o: &'a mut Outer) {
self.foo5(&mut o).await
}
async fn foo5(&mut self, o: &'a mut Outer) {
self.futures_list.push(o.foo4());
}
}
#[tokio::main]
async fn main() {
let mut o = Outer { i: Inner {} };
let mut o2 = Outer2 { futures_list: FuturesOrdered::new() };
o2.foo5(&mut o).await;
}
playground
The '1 represents the anonymous lifetime of the self parameter for function foo5.
Note that in foo6, o is already a mutable reference to Outer, so writing &mut o actually gives you a mutable reference to a mutable reference to Outer with one too many indirections. You can fix your code by removing the extra reference:
async fn foo6(&mut self, mut o: &'a mut Outer) {
self.foo5(o).await
}
Playground

How do I fix a lifetime issue when returning an iterator of all combinations between a newly received value and cached values?

I am trying to return an iterator of all combinations between a newly received value and cached values, but I got a lifetime issue.
use std::collections::HashMap;
pub struct Status {
// <i,Vec<u>>
old: HashMap<usize, Vec<usize>>,
}
impl<'a> Status {
pub fn new() -> Self {
Status {
old: HashMap::new(),
}
}
pub fn gen(&mut self, u: usize, i: usize) -> UserPairIter<'a> {
let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
UserPairIter::new(entry, u)
}
}
struct UserPairIter<'a> {
data: &'a mut Vec<usize>,
u: usize,
index: usize,
}
impl<'a> UserPairIter<'a> {
pub fn new(data: &'a mut Vec<usize>, u: usize) -> Self {
UserPairIter { data, u, index: 0 }
}
}
impl<'a> Iterator for UserPairIter<'a> {
type Item = (usize, usize);
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.data.len() {
self.data.push(self.u);
return None;
}
let result = (self.u, self.data[self.index]);
self.index += 1;
Some(result)
}
}
fn main() {}
When I compile, I get the following error message:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:16:50
|
16 | let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
| ^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn gen(&mut self, u: usize, i: usize) -> UserPairIter<'a> {
16 | | let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
17 | | UserPairIter::new(entry, u)
18 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:16:41
|
16 | let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
| ^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 8:1...
--> src/main.rs:8:1
|
8 | / impl<'a> Status {
9 | | pub fn new() -> Self {
10 | | Status {
11 | | old: HashMap::new(),
... |
18 | | }
19 | | }
| |_^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:16:41
|
16 | let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
First of all, do not put the lifetime generic in Status. If you need genericity in a function, put this parameter in function:
impl Status {
pub fn new() -> Self {
Status {
old: HashMap::new(),
}
}
pub fn gen<'a>(&mut self, u: usize, i: usize) -> UserPairIter<'a> {
let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
UserPairIter::new(entry, u)
}
}
Then the compiler says that it cannot infer a lifetime for self.old. Just give it the hint with &'a mut self so that the compiler understands that the lifetime of the UserPairIter is the same as the lifetime of Status:
impl Status {
pub fn new() -> Self {
Status {
old: HashMap::new(),
}
}
pub fn gen<'a>(&'a mut self, u: usize, i: usize) -> UserPairIter<'a> {
let entry: &'a mut Vec<usize> = self.old.entry(i).or_insert(Vec::new());
UserPairIter::new(entry, u)
}
}
And that is ok!
You do not need to say the type of entry, the compiler can infer it with the function signature:
pub fn gen<'a>(&'a mut self, u: usize, i: usize) -> UserPairIter<'a> {
let entry = self.old.entry(i).or_insert(Vec::new());
UserPairIter::new(entry, u)
}

Resources