Recursion

在内部,async fn创建一个状态机类型,它包含每个子-Future,且都正处于.awaited。这使得递归async fn有点棘手,因状态机类型的结果必须包含自身:

  1. // 这个函数:
  2. async fn foo() {
  3. step_one().await;
  4. step_two().await;
  5. }
  6. // 生成了一个类型,如下:
  7. enum Foo {
  8. First(StepOne),
  9. Second(StepTwo),
  10. }
  11. // 所以,这个函数:
  12. async fn recursive() {
  13. recursive().await;
  14. recursive().await;
  15. }
  16. // 就生成了一个类型,如下:
  17. enum Recursive {
  18. First(Recursive),
  19. Second(Recursive),
  20. }

这行不通——我们创建了一个无限大的类型!编译器会抱怨:

  1. error[E0733]: recursion in an `async fn` requires boxing
  2. --> src/lib.rs:1:22
  3. |
  4. 1 | async fn recursive() {
  5. | ^ an `async fn` cannot invoke itself directly
  6. |
  7. = note: a recursive `async fn` must be rewritten to return a boxed future.

为了搞定这一点,我们必须用Box剑走偏锋。但不幸的是,编译器的局限性意味着,仅将对recursive()的 call 包裹进Box::pin,是还不够的,我们必须将recursive变成非async函数,且它返回一个.boxed() async代码块:

  1. {{#include ../../examples/07_05_recursion/src/lib.rs:example}}