Давайте использовать это как наш Минимальный воспроизводимый пример :
async fn foo(x: u8) -> u8 {
2 * x
}
struct S {
foo: (),
}
async fn example() {
let s = S { foo };
}
Выдает ошибку:
error[E0308]: mismatched types
--> src/main.rs:10:17
|
10 | let s = S { foo };
| ^^^ expected (), found fn item
|
= note: expected type `()`
found type `fn(u8) -> impl std::future::Future {foo}`
Тип foo
являетсяуказатель на функцию, который принимает u8
и возвращает некоторый тип, реализующий черту std::future::Future
. async fn
фактически является просто синтаксическим сахаром, который преобразует -> Foo
в -> impl Future<Output = Foo>
.
Мы делаем нашу структуру универсальной и накладываем черту, привязанную к универсальному, который соответствует. В реальном коде вы, вероятно, захотите наложить ограничение на связанный тип Output
, но в этом примере это не требуется. Затем мы можем вызвать функцию, как любое другое поле вызываемого члена:
async fn foo(x: u8) -> u8 {
2 * x
}
struct S<F>
where
F: std::future::Future,
{
foo: fn(u8) -> F,
}
impl<F> S<F>
where
F: std::future::Future,
{
async fn do_thing(self) {
(self.foo)(42).await;
}
}
async fn example() {
let s = S { foo };
s.do_thing().await;
}
Чтобы быть еще более гибким, вы можете использовать другой универсальный тип для хранения замыкания вместо принудительного указания только указателя функции:
struct S<C, F>
where
C: Fn(u8) -> F,
F: std::future::Future,
{
foo: C,
}
impl<C, F> S<C, F>
where
C: Fn(u8) -> F,
F: std::future::Future,
{
async fn do_thing(self) {
(self.foo)(42).await;
}
}
См. Также: