This works:
let fut = Arc::new(Mutex::new(Box::pin(async { 1 })));
let mut conn_futures = BTreeMap::new(); // implicitly typed
conn_futures.insert(123, fut);
if let Some(fut) = conn_futures.get_mut(&123) {
let fut = fut.clone();
self.pool.spawn(async move {
let mut fut = fut.try_lock().unwrap();
(&mut *fut).await;
});
};
How do I write the same thing inside a structure; what is the type of conn_futures
? According to the compiler, it's BTreeMap<i32, impl Future>
, but there's no way to write that in a structure:
struct Foo {
conn_futures: BTreeMap<i32, impl Future>, // impl not allow in this position
}
I tried this:
use futures::{executor::LocalPool, lock::Mutex, task::SpawnExt, Future}; // 0.3.1
use std::{collections::BTreeMap, pin::Pin, sync::Arc};
struct Foo {
conn_futures: BTreeMap<i32, Arc<Mutex<Pin<Box<dyn Future<Output = i32>>>>>>,
}
fn alternative() {
let mut pool = LocalPool::new();
let spawner = pool.spawner();
// Have a structure with the btreemap instead
let mut foo = Foo {
conn_futures: BTreeMap::new(),
};
let fut = Arc::new(Mutex::new(Box::pin(async { 1 })));
foo.conn_futures.insert(123, fut);
if let Some(fut) = foo.conn_futures.get_mut(&123) {
let fut = fut.clone();
spawner.spawn(async move {
let mut fut = fut.try_lock().unwrap();
(&mut *fut).await;
});
};
}
fn main() {
let mut pool = LocalPool::new();
let spawner = pool.spawner();
let fut = Arc::new(Mutex::new(Box::pin(async { 1 })));
let mut conn_futures = BTreeMap::new(); // implicitly typed
conn_futures.insert(123, fut);
if let Some(fut) = conn_futures.get_mut(&123) {
let fut = fut.clone();
spawner.spawn(async move {
let mut fut = fut.try_lock().unwrap();
(&mut *fut).await;
});
};
}
And got an error
error[E0308]: mismatched types
--> src/main.rs:17:34
|
17 | foo.conn_futures.insert(123, fut);
| ^^^ expected trait core::future::future::Future, found opaque type
|
= note: expected type `std::sync::Arc<futures_util::lock::mutex::Mutex<std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = i32> + 'static)>>>>`
found type `std::sync::Arc<futures_util::lock::mutex::Mutex<std::pin::Pin<std::boxed::Box<impl core::future::future::Future>>>>`
How do I declare the type of conn_futures
in a struct?
impl
just means "any type that implements this trait". To store it in a struct or enum, you have 3 options: 1) make the stuct generic, e.g.struct Foo<T: Future>
, 2) use the concrete type that implements the trait, 3) use a trait object, e.g.Box<dyn Future>
– ApieceFuture
option (2) doesn't work if the future is from an async block. But option (3) works. Just cast the result ofBox::pin
toPin<Box<dyn Future<Output = i32>>>
– Apiece