mq7*_*mq7 6 rust async-await rust-tokio
我想在 trait 中编写异步函数,但由于async fn尚不支持 in trait,我试图找到等效的方法接口。这是我每晚在 Rust 中尝试过的(2019-01-01):
#![feature(await_macro, async_await, futures_api)]
#[macro_use]
extern crate tokio;
use tokio::prelude::*;
trait T {
async fn f();
}
fn main() {
}
Run Code Online (Sandbox Code Playgroud)
error[E0706]: trait fns cannot be declared `async`
--> src/main.rs:7:5
|
7 | async fn f();
| ^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
我在某处读到async只是impl Future.
trait T {
fn f() -> impl futures::Future<Item = (), Error = ()>;
}
Run Code Online (Sandbox Code Playgroud)
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/lib.rs:2:15
|
2 | fn f() -> impl futures::Future<Item = (), Error = ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
impl trait不允许直接返回,所以我尝试了一个boxed trait:
trait Resource {
fn loaded(&self) -> bool;
fn init(&mut self, auth: &str) -> Box<dyn std::future::Future<Output=()>>;
fn prepare(&mut self, auth: &str) -> Box<dyn std::future::Future<Output=()>> {
Box::new(async {
if !self.loaded() {
await!(*(self.init(auth)));
}
})
}
}
Run Code Online (Sandbox Code Playgroud)
[rustc] the size for values of type `dyn std::future::Future<Output=()>` cannot be known at compilation time
Run Code Online (Sandbox Code Playgroud)
没有 deref,我得到不into_awaitable存在的错误Box<>.
我可以使用非尺码impl Future或*Box<Future>搭配await!吗?trait 中最适合异步函数的接口是什么?
特征中既不允许async使用功能,也impl Trait不允许使用。您可以使用关联类型来更接近。以下是一些想法:
pub trait ResourceTrait {
type FutType: Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::Next;
}
Run Code Online (Sandbox Code Playgroud)
目前实现这一点有点棘手,因为一些所需的工具要么尚不可用,要么不稳定,要么有缺陷。
它可以实现为:
impl ResourceTrait for Resource {
type FutType = FutureObj<'static, ()>;
fn prepare(&mut self, auth: &str) -> FutureObj<'static, ()> {
FutureObj::new(Box::new(
async move {
// Do async things
// You might get a lifetime issue here if trying to access auth,
// since it's borrowed.
}
))
}
}
Run Code Online (Sandbox Code Playgroud)
存在类型的替代方案可能是:
impl ResourceTrait for Resource {
// this is required since the real type of the async function
// is unnameable
existential type FutType = Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::FutType {
async move {
// Do async things. Might still encounter the same borrowing issues,
// since the lifetime of the returned Future isn't coupled to the
// lifetime of self.
// The workaround is to make copies of all required fields and move
// them into the Future
}
}
}
Run Code Online (Sandbox Code Playgroud)
这可能有效,也可能无效(因为该功能正在开发中)。为了正确借用像selforauth在返回的 future 中的参数,我们可能还需要首先使用通用关联类型。
为了解决 的借用问题self,您也许可以定义
pub trait ResourceTrait {
type FutType: Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::Next;
}
Run Code Online (Sandbox Code Playgroud)
这样您就可以复制inner并将prepare其移动到Future.