Async: Async Vs Awaitable

A common question is why the async keyword is needed for functions that return Awaitable. The keyword is required because it is possible to have non-async functions that return awaitables - the async keyword is merely an implementation detail. For this reason, async is not allowed in interfaces. For example:

<?hh

namespace HHVM\UserDocumentation\Async\Examples\AsyncVsAwaitables;

interface Car {
  // It doesn't matter to the caller how this is implemented, only that it
  // returns an Awaitable<void>
  public function drive(): Awaitable<void>;
}

This can be implemented with an async function:

<?hh

namespace HHVM\UserDocumentation\Async\Examples\AsyncVsAwaitables;

class Ford implements Car {
  public async function drive(): Awaitable<void> {
    // ...
  }
}

It can also be implemented by a non-async function:

<?hh

namespace HHVM\UserDocumentation\Async\Examples\AsyncVsAwaitables;

class VolkswagenDiesel implements Car {
  public function drive(): Awaitable<void> {
    $being_tested = class_exists(
      \PHPUnit_Framework_TestCase::class,
      /* autoload = */ false,
    );

    // As these two functions return Awaitable<void>, we can just pass along
    // their Awaitables.
    if ($being_tested) {
      return $this->driveWithCleanEmissions();
    }
    return $this->driveNormally();
  }

  private async function driveWithCleanEmissions(): Awaitable<void> {
    // ...
  }

  private async function driveNormally(): Awaitable<void> {
    // ...
  }
}