Issues with mutability and futures

⚓ Rust    📅 2025-05-04    👤 surdeus    👁️ 8      

surdeus

Warning

This post was published 108 days ago. The information described in this article may have changed.

Hello,

In my application I use the etcd client API:

[dependencies]
etcd-client = "0.15.0"

This defines:

    pub async fn put(
        &mut self,
        key: impl Into<Vec<u8>>,
        value: impl Into<Vec<u8>>,
        options: Option<PutOptions>,
    ) -> Result<PutResponse> {
        self.kv.put(key, value, options).await
    }

I want to loop over a map of key/value pairs and call this method, but it complains that the client can only be borrowed mutably once.

Here is the code I wrote:

use std::vec;
use etcd_client::{Client, Error};
use std::collections::HashMap;
use futures;

async fn create_keys() -> Result<(), Error> {
    let mut dict = HashMap::new();
    dict.insert("k1", "vv1");
    dict.insert("k2", "vv2");
    dict.insert("k3", "vv3");

    let mut client = Client::connect(["localhost:2379"], None).await?;
    let mut futures = vec![];
    for (k,v) in dict.iter() {
        let fut = async {
            client.put(*k, *v, None).await;
        };
        futures.push(fut);
    }
    futures::future::join_all(futures).await;
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    create_keys().await?;
    Ok(())
}

Here is the problem description:

error[E0499]: cannot borrow `client` as mutable more than once at a time
  --> mycrate/src/main.rs:15:19
   |
15 |         let fut = async {
   |                   ^^^^^ `client` was mutably borrowed here in the previous iteration of the loop
16 |             client.put(*k, *v, None).await;
   |             ------ borrows occur due to use of `client` in coroutine
...
20 |     futures::future::join_all(futures).await;
   |                               ------- first borrow used here, in later iteration of loop

For more information about this error, try `rustc --explain E0499`.
error: could not compile `node` (bin "mycrate") due to 1 previous error

I'm not sure how to use the API to do what I need. The key-value mappings I need to populate are not known at compile time (the hashmap is actually a surrogate for reading from a file) and I am quite new to Rust even (let alone async).

1 post - 1 participant

Read full topic

🏷️ rust_feed