Skip to content

cannot implement async trait that returning "impl Trait" #281

@nicholas-1vbw

Description

@nicholas-1vbw

Since rust 1.75, we are able to write functions that return impl Trait in trait.

I'd like to use it with async_trait, like below:

#[async_trait::async_trait]
pub trait X {
    type Error;
    async fn x(&self) -> Result<impl AsRef<str> + Send + Sync, Self::Error>;
}

The code upon can pass the compilation, but implementing X cannot.

struct T;
#[async_trait::async_trait]
impl X for T {
   type Error = ();
   async fn x(&self) -> Result<impl AsRef<str> + Send + Sync, Self::Error> {
      Ok("Hello World")
   }
}

Complation error:

error[E0562]: `impl Trait` is not allowed in paths
  --> scratch/src/main.rs:11:33
   |
11 |     async fn x(&self) -> Result<impl AsRef<str> + Send + Sync, Self::Error> {
   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `impl Trait` is only allowed in arguments and return types of functions and methods

error[E0562]: `impl Trait` is not allowed in the type of variable bindings
  --> scratch/src/main.rs:11:33
   |
11 |     async fn x(&self) -> Result<impl AsRef<str> + Send + Sync, Self::Error> {
   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `impl Trait` is only allowed in arguments and return types of functions and methods

After inspecting code generated by async_trait macro:

impl X for T {
    type Error = ();
    #[allow(
        elided_named_lifetimes,
        clippy::async_yields_async,
        clippy::diverging_sub_expression,
        clippy::let_unit_value,
        clippy::needless_arbitrary_self_type,
        clippy::no_effect_underscore_binding,
        clippy::shadow_same,
        clippy::type_complexity,
        clippy::type_repetition_in_bounds,
        clippy::used_underscore_binding
    )]
    fn x<'life0, 'async_trait>(
        &'life0 self,
    ) -> ::core::pin::Pin<
        Box<
            dyn ::core::future::Future<
                Output = Result<impl AsRef<str>, Self::Error>,
            > + ::core::marker::Send + 'async_trait,
        >,
    >
    where
        'life0: 'async_trait,
        Self: 'async_trait,
    {
        Box::pin(async move {
            if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<
                Result<impl AsRef<str> + Send + Sync, Self::Error>,
            > {
                #[allow(unreachable_code)] return __ret;
            }
            let __self = self;
            let __ret: Result<impl AsRef<str> + Send + Sync, Self::Error> = { Ok("Hello World") };
            #[allow(unreachable_code)] __ret
        })
    }
}

Upon inspecting the generated code by the async_trait macro, the impl Trait appears in type annotations, causing the issue. Replacing these occurrences of impl Trait with _ resolves the compilation errors.

Can the macro automatically replace all instances of impl Trait with _ to bypass this issue?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions