Work around "multiple borrows in loop" borrow checker limitation

I'm experimenting with extending a tokio based BACnet client (see here extend simple client to ignore mismatching invoke_ids by mnbbrown · Pull Request #2 · ninjasource/embedded-bacnet · GitHub for the PR)

When I build I get the following error:

> cargo build
   Compiling embedded-bacnet v0.3.0 (/Users/mnbbrown/code/embedded-bacnet)
error[E0502]: cannot borrow `*buf` as mutable because it is also borrowed as immutable
   --> src/simple/mod.rs:238:21
    |
229 |     async fn send_and_receive_complex_ack<'a>(
    |                                           -- lifetime `'a` defined here
...
238 |             let n = self.io.read(buf).await.map_err(BacnetError::Io)?;
    |                     ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
239 |             let buf = &buf[..n];
    |                        --- immutable borrow occurs here
...
250 |                 return Ok(ack)
    |                        ------- returning this value requires that `*buf` is borrowed for `'a`

For more information about this error, try `rustc --explain E0502`.
error: could not compile `embedded-bacnet` (lib) due to 1 previous error

Based on my reading of this blog post I think I'm coming up against this borrow checker limitation but I'm stuck figuring out how to work around it.

I've tried a couple of things like copy creating a new vec in every loop, but that (obvious in hindsight) didn't work because the temp allocation is being dropped.

Appreciate any tips on how I might work around this :slight_smile:

I believe the simple workarounds can’t help here because your loop mutates the 'a borrow you want to return, so there's no possibility of using only immutable references till the loop succeeds.

You need polonius-the-crab.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.