Recursion
在内部,async fn
创建一个状态机类型,它包含每个子-Future
,且都正处于.await
ed。这使得递归async fn
有点棘手,因状态机类型的结果必须包含自身:
#![allow(unused_variables)] fn main() { // 这个函数: async fn foo() { step_one().await; step_two().await; } // 生成了一个类型,如下: enum Foo { First(StepOne), Second(StepTwo), } // 所以,这个函数: async fn recursive() { recursive().await; recursive().await; } // 就生成了一个类型,如下: enum Recursive { First(Recursive), Second(Recursive), } }
这行不通——我们创建了一个无限大的类型!编译器会抱怨:
error[E0733]: recursion in an `async fn` requires boxing
--> src/lib.rs:1:22
|
1 | async fn recursive() {
| ^ an `async fn` cannot invoke itself directly
|
= note: a recursive `async fn` must be rewritten to return a boxed future.
为了搞定这一点,我们必须用Box
剑走偏锋。但不幸的是,编译器的局限性意味着,仅将对recursive()
的 call 包裹进Box::pin
,是还不够的,我们必须将recursive
变成非async
函数,且它返回一个.boxed()
async
代码块:
#![allow(unused_variables)] fn main() { use futures::future::{BoxFuture, FutureExt}; fn recursive() -> BoxFuture<'static, ()> { async move { recursive().await; recursive().await; }.boxed() } }