Skip to main content

Async / Await

Zynx provides a hot-start, single-runtime async/await model.


Async Functions

Declare with async fn. Calling an async function returns a Future<T> and schedules it with the runtime.

async fn add(a: i32, b: i32) -> i32 {
return a + b;
}

Await

Use await inside an async fn to suspend until a Future<T> is ready.

async fn main() {
let value = await add(20, 22);
os.write("{value}\n");
}
  • await is only valid within async fn.
  • Error propagation remains explicit: await Future<T!> yields T!, requiring try or catch.

Cancellation

Cancellation is cooperative and applies only to error-carrying futures (Future<T!>).

async fn main() {
let fut = work();
let p = Promise<i32!> { future: fut };

_ = p.cancel(); // Request cancellation
let value = (await fut) catch 99;
}

Suspend-Safety Rules

To maintain memory safety, the following are prohibited across await points:

  • Borrows: Neither mutable nor shared borrows may live across await.
  • Defer: defer blocks cannot remain live across await.

Implementation Details

Async Main

An async fn main initializes the runtime, schedules the task, and runs the event loop until completion.

Lowering and Shapes

The compiler optimizes common async patterns (linear sequences, simple loops, condition trees). If a pattern isn't optimized, it uses a fallback lowering strategy and emits a compile-time warning.

To inspect shape detection:

zynx --dump-async-shape <file.zx>