¿Cómo usar un Rust async fn que toma una referencia como devolución de llamada?

10

async fndevuelve un tipo anónimo que se implementa Future, por lo que si queremos usarlo como devolución de llamada, debemos convertir el valor de retorno en un objeto de rasgo.

Traté de escribir una función para hacer esto, pero tuve algunos problemas de por vida.

async fndevolverá la vida útil de todos los parámetros, por lo que la firma de devolución de llamada también debe hacerlo. ¿Cómo puedo agregar la vida útil al valor de retorno de la devolución de llamada?

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
fuente
¿Por qué es la entrada a normalize_async_cbun puntero de función?
Codificador-256
Además, ¿qué quieres decir con "devolución de llamada"? ¿Puede proporcionar un ejemplo que muestre dónde necesitaría este tipo de devolución de llamada?
Codificador-256

Respuestas:

1

Rust no admite polimorfismo de tipo superior, por lo que debe agregar un parámetro de por vida al AsyncCbtipo:

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)
}

Además, puede evitar un rasgo Boxdevolviendo impl:

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
}

(La persona que llama puede usar Box::new(normalize_async_cb(…))como tipo AsyncCbsi lo desea).

Anders Kaseorg
fuente