Wie verwende ich ein asynchrones Rust-Fn, das eine Referenz als Rückruf verwendet?

10

async fnGibt einen anonymen Typ zurück, der implementiert Futurewird. Wenn wir ihn also als Rückruf verwenden möchten, müssen wir den Rückgabewert in ein Merkmalobjekt konvertieren.

Ich habe versucht, eine Funktion zu schreiben, um dies zu tun, aber ich hatte einige lebenslange Probleme.

async fngibt die Lebensdauer aller Parameter zurück, daher muss auch die Signatur des Rückrufs. Wie kann ich die Lebensdauer zum Rückgabewert des Rückrufs hinzufügen?

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
quelle
Warum erfolgt die Eingabe in normalize_async_cbeinen Funktionszeiger?
Coder-256
Was meinst du mit einem "Rückruf"? Können Sie ein Beispiel geben, das zeigt, wo Sie diese Art von Rückruf benötigen würden?
Coder-256

Antworten:

1

Rust unterstützt keinen höherwertigen Polymorphismus, daher müssen Sie dem AsyncCbTyp einen Lebensdauerparameter hinzufügen :

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

Zusätzlich können Sie ein vermeiden, Boxindem Sie das implMerkmal zurückgeben:

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
}

(Der Anrufer kann dann bei Bedarf Box::new(normalize_async_cb(…))als Typ verwenden AsyncCb.)

Anders Kaseorg
quelle