Skip to main content

main

Attribute Macro main 

Source
#[main]
Expand description

The async entry-point attribute (see the crate-level docs). Wraps async fn main in a tokio runtime. Turns async fn main() into a synchronous entry point that runs on a multi-threaded Tokio runtime.

Apply this attribute to your application’s main function in place of #[tokio::main]. The attribute:

  1. Verifies that the annotated function is async. A compile error is emitted if it is not.
  2. Removes the async keyword so the result is a valid synchronous fn main that the Rust runtime can call directly.
  3. Wraps the original function body in a call to tokio::runtime::Builder::new_multi_thread().enable_all().build() and then blocks on the async body with block_on.

§Constraints

  • The annotated function must be async. Applying the attribute to a non-async function is a hard compile error:

    error: #[churust::main] requires an `async fn`
  • tokio must be a dependency (directly or transitively) of the crate that uses this attribute, because the expanded code references ::tokio::runtime::Builder.

§Return type

The return type is preserved unchanged. Returning std::io::Result<()> is idiomatic because Churust::server().start().await returns that type:

#[churust::main]
async fn main() -> std::io::Result<()> {
    Ok(())
}

Returning () is also valid when no top-level I/O error needs to be propagated:

#[churust::main]
async fn main() {
    // fire-and-forget setup, panics on failure
}

§Attribute arguments

No arguments are accepted. The attribute token stream is intentionally ignored so that the macro does not trap future extensions, but passing any tokens currently has no effect.

§Generated code

Given the following input:

#[churust::main]
async fn main() -> std::io::Result<()> {
    do_something().await
}

The macro expands to roughly the following synchronous function. The generated runtime variable uses a mangled name (__rt) to avoid shadowing anything in the caller’s scope:

fn main() -> std::io::Result<()> {
    let __rt = ::churust::__private::tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .expect("failed to build tokio runtime");
    __rt.block_on(async move {
        do_something().await
    })
}

The runtime is reached through churust’s re-export rather than ::tokio, so an application needs only churust as a dependency.

All original attributes (e.g. #[cfg(…)], doc comments) and visibility modifiers on the original function are forwarded to the generated function unchanged.