Mismatch return type: Can I simplify return type?

I'm implementing a function that returns an instance of BasicClient from the oauth2 crate, but I'm encountering a type mismatch error.

Here's the function:

fn create_oauth_client(port: u16) -> Result<BasicClient> {
    // Unimportant code omitted

    let client = BasicClient::new(client_id)
        .set_auth_uri(auth_url)
        .set_token_uri(token_url)
        .set_redirect_uri(RedirectUrl::new(format!("http://localhost:{port}"))?);

    Ok(client)
}

However, this results in the following compilation error:

error[E0308]: mismatched types
   --> src/auth_service.rs:40:8
    |
40  |     Ok(client)
    |     -- ^^^^^^ expected `Client<StandardErrorResponse<...>, ..., ..., ..., ...>`, found `Client<StandardErrorResponse<...>, ..., ..., ..., ..., ..., ..., ..., ..., ...>`
    |     |
    |     arguments to this enum variant are incorrect
    |
    = note: expected struct `oauth2::Client<_, _, _, _, _, EndpointNotSet, _, _, _, EndpointNotSet>`
               found struct `oauth2::Client<_, _, _, _, _, EndpointSet, _, _, _, EndpointSet>`

I know if I specify the exact type of client ( Client<StandardErrorResponse<BasicErrorResponseType>, StandardTokenResponse<EmptyExtraTokenFields, BasicTokenType>, StandardTokenIntrospectionResponse<EmptyExtraTokenFields, BasicTokenType>, StandardRevocableToken, StandardErrorResponse<RevocationErrorResponseType>, EndpointSet, EndpointNotSet, EndpointNotSet, EndpointNotSet, EndpointSet>), the error goes away, but the type is quite long, which hurts readability.
Is it possible to simplify the return type?

I would define a type alias for the specific variation you are using.

type Client = oauth2::Client<StandardErrorResponse<BasicErrorResponseType>, StandardTokenResponse<EmptyExtraTokenFields, BasicTokenType>, StandardTokenIntrospectionResponse<EmptyExtraTokenFields, BasicTokenType>, StandardRevocableToken, StandardErrorResponse<RevocationErrorResponseType>, EndpointSet, EndpointNotSet, EndpointNotSet, EndpointNotSet, EndpointSet>;

fn create_oauth_client(port: u16) -> Result<Client> {
    ...
}

There are other possible solutions in other circumstances (particularly if a trait is involved) but this is the most general one, and it should be clean in the rest of your code unless you need other variations of oauth2::Client too.

2 Likes

Thank you!
I don't need other variations of oauth2::Client, so your suggestion works well.

I am asking for too much but I wonder if there's a macro or some other mechanism that eliminates the need to manually check and specify the type of a variable in the first place.

There is an experimental feature (type_alias_impl_trait) which will allow specifying a type alias as “this is a particular type that implements this trait” without writing out a full specification of the concrete type. However, that does not apply to this situation, because the actual use of oauth2::Client is not through a trait.

Broadly, you always have to give enough information to specify what you can do with the type, and the authors of oauth2::Client have decided to expose a lot of possible variations of what you can do.

2 Likes

you always have to give enough information to specify what you can do with the type , and the authors of oauth2::Client have decided to expose a lot of possible variations of what you can do.

This really makes sense to me. Thank you.