tokio-rs/axum

Handler trait bound not satisfied when two functions that return Result<(), Box<dyn std::error::Error>> are called in a handler function

Closed this issue · 0 comments

Bug Report

Version

axum v0.7.4
axum-core v0.4.3

Platform

Darwin Akhils-MacBook-Pro.local 23.2.0 Darwin Kernel Version 23.2.0: Wed Nov 15 21:53:18 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6000 arm64

Description

I created a handler function called test which calls two other functions which return Result<(), Box<dyn std::error::Error>>

#[tokio::main]
async fn main() {
    // initialize tracing
    tracing_subscriber::fmt::init();

    // build our application with a route
    let app = Router::new()
        .route("/", get(root))
        .route("/test", get(test));

    // run our app with hyper
    let listener = tokio::net::TcpListener::bind("127.0.0.1:9000")
        .await
        .unwrap();
    tracing::info!("listening on http://{}", listener.local_addr().unwrap());
    axum::serve(listener, app).await.unwrap();
}

async fn test() -> impl IntoResponse {
    let res1 = function1().await;
    let res2 = function2().await;
    "Hello, World!"
}

async fn function1() -> Result<(), Box<dyn std::error::Error>> {
    Ok(())
}

async fn function2() -> Result<(), Box<dyn std::error::Error>> {
    Ok(())
}

Getting the following error for the above code.

error[E0277]: the trait bound `fn() -> impl Future<Output = impl IntoResponse> {test}: Handler<_, _>` is not satisfied
   --> src/main.rs:21:29
    |
21  |         .route("/test", get(test));
    |                         --- ^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn() -> impl Future<Output = impl IntoResponse> {test}`
    |                         |
    |                         required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S>`:
              <axum::handler::Layered<L, H, T, S> as Handler<T, S>>
              <MethodRouter<S> as Handler<(), S>>
note: required by a bound in `axum::routing::get`
   --> /Users/akhil/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.7.4/src/routing/method_routing.rs:385:1
    |
385 | top_level_handler_fn!(get, GET);
    | ^^^^^^^^^^^^^^^^^^^^^^---^^^^^^
    | |                     |
    | |                     required by a bound in this function
    | required by this bound in `get`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

There is no issue when I use only one function (and comment the other) and also when I use unwrap for both function calls

// Works fine
async fn test() -> impl IntoResponse {
    let res1 = function1().await;
    // let res2 = function2().await;
    "Hello, World!"
}

// This works fine too!
async fn test() -> impl IntoResponse {
    let res1 = function1().await.unwrap();
    let res2 = function2().await.unwrap();
    "Hello, World!"
}

I created this issue as a bug as I didn't expect this behaviour. Please let me know if I am missing something.

Thanks in advance