I am trying to get some async Rust going, to allow concurrent access to a database. I understand futures need to have 'Send' implemented for all the variables that can be held whilst it is awaited, but I am specifically importing Send for the Database itself, as well as declaring it on the input type.
#[async_trait]
pub trait Database: Send {
async fn get_something(&self) -> Option<Vec<f32>>;
}
async fn calculate_something(&mut self, db: Arc<(dyn Database + Send)>, var: i16) -> Option<f32> {
let something = db.get_something(var).await;
// Do stuff with the something.
Some()
}
This gives me the error:
^ future created by async block is not `Send`
help: the trait `Sync` is not implemented for `dyn database::Database + Send`
note: captured value is not `Send`
--> src/alarms/something_calculator.rs:31:47
|
31 | async fn calculate_something(&mut self, db: Arc<(dyn Database + Send)>, var: i16) -> Option<f32> {
| ^^ has type `Arc<dyn database::Database + Send>` which is not `Send`
= note: required for the cast to the object type `dyn Future<Output = Option<f32>> + Send`
I am new to rust so I'm sure I am doing something silly, but I can't wrap my head around it not implementing Send when it is defined as a Send in its type.
Thanks in advance.
The async function requires all captured values to be Send
such that itself is Send
. For the Arc
type to be Send
its type argument must be Sync + Send
. You can write db: Arc<(dyn Database + Send + Sync)>
to make the async Future send.
It mentions this in the error message:
help: the trait `Sync` is not implemented for `dyn database::Database + Send
This change might have further consequences for your code if the db
argument is not already Sync
, but you are not providing enough context to determine that.