Минимальный пример:
struct Tst;
impl Tst {
async fn foo(&self) {
self.bar().boxed().await;
}
async fn bar(&self) {
self.foo().await;
}
}
В реальном коде, конечно же, и foo, и bar совершают полезную работу, а рекурсия условная, а не бесконечная.
Но ошибка одна и та же:
future cannot be sent between threads safely
future returned by `bar` is not `Send`
Note: cannot satisfy `impl futures_util::Future<Output = ()>: std::marker::Send`
Note: future is not `Send` as it awaits another future which is not `Send`
Note: required by a bound in `futures_util::FutureExt::boxed`
Ну а без .boxed() стандартная ошибка компилятора о недопустимости рекурсии без упаковки фич.
С помощью нейросетей нашёл вот такой рабочий work-around:
use futures_util::future::BoxFuture;
use futures_util::FutureExt;
struct Tst;
impl Tst {
fn foo(&'_ self) -> BoxFuture<'_, ()> {
async {
self.bar().await;
}.boxed()
}
async fn bar(&self) {
self.foo().await;
}
}
Любую одну функцию в рекурсивной цепочке переписать из async fn в обычную fn возвращающую BoxFuture. Тогда код начинает компилироваться.
Но выглядит уродливо.
Есть ли варианты лучше?




