[英]How do I store a variable of type `impl Trait` in a struct?
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
? conn_futures
的类型是conn_futures
? According to the compiler, it's BTreeMap<i32, impl Future>
, but there's no way to write that in a structure:根据编译器的BTreeMap<i32, impl Future>
,它是BTreeMap<i32, impl Future>
,但无法将其写入结构中:
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?如何在结构中声明conn_futures
的类型?
You cannot, really.你不能,真的。 impl Trait
creates an anonymous, unnameable type. impl Trait
创建一个匿名的、不可命名的类型。 That means that you cannot declare a variable with an explicit type that will work.这意味着您不能声明具有有效类型的变量。
The primary solution is to use a trait object :主要的解决方案是使用trait 对象:
use std::fmt::Display;
fn make_it() -> impl Display {
2
}
struct Example {
it: Box<dyn Display>,
}
impl Example {
fn make() -> Self {
Example {
it: Box::new(make_it()),
}
}
}
You can also avoid using an associated function and use a plain function instead, coupled with a generic:您还可以避免使用关联函数,而是使用普通函数,并结合泛型:
use std::fmt::Display;
fn make_it() -> impl Display {
2
}
struct Example<T> {
it: T,
}
impl Example<Box<dyn Display>> {
fn make() -> Self {
Example {
it: Box::new(make_it()),
}
}
}
fn make_example() -> Example<impl Display> {
Example {
it: make_it(),
}
}
If you wish to use unstable nightly features, you can use existential types (RFC 2071) :如果您希望使用不稳定的夜间功能,您可以使用存在类型(RFC 2071) :
// 1.51.0-nightly (2021-01-03 80184183ba0a53aa4f49)
#![feature(type_alias_impl_trait)]
use std::fmt::Display;
type SomeDisplay = impl Display;
fn make_it() -> SomeDisplay {
2
}
struct Example {
it: SomeDisplay,
}
impl Example {
fn make() -> Self {
Example { it: make_it() }
}
}
Or:或者:
// 1.51.0-nightly (2021-01-03 80184183ba0a53aa4f49)
#![feature(type_alias_impl_trait)]
use std::fmt::Display;
fn make_it() -> impl Display {
2
}
struct Example<T> {
it: T,
}
type SomeDisplay = impl Display;
impl Example<SomeDisplay> {
fn make() -> Self {
Example { it: make_it() }
}
}
See also:也可以看看:
Though the suggestions above are useful, the specific answer to the question is to cast the Pin<Box<Future>>>
appropriately尽管上述建议很有用,但问题的具体答案是适当地投射Pin<Box<Future>>>
This line这条线
let fut = Arc::new(Mutex::new(Box::pin(async { 1 })));
needs to change需要改变
let fut = Arc::new(Mutex::new(Box::pin(async { 1 }) as Pin<Box<Future<Output=i32>>> ));
which will allow one to express the following struct这将允许人们表达以下结构
struct Foo {
conn_futures: BTreeMap<ChannelId, Arc<Mutex<Pin<Box<dyn Future<Output = i32>>>>>>,
}
and the compiler won't complain.并且编译器不会抱怨。 Thanks @Aloso for the hint感谢@Aloso 的提示
However, the following error is given instead但是,反而给出了以下错误
error[E0277]: `(dyn core::future::future::Future<Output = i32> + 'static)` cannot be sent between threads safely
--> src/main.rs:24:16
|
24 | spawner.spawn(async move {
| ^^^^^ `(dyn core::future::future::Future<Output = i32> + 'static)` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `(dyn core::future::future::Future<Output = i32> + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn core::future::future::Future<Output = i32> + 'static)>`
= note: required because it appears within the type `std::boxed::Box<(dyn core::future::future::Future<Output = i32> + 'static)>`
= note: required because it appears within the type `std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = i32> + 'static)>>`
= note: required because of the requirements on the impl of `std::marker::Send` for `futures_util::lock::mutex::Mutex<std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = i32> + 'static)>>>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<futures_util::lock::mutex::Mutex<std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = i32> + 'static)>>>>`
= note: required because it appears within the type `[static generator@src/main.rs:24:33: 27:10 fut:std::sync::Arc<futures_util::lock::mutex::Mutex<std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = i32> + 'static)>>>> _]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@src/main.rs:24:33: 27:10 fut:std::sync::Arc<futures_util::lock::mutex::Mutex<std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = i32> + 'static)>>>> _]>`
= note: required because it appears within the type `impl core::future::future::Future`
which will be a separate question这将是一个单独的问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.