I am writing a concurrent interpreter using Rust and the tokio library. My current code for a recursive asynchronous function for variable substitution is as follows
fn subst_idents_in_expr_for_vals(
expr: &'static meerast::Expr,
worker_inboxes: &'static HashMap<String, mpsc::Sender<Message>>,
receiver_from_workers: &'static mut mpsc::Receiver<Message>,
) -> Pin<Box<dyn Future<Output = meerast::Expr>>> {
Box::pin(async move {
match expr {
Expr::Apply { fun, args } => {
let substed_fun =
subst_idents_in_expr_for_vals(fun, worker_inboxes, receiver_from_workers).await; // First mut borrow of `receiver_from_workers` here
let mut substed_args: Vec<meerast::Expr> = vec![];
for arg in args.iter() {
let substed_arg =
subst_idents_in_expr_for_vals(arg, worker_inboxes, receiver_from_workers)
.await; // Second mut borrow of `receiver_from_workers` here
substed_args.push(substed_arg);
}
meerast::Expr::Apply {
fun: Box::new(substed_fun),
args: substed_args,
}
}
_ => todo!(),
}
})
}
The two mutable borrows of a statically lifetimed reference indicated by the comments conflict.
I have tried to make the lifetime of the references in the parameters to be 'a
instead of 'static
. However, tokio and async Rust require that everything borrowed into an async block have to have static lifetime.
I cannot capture the ownership of the receiver_from_workers
because of the limitations of tokio.