Comment utiliser un fn Rust async qui prend une référence comme rappel?

10

async fnrenvoie un type anonyme qui implémente Future, donc si nous voulons l'utiliser comme rappel, nous devons convertir la valeur de retour en objet trait.

J'ai essayé d'écrire une fonction pour ce faire, mais j'ai eu des problèmes à vie.

async fnrenverra la durée de vie de tous les paramètres, donc la signature du rappel doit également le faire. Comment puis-je ajouter la durée de vie à la valeur de retour du rappel?

use futures::future::{Future, FutureExt, LocalBoxFuture};

type Context = ();
type AsyncCb = Box<dyn for<'r> FnOnce(&'r Context) -> LocalBoxFuture<'r, ()>>;

fn normalize_async_cb<Fut: Future<Output = ()>>(f: for<'r> fn(&'r Context) -> Fut) -> AsyncCb
//                                                    how to add 'r for Fut?  ^^^
{
    let cb = move |ctx: &Context| f(ctx).boxed_local();
    Box::new(cb)
}
s97712
la source
Pourquoi l'entrée d' normalize_async_cbun pointeur de fonction?
Coder-256
Aussi, que voulez-vous dire par un "rappel"? Pouvez-vous fournir un exemple montrant où vous auriez besoin de ce type de rappel?
Coder-256

Réponses:

1

Rust ne prend pas en charge le polymorphisme de type supérieur, vous devez donc ajouter un paramètre de durée de vie au AsyncCbtype:

use futures::future::{Future, FutureExt, LocalBoxFuture};

type Context = ();
type AsyncCb<'r> = Box<dyn FnOnce(&'r Context) -> LocalBoxFuture<'r, ()> + 'r>;

fn normalize_async_cb<'r, Fut: Future<Output = ()> + 'r>(f: fn(&'r Context) -> Fut) -> AsyncCb {
    let cb = move |ctx: &'r Context| f(ctx).boxed_local();
    Box::new(cb)
}

De plus, vous pouvez éviter un Boxen retournant un impltrait:

fn normalize_async_cb<'r, Fut: Future<Output = ()> + 'r>(
    f: fn(&'r Context) -> Fut,
) -> impl FnOnce(&'r Context) -> LocalBoxFuture<'r, ()> {
    let cb = move |ctx: &'r Context| f(ctx).boxed_local();
    cb
}

(L'appelant peut ensuite utiliser Box::new(normalize_async_cb(…))comme type AsyncCbsi vous le souhaitez.)

Anders Kaseorg
la source