Skip to content

Improve Rust ergonomics for wasip3 async main functions #110

@wingo

Description

@wingo

It would be nice to write this kind of program:

extern crate wasi;

async fn main() {
    let one_millisecond = 1_000_000u64;
    wasi::clocks::monotonic_clock::wait_for(one_millisecond).await
}

However, there are a number of things that get in the way. Right now you need something like:

extern crate wit_bindgen;

wit_bindgen::generate!({
    inline: r"
  package test:test;

  world test {
      include wasi:clocks/imports@0.3.0-rc-2025-08-15;
      include wasi:cli/command@0.3.0-rc-2025-08-15;
  }
",
    // Work around https://github.com/bytecodealliance/wasm-tools/issues/2285.
    features:["clocks-timezone"],
    async: [
        "wasi:cli/run@0.3.0-rc-2025-08-15#run",
    ],
    generate_all
});

struct Component;
export!(Component);

impl exports::wasi::cli::run::Guest for Component {
    async fn run() -> Result<(), ()> {
        wasi::clocks::monotonic_clock::wait_for(one_millisecond).await
        Ok(())
    }
}

fn main() { unreachable!("main is a stub"); }

Which:

  1. It's weird to have the stub main function
  2. It would be nice to have the same impl std::process::Termination setup for run so we don't have to OK(())
  3. Would be nice to have the wasi::cli::run::Guest implementation produced automatically and just call the async fn main()
  4. Would be nice to avoid having to explicitly declare wasi:cli/run as async when defining async fn main()

Alex mentioned that something like this might be possible, and it seems 95% of the way there:

#[wit_bindgen::async]
async fn main() {}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions