Another "distinct uses of `impl Trait` result in different opaque types"

Hi,

I've read Error: distinct uses of `impl Trait` result in different opaque types - #12 by CAD97

but it doesn't help me in my case because the result type is also an impl Trait:

// in main
warp::path("endpoint").and(warp::query()).and_then(
        move |params: HashMap<String, String>| {
            async move {
                endpoint(params)
                    .await
                    .map_err(warp::reject::custom::<error::ServerError>)
            }
        },
    );

// src/api/endpoint.rs

async fn endpoint(params: HashMap<String, String>) -> anyhow::Result<impl warp::reply::Reply> {
    if some_condition() {
        call_a(params).await
    } else {
        call_b(params).await
    }
}

async fn call_a(params: HashMap<String, String>) -> anyhow::Result<impl warp::reply::Reply> {
    todo!()
}

async fn call_b(params: HashMap<String, String>) -> anyhow::Result<impl warp::reply::Reply> {
    todo!()
}
error[E0308]: mismatched types
   --> src/api/endpoint.rs:61:9
    |
61  |         call_b(params).await
    |         ^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
...
71  | async fn call_b(params: HashMap<String, String>) -> Result<impl Reply> {
    |                                                            ---------- the found opaque type
...
113 | async fn call_a(params: HashMap<String, String>) -> Result<impl Reply> {
    |                                                            ---------- the expected opaque type
    |
    = note: expected enum `std::result::Result<impl warp::Reply, _>` (opaque type at <src/api/endpoint.rs:113:81>)
               found enum `std::result::Result<impl warp::Reply, _>` (opaque type at <src/api/endpoint.rs:71:70>)
    = note: distinct uses of `impl Trait` result in different opaque types

I've wrap my call_a and call_b in Either's variant since:

async fn endpoint(params: HashMap<String, String>) -> anyhow::Result<impl warp::reply::Reply> {
    let fut = if some_condition() {
        Either::Left(call_a(params))
    } else {
        Either::Right(call_b(params))
    };

   fut.await
}

but it was complaining on the impl Reply and not (yet) on the impl Future, it didn't help.

What's the trick in my case?

Thanks

async fn endpoint(params: HashMap<String, String>) -> anyhow::Result<impl warp::reply::Reply> {
    if some_condition() {
        Ok(Either::Left(call_a(params).await?))
    } else {
        Ok(Either::Right(call_b(params).await?))
    }
}
1 Like

Could you file a ticket with this case? We already attempt to push you in the right direction in simple cases and it would be appropriate to detect more complex cases.

2 Likes

Done: Opaque error message for opaque type · Issue #93519 · rust-lang/rust · GitHub

1 Like

Thanks for your answer Alice!

unfortunately:

error[E0277]: the trait bound `futures::future::Either<impl warp::Reply, _>: warp::Reply` is not satisfied
  --> src/api/endpoint.rs:26:6
   |
26 | ) -> Result<impl Reply> {
   |      ^^^^^^^^^^^^^^^^^^ the trait `warp::Reply` is not implemented for `futures::future::Either<impl warp::Reply, _>`

You'll need to find another Either enum that implements the Reply trait and use that instead. (or write your own enum)

Discord gives the answer :slight_smile:
no need for Either, just add .map(Reply::into_response) to each call :slight_smile:

thank you again!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.