Code Monkey home page Code Monkey logo

async-trait's People

Contributors

azriel91 avatar benbrittain avatar c410-f3r avatar compiler-errors avatar de-vri-es avatar dtolnay avatar erer1243 avatar freax13 avatar kamilaborowska avatar marwes avatar nightmared avatar olegnn avatar qutesy avatar sergiobenitez avatar sorz avatar taiki-e avatar tyranron avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

async-trait's Issues

Associated constants in trait functions

This is a weird one & may not be an issue with async-trait, so please close if needed. When trying to use associated constants in macros (such as debug! or println!) it appears to trip up the compiler.

This standard trait compiles:

pub trait Example {
    const ASSOCIATED: &'static str;

    fn associated(&self) {
        println!("Associated:{}", Self::ASSOCIATED);
    }
}

This decorated trait does not compile:

#[async_trait]
pub trait Example {
    const ASSOCIATED: &'static str;

    async fn associated(&self) {
        println!("Associated:{}", Self::ASSOCIATED);
    }
}

I get the following error message:

error[E0401]: can't use generic parameters from outer function
  --> src/example.rs:16:35
   |
16 |         println!("Associated:{}", Self::ASSOCIATED);
   |                                   ^^^^^^^^^^^^^^^^
   |                                   |
   |                                   use of generic parameter from outer function
   |                                   can't use `Self` here

However, the trait impl works fine if you let bind it:

#[async_trait]
pub trait Example {
    const ASSOCIATED: &'static str;

    async fn associated(&self) {
        let associated = Self::ASSOCIATED;
        println!("Associated:{}", associated);
    }
}

The workaround appears to be OK for my use case.

Problem with implementing trait for `async fn`s

I'm trying to implement trait with async fn for all async fns. Simplified example:

#[async_trait]
trait Trait {
    async fn run(&self);
}

#[async_trait]
impl<F, Fut> Trait for F
where
    F: Fn() -> Fut + Sync,
    Fut: Future<Output = ()> + Send,
{
    async fn run(&self) {
        self().await
    }
}
simplified `cargo expand`
trait Trait {
    fn run<'s, 'async_trait>(&'s self) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
    where
        's: 'async_trait,
        Self: 'async_trait;
}

impl<F, Fut> Trait for F
where
    F: Fn() -> Fut + Sync,
    Fut: Future<Output = ()> + Send,
{
    fn run<'s, 'async_trait>(&'s self) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
    where
        's: 'async_trait,
        Self: 'async_trait,
    {
        #[allow(clippy::used_underscore_binding)]
        async fn __run<F, Fut>(_self: &F)
        where
            F: Fn() -> Fut + Sync,
            Fut: Future<Output = ()> + Send,
        {
            _self().await
        }
        Box::pin(__run::<F, Fut>(self))
    }
}

But sadly, this doesn't work:

error[E0309]: the parameter type `Fut` may not live long enough
  --> src/lib.rs:16:1
   |
16 | #[async_trait]
   | ^^^^^^^^^^^^^^
17 | impl<F, Fut> Trait for F
   |         --- help: consider adding an explicit lifetime bound `Fut: 'async_trait`...
   |
note: ...so that the type `impl std::future::Future` will meet its required lifetime bounds
  --> src/lib.rs:16:1
   |
16 | #[async_trait]
   | ^^^^^^^^^^^^^^

error: aborting due to previous error

(adding Fut: 'async_trait is impossible because it leads to impl has stricter requirements than trait errors)

But with by-hand desugaring this implementation is possible:

impl<F, Fut> Trait for F
where
    F: Fn() -> Fut + Sync,
    Fut: Future<Output = ()> + Send,
{
    fn run<'s, 'async_trait>(&'s self) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
    where
        's: 'async_trait,
        Self: 'async_trait,
    {
        Box::pin(async move { self().await })
    }
}

#[test]
fn test() {
    let closure = || async { () };
    Trait::run(&closure);
}

So, my questions are:

  1. Why the first implementation doesn't work, but the second does?
  2. Is it possible to remove async move {} from the last example? (Box::pin(self()) leads to the same error the parameter type Fut may not live long enough)
  3. Is it possible to write implementation like this, but without so much boilerplate?
  4. Can async_trait to accept implementations like in the first example? (after some changes in how macro works)

no_std support

Async-trait hardcodes paths to std instead of using paths to core/alloc (which is now stable). Async/await can be made to work on no_std through various hacks (such as https://github.com/SunriseOS/core-futures-tls ). As such, I believe it makes sense to use paths pointing to core/alloc instead.

error[E0698]: type inside `async` object must be known in this context

This code works:

impl<T: ?Sized> FutureExt for T where T: Future {}

#[async_trait]
pub trait FutureExt: Future {
    async fn flatten(self) -> <<Self as Future>::Output as Future>::Output
        where <Self as Future>::Output: Future + Send,
              Self: Sized,
    {
        let nested_future = self.await;
        nested_future.await
    }
}

However if I want to reduce the number of angle brackets, this won't work:

    async fn flatten(self) -> <<Self as Future>::Output as Future>::Output
        where Self::Output: Future + Send,
              Self: Sized,
    {...}


error:
   |
34 |         let nested_future = self.await;
   |             ^^^^^^^^^^^^^ cannot infer type
   |

But this will work:

    async fn flatten(self) -> <<Self as Future>::Output as Future>::Output
        where Self: Future, // hence self is Future whereas we already have FutureExt: Future
              Self::Output: Future + Send,
              Self: Sized,
    {...}

Why? Is it a desired behavior? Also I'd like to reduce angle brackets in the result type, but I failed...

Future type returned by trait methods should impl Sync

The methods generated by this library return Pin<Box<dyn Future + Send + 'async>> but leave out Sync.

As discussed on this internals thread, every type that may be used in async-await should be Sync. It may seem meaningless for a Future to impl Sync since its only method (poll) takes &mut self so &Future is useless, but the problem is that as an auto trait, the !Sync propagates to anything that owns the Future.

As a concrete example, I ran into this while trying to make a Hyper server that concatenates multiple objects from Amazon S3 into an HTTP response. rusoto_s3 uses async-trait to define its S3 trait. S3::get_object returns Pin<Box<dyn Future + Send>>, without Sync. When combining these futures into a stream, the resulting Stream therefore does not impl Sync. However, hyper::Body::wrap_stream has a Sync bound on its argument because the stream it is passed ends up wrapped inside a Request struct that needs to be Sync so that it can be borrowed across an await.

async-trait cannot handle `trait<'a>`?

I want to write a trait with lifetime, say:

use async_trait::async_trait;
use futures::executor::block_on;
pub struct Something<'a> {
    name: &'a str,
}

#[async_trait]
pub trait Abstract<'a> {
    async fn hello(thing: Something<'a>) -> String;
    async fn hello_ref(thing: Something<'a>) -> &'a str;
}

pub struct Real();
#[async_trait]
impl <'a> Abstract<'a> for Real {
    async fn hello(thing: Something<'a>) -> String {
        String::from(thing.name)
    }

    async fn hello_ref(thing: Something<'a>) -> &'a str {
        thing.name
    }
}

fn main() {
    let thing = Something{ name: "name" };
    let name = block_on(Real::hello(thing));
    println!("name: {}", name);
}

But it will throw an Error:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in function call due to conflicting requirements
  --> src\main.rs:14:1
   |
14 | #[async_trait]
   | ^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 15:7...
  --> src\main.rs:15:7
   |
15 | impl <'a> Abstract<'a> for Real {
   |       ^^
   = note: ...so that the expression is assignable:
           expected Something<'_>
              found Something<'a>
   = note: but, the lifetime must be valid for the static lifetime...
   = note: ...so that the expression is assignable:
           expected std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = std::string::String> + std::marker::Send + 'static)>>
              found std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::string::String> + std::marker::Send>>

I wonder am I do anything wrong? How to set the lifetime correctly?

Compatibility with specialization

In Rocket, there's currently the following function:

impl<'r, R: Responder<'r> + Send + 'r, E: fmt::Debug + Send + 'r> Responder<'r> for Result<R, E> {
    default fn respond_to(self, req: &'r Request<'_>) -> response::ResultFuture<'r> {
        Box::pin(async move {
            match self {
                Ok(r) => r.respond_to(req).await,
                Err(e) => {
                    error_!("Response was a non-`Responder` `Err`: {:?}.", e);
                    Err(Status::InternalServerError)
                }
            }
        })
    }
}

I'm looking into rewriting the traits using this crate, and would like to write the function as

#[async_trait]
impl<'r, R: Responder<'r> + Send + 'r, E: fmt::Debug + Send + 'r> Responder<'r> for Result<R, E> {
    default async fn respond_to(self, req: &'r Request<'_>) -> response::Result<'r> {
        match self {
            Ok(r) => r.respond_to(req).await,
            Err(e) => {
                error_!("Response was a non-`Responder` `Err`: {:?}.", e);
                Err(Status::InternalServerError)
            }
        }
    }
}

When doing this, I get an error.

error: missing `fn`, `type`, or `const` for impl-item declaration
   --> core/lib/src/response/responder.rs:296:99
    |
296 |   impl<'r, R: Responder<'r> + Send + 'r, E: fmt::Debug + Send + 'r> Responder<'r> for Result<R, E> {
    |  ___________________________________________________________________________________________________^
297 | |     default async fn respond_to(self, req: &'r Request<'_>) -> response::Result<'r> {
    | |____^ missing `fn`, `type`, or `const`

I presume this is because of specialization, as it seems to work everywhere else.

Attribute drops (some) attributes inside trait function implementations

When attributes appear inside of a function in a trait implementation decorated with #[async_trait], those attributes can be dropped depending on what they're decorating. In particular, attributes decorating fields are dropped entirely.

Consider the following example:

#[async_trait::async_trait]
trait Foo: Sized {
    fn g(&self);
}

struct K { field: usize }

#[async_trait::async_trait]
impl Foo for K {
    fn g(&self) {
        let _ = K {
            #[cfg(debug_assertions)]
            field: 0,
            #[cfg(not(debug_assertions))]
            field: 1,
        };
    }
}

This impl expand to:

impl Foo for K {
    fn g(&self) {
        let _ = K { field: 0, field: 1, };
    }
}

Which results in the (incorrect) compile-time error:

error[E0062]: field `field` specified more than once

error: aborting due to previous error

Note that span information appears to be lost as well.

Allow future to be !Send

I hope there is a parameter in async_trait like:

#[async_trait(unsend)]
trait A {
    async fn do(&self);
}

Then return type of A::do will be Pin<Box<dyn std::future::Future<Output = ()> + 'async>> instead of Pin<Box<dyn std::future::Future<Output = ()> + Send + 'async>>.

Using `type` in async trait will cause some problems?

Hi, me again. I found using type in trait will cause some problems...

  1. mismatched types
  2. cannot infer an appropriate lifetime for lifetime parameter 'a due to conflicting requirements
extern crate async_trait;

use async_trait::async_trait;
use futures::executor::block_on;

#[async_trait]
pub trait State<'a> {
    type Command: 'a + Send;

    async fn add_comm(mut self, more_str: Self::Command) -> Self where Self: Sized;
    async fn add_more_comm(mut self, str1: Self::Command, str2: Self::Command) -> Self where Self: Sized {
        let self1 = self.add_comm(str1).await;
        let self2 = self1.add_comm(str2).await;
        self2
    }
}

#[derive(Debug)]
pub struct RealState(String);
#[async_trait]
impl <'a> State<'a> for RealState {
    type Command = String;

    async fn add_comm(mut self, more_str: Self::Command) -> Self {
        self.0 = self.0.clone() + more_str.as_ref();
        self
    }
}

fn main() {
    let state = RealState(Default::default());
    let state1 = block_on(state.add_more_str("hello", " world"));
    println!("{:?}", state1);
}

Error:

error[E0308]: mismatched types
 --> src/lifetime-error.rs:6:1
  |
6 | #[async_trait]
  | ^^^^^^^^^^^^^^ one type is more general than the other
  |
  = note: expected type `std::marker::Send`
             found type `std::marker::Send`

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
 --> src/lifetime-error.rs:6:1
  |
6 | #[async_trait]
  | ^^^^^^^^^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 7:17...
 --> src/lifetime-error.rs:7:17
  |
7 | pub trait State<'a> {
  |                 ^^
  = note: ...so that the expression is assignable:
          expected <Self as State<'_>>::Command
             found <Self as State<'a>>::Command
note: but, the lifetime must be valid for the lifetime 'async_trait as defined on the method body at 6:1...
 --> src/lifetime-error.rs:6:1
  |
6 | #[async_trait]
  | ^^^^^^^^^^^^^^
  = note: ...so that the expression is assignable:
          expected std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = Self> + std::marker::Send + 'async_trait)>>
             found std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = Self> + std::marker::Send>>

Longhand method receivers emit the wrong bound

use async_trait::async_trait;

#[async_trait]
pub trait Trait {
    async fn f(&self) {} // works
    async fn g(self: &Self) {} // does not work
}
error[E0277]: `Self` cannot be shared between threads safely
   --> tests/test.rs:564:33
    |
564 |         async fn g(self: &Self) {}
    |                                 ^^ `Self` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `Self`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&Self`
    = note: required because it appears within the type `[static generator@tests/test.rs:564:33: 564:35 _self:&Self {}]`
    = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@tests/test.rs:564:33: 564:35 _self:&Self {}]>`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required for the cast to the object type `dyn std::future::Future<Output = ()> + std::marker::Send`

Will `default async fn` be supported?

Hi, me again. Now the trait with default async functions will not be support, say:

use async_trait::async_trait;
use futures::executor::block_on;
pub struct Something<'a> {
    name: &'a str,
}

#[async_trait]
pub trait Abstract<'a> {
    async fn hello(thing: Something<'a>) -> String;
    async fn hello_twice(thing1: Something<'a>, thing2: Something<'a>) -> String {
        let str1 = Self::hello(thing1).await;
        let str2 = Self::hello(thing2).await;
        str1 + str2.as_ref()
    }
}

pub struct Real();
#[async_trait]
impl <'a> Abstract<'a> for Real {
    async fn hello(thing: Something<'a>) -> String {
        String::from(thing.name)
    }
}

fn main() {
    let thing1 = Something{ name: "hello" };
    let thing2 = Something {name: "world"};
    let name = block_on(Real::hello_twice(thing1, thing2));
    println!("name: {}", name);
}

Will get error:

error[E0412]: cannot find type `AsyncTrait` in this scope
 --> src\main.rs:7:1
  |
7 | #[async_trait]
  | ^^^^^^^^^^^^^^ not found in this scope

Builds targeting musl currently fail

Using async-trait in builds targeting musl currently fails with the following error:

error: cannot produce proc-macro for `async-trait v0.1.22` as the target `x86_64-unknown-linux-musl` does not support these crate types

rust-lang/rust#40174

lifetimes do not match method in trait

When using async-trait the compiler reports that the lifetimes do not match when no lifetimes are specified. Specifying a lifetime resolves the issue even though the lifetime is never used.

This crate requires #![feature(proc_macro_hygiene)] and thus requires nightly.

$ cargo check                                                                                                                                                                                                               master
    Checking enzyme v0.1.0 (/usr/dataplus/enzyme)
    Checking user v0.1.0 (/usr/dataplus/enzyme/example/microservices/user)
error[E0195]: lifetime parameters or bounds on method `from_parts` do not match the trait declaration
  --> src/context.rs:10:24
   |
10 |     async fn from_parts(_parts: Parts, _params: Params) -> WebResult<TokenContext> {
   |                        ^ lifetimes do not match method in trait

error[E0195]: lifetime parameters or bounds on method `from_parts` do not match the trait declaration
  --> src/context.rs:21:24
   |
21 |     async fn from_parts(parts: Parts, _params: Params) -> WebResult<AuthContext> {
   |                        ^ lifetimes do not match method in trait

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0195`.
error: could not compile `user`.

To learn more, run the command again with --verbose.

Trait Definition:

https://github.com/technetos/enzyme/blob/master/src/context.rs#L7

Trait Usage:

https://github.com/technetos/enzyme/blob/master/example/microservices/user/src/context.rs#L10
and
https://github.com/technetos/enzyme/blob/master/example/microservices/user/src/context.rs#L21

Method of reproduction:

Remove the <'a> lifetime from the trait definition and the usages above. Run cargo check

cannot compile with serde's derive feature

With an empty src/lib.rs and a Cargo.toml:

[package]
name = "serde_test"
version = "0.1.0"
edition = "2018"

[dependencies]
serde = { version = "1", features = ["derive"] }
async-trait = "*"

I get a compile error:

/usr/bin/ld: /home/mjibson/go/src/github.com/mjibson/smith/target/debug/deps/libasync_trait-7f0705ba8d8d4e2b.so: hidden symbol `_ZN94_$LT$syn..punctuated..Pairs$LT$T$C$P$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$4next28_$u7b$$u7b$closure$u7d$$u7d$17ha125e58e4ccb5957E' isn't defined
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
          

error: aborting due to previous error

error: could not compile `async-trait`.

Removing the features = ["derive"] from serde causes this to compile fine. This is problematic because this crate is a dependency for many others (like the postgres crate, which is what led me to here).

`self` in locally defined macro doesn't get rewritten

Hi there and thanks for the great lib!

I just noticed that self, when referenced from a locally defined macro, is not correctly rewritten to _self.

#[async_trait::async_trait]
trait Magic {
    async fn foo(&self);
}

struct Bar {
    x: i32,
}

#[async_trait::async_trait]
impl Magic for Bar {
    async fn foo(&self) {
        macro_rules! ref_self {
            () => {
                // reference self somehow
                let _x = self.x;
            }
        }

        ref_self!();
    }
}

fn main() {}

expands to

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std;
trait Magic {
    fn foo<'life0, 'async_trait>(
        &'life0 self,
    ) -> ::core::pin::Pin<
        Box<dyn ::core::future::Future<Output = ()> + ::core::marker::Send + 'async_trait>,
    >
    where
        'life0: 'async_trait,
        Self: 'async_trait;
}
struct Bar {
    x: i32,
}
impl Magic for Bar {
    fn foo<'life0, 'async_trait>(
        &'life0 self,
    ) -> ::core::pin::Pin<
        Box<dyn ::core::future::Future<Output = ()> + ::core::marker::Send + 'async_trait>,
    >
    where
        'life0: 'async_trait,
        Self: 'async_trait,
    {
        #[allow(
            clippy::missing_docs_in_private_items,
            clippy::type_repetition_in_bounds,
            clippy::used_underscore_binding
        )]
        async fn __foo(_self: &Bar) {
            let _x = self.x;
        }
        Box::pin(__foo(self))
    }
}
fn main() {}

resulting in

error[E0434]: can't capture dynamic environment in a fn item
  --> src/main.rs:16:26
   |
16 |                 let _x = self.x;
   |                          ^^^^
...
20 |         ref_self!();
   |         ------------ in this macro invocation
   |
   = help: use the `|| { ... }` closure form instead

Currently, I just work around this by just passing it in as $self:ident.

Problems with inherited associated types

Hello there. I have problem with inherited associated types. The code below compiles successfully:

struct Foo;

trait T1 {
    type T;

    fn f1(&self, t: Self::T) -> Self::T;
}

trait T2: T1 {
    fn f2(&self, t: Self::T) -> Self::T;
}

impl T1 for Foo {
    type T = Foo;

    fn f1(&self, t: Self::T) -> Self::T {
        t
    }
}

impl T2 for Foo {
    fn f2(&self, t: Self::T) -> Self::T {
        self.f1(t)
    }
}

but if I add #[async_trait] like in this example:

use async_trait::async_trait;

struct Foo;

#[async_trait]
trait T1 {
    type T;

    async fn f1(&self, t: Self::T) -> Self::T;
}

#[async_trait]
trait T2: T1 {
    async fn f2(&self, t: Self::T) -> Self::T;
}

#[async_trait]
impl T1 for Foo {
    type T = Foo;

    async fn f1(&self, t: Self::T) -> Self::T {
        t
    }
}

#[async_trait]
impl T2 for Foo {
    async fn f2(&self, t: Self::T) -> Self::T {
        self.f1(t).await
    }
}

rust compiler generates these errors:

error[E0576]: cannot find associated type `T` in trait `T2`
  --> experiments/src/main.rs:32:33
   |
32 |     async fn f2(&self, t: Self::T) -> Self::T {
   |                                 ^ not found in `T2`

error[E0576]: cannot find associated type `T` in trait `T2`
  --> experiments/src/main.rs:32:45
   |
32 |     async fn f2(&self, t: Self::T) -> Self::T {
   |                                             ^ not found in `T2`

error: aborting due to 2 previous errors

cargo expand output shows that attribute replaces associated type to its code:

async fn __f2(_self: &Foo, t: <Foo as T2>::T) -> <Foo as T2>::T {
    _self.f1(t).await
}

If I replace Self::T with <Self as T1>::T rustc will be happy.

Does not compile if self is Arc<Self>

Please add support for using a self type of Arc.

#![feature(async_await)]
use std::sync::Arc;
use async_trait::async_trait;

#[async_trait]
trait Trait {
    async fn example(self : Arc<Self>);
}

struct A;

#[async_trait]
impl Trait for A where  {
    async fn example(self : Arc<Self>) {
    }
}

fn main() {
    let a = Arc::new(A);
    async move {
        a.example().await
    };
}

error: unexpected `self` parameter in function
  --> src\main.rs:12:1
   |
12 | #[async_trait]
   | ^^^^^^^^^^^^^^ not valid as function parameter
   |
   = note: `self` is only valid as the first parameter of an associated function

Combine generic parameters from impl block and method

#![feature(async_await)]

use async_trait::async_trait;

#[async_trait]
trait Trait {
    async fn f<U>(&self);
}

#[async_trait]
impl<T> Trait for Vec<T> {
    async fn f<U>(&self) {}
}

Currently this fails to compile because the nested freestanding async fn we generate is missing the T type parameter:

error[E0401]: can't use generic parameters from outer function
  --> src/main.rs:11:23
   |
7  |     async fn f<U>(&self);
   |              - try adding a local generic parameter in this method instead
...
11 | impl<T> Trait for Vec<T> {
   |      -                ^ use of generic parameter from outer function
   |      |
   |      type parameter from outer function

Expanded code:

impl<T> Trait for Vec<T> {
    fn f<'life0, 'async_trait, U>(
        &'life0 self,
    ) -> std::pin::Pin<
        std::boxed::Box<dyn std::future::Future<Output = ()> + std::marker::Send + 'async_trait>,
    >
    where
        U: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait,
    {
        async fn __f<'async_trait, U>(_self: &Vec<T>) {}
        std::pin::Pin::from(std::boxed::Box::new(__f::<U>(self)))
    }
}

We need to merge the syn::Generics from the impl block with the syn::Generics on the method to produce the generics that go on the inner function. In this case it should be:

        async fn __f<'async_trait, T, U>(_self: &Vec<T>) {}

Any ideas on how to abstract over async closures? Can you collaborate with Diesel to bring about async?

Would you be willing to read over the Async I/O thread on Diesel? If you have any ideas on how to unblock Diesel going full async, I reckon the more full async ODM/ORMs/DB Drivers there all, and the more feature complete they become, the more compelling Rust is going to look over other languages. It feels like we're almost there, but that this is a blocker for widespread adoption in the startup space, and that once we get past this hurdle Rust will start to experience a healthy period of growth/adoption.

expected bound lifetime parameter, found concrete lifetime

Hello, anyone can help me to fix this error?

use std::collections::HashMap;
use async_trait::async_trait;
use std::future::Future;

#[tokio::main]
async fn main() {
    call_handler(hello).await;
}

async fn call_handler(handler: impl Handler) {
    let mut data = HashMap::new();
    handler.handle(&mut data);
}

async fn hello(data: &mut HashMap<String, String>) {
    print!("{:#?}", data);
}

#[async_trait]
pub trait Handler{
    async fn handle(&self, data: &mut HashMap<String, String>);
}

#[async_trait]
impl<F, R> Handler for F
where
    F: Send + Sync + 'static + Fn(&mut HashMap<String, String>) -> R,
    R: Send + 'static + Future<Output=()>,
{
    async fn handle(&self, data: &mut HashMap<String, String>) {
        (*self).handle(data).await
    }
}

this code will report error๏ผš

error[E0271]: type mismatch resolving `for<'r> <for<'_> fn(&mut std::collections::HashMap<std::string::String, std::string::String>) -> impl std::future::Future {hello} as std::ops::FnOnce<(&'r mut std::collections::HashMap<std::string::String, std::string::String>,)>>::Output == _`
  --> src\main.rs:7:5
   |
7  |     call_handler(hello).await;
   |     ^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
...
10 | async fn call_handler(handler: impl Handler) {
   |          ------------               ------- required by this bound in `call_handler`
   |
   = note: required because of the requirements on the impl of `Handler` for `for<'_> fn(&mut std::collections::HashMap<std::string::String, std::string::String>) -> impl std::future::Future {hello}`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0271`.
error: could not compile `rust-test`.

To learn more, run the command again with --verbose.

Using anonymous lifetimes fails to compile

The following:

struct Baz;

#[async_trait]
trait Foo {
    async fn test(value: &Baz);
}

struct Bar<'a>(&'a ());

#[async_trait]
impl Foo for Bar<'_> {
    async fn test(value: &Baz) {
    }
}

Results in:

error[E0261]: use of undeclared lifetime name `'_`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0261`.
error: Could not compile `oxidize`.

To learn more, run the command again with --verbose.

Elided or placeholdered generic lifetimes are not properly respected in trait implementation

Consider the following, where the lifetime for & is elided in the trait implementation and a placeholder is used for the generic in the trait:

#[async_trait::async_trait]
trait Foo<'a>: Sized {
    async fn f(bar: &'a usize) -> Self;
}

#[async_trait::async_trait]
impl Foo<'_> for usize {
    async fn f(bar: &usize) -> Self {
        10
    }
}

This generates the following implementation:

impl Foo<'_> for usize {
    fn f<'y, 'life0>(bar: &'life0 usize) -> BoxFuture<'y, Self>
        where 'life0: 'y, Self: 'y
    {
        async fn __f(bar: &usize) -> usize { 10 }
        Box::pin(__f::<>(bar))
    }
}

This, of course, does not match the generated trait definition which has only a single lifetime generic in f. The "correct" implementation would look like:

impl<'f> Foo<'f> for usize {
    fn f<'y>(bar: &'f usize) -> BoxFuture<'y, Self>
        where 'f: 'y, Self: 'y
    {
        async fn __f(bar: &usize) -> usize { 10 }
        Box::pin(__f::<>(bar))
    }
}

This, of course, would require async-trait to know that the placeholdered generic lifetime in the trait corresponds to the elided lifetime in the implementation. In general, it's clear that async-trait can't do this as it doesn't have type information nor access to the AST of the definition.

I believe that async-trait should likely error when trait generics are placeholdered. At least then the user gets a nice error message as opposed to incorrect code being generated.

`&mut self` parameters don't need `Sync` bounds

Only &self needs Sync bounds, because you can create more of these references. But if you start out with &mut self, there's no way anyone else can have a borrow, so the additional bound is unnecessary.

Generic params from impl dont have 'async_trait lifetime

I tried to produce a MRE:

#[async_trait]
pub trait MapInto<T>: Future {
    async fn map_into(self) -> T
        where Self: Sized;
}

#[async_trait]
impl<F, T> MapInto<T> for F
    where F: ?Sized,
          F: Future + Send,
          T: From<F::Output>,
{
    async fn map_into(self) -> T
        where Self: Sized,
    {
        self.await.into()
    }
}

error:

error[E0309]: the parameter type `T` may not live long enough
   --> src/future.rs:116:1
    |
116 | #[async_trait]
    | ^^^^^^^^^^^^^^
117 | impl<F, T> MapInto<T> for F
    |         - help: consider adding an explicit lifetime bound `T: 'async_trait`...
    |

A fix for me: T: 'static, in impl block. Is it a bug?

Split into implementation and proc_macro crate

I wanted to make a proc macro that used the async_trait proc macro (after doing some other changes to the input). Now, one way to do this is to require consumers to always add both (in the right order), however, I wanted to avoid that as it's not ergonomic. So I tried doing this:

use async_trait::async_trait;
use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn test(_args: TokenStream, input: TokenStream) -> TokenStream {
  let cloned = input.clone();

  ::async_trait::async_trait(TokenStream::new(), input)
}

This does not compile, and I've not been able to figure out any way to make it work. The only thing I can think of is generating code (from my proc macro) that has #[async_trait] in front, but this requires consumers to explicitly have a reference to this crate, which I would also like to avoid if possible. So I suggest splitting up this crate into an "implementation" crate, using proc-macro2, and an actual proc_macro crate that just calls the functions exported from the implementation crate. This should be pretty straight forward to do. I'm willing to provide a PR if this is something that would be accepted.

Self:: doesn't work in patterns

use async_trait::async_trait;

#[async_trait]
pub trait Trait {
    async fn handle(&self);
}

pub enum Enum {
    Variant,
}

#[async_trait]
impl Trait for Enum {
    async fn handle(&self) {
        let Enum::Variant = self; // works
        let Self::Variant = self; // does not work
    }
}
error[E0401]: can't use generic parameters from outer function
   --> tests/test.rs:552:17
    |
549 |     impl Trait for Enum {
    |     ---- `Self` type implicitly declared here, by this `impl`
...
552 |             let Self::Variant = self;
    |                 ^^^^^^^^^^^^^
    |                 |
    |                 use of generic parameter from outer function
    |                 use a type here instead

Error using async trait helper methods with async trait bound on associated type

I'm not experienced enough with async/await to be sure that this is a library issue and not a user error, but I didn't expect to see this type of type error in this use case. (minimized example)

#[async_trait]
pub trait TestCap {
    async fn foo(&self) -> String;
}

#[async_trait]
pub trait HasTestCap {
    type Output: TestCap;

    fn test_caps(&self) -> &Self::Output;

    async fn test_foo(&self) -> String {
        self.test_caps().foo()
    }
}

results in:

error[E0271]: type mismatch resolving `<impl core::future::future::Future as core::future::future::Future>::Output == std::string::String`
  --> src/capabilities/mod.rs:26:33
   |
26 |     async fn test_foo(&self) -> String {
   |                                 ^^^^^^ expected struct `std::pin::Pin`, found struct `std::string::String`
   |
   = note: expected type `std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::string::String> + std::marker::Send>>`
              found type `std::string::String`
   = note: the return type of a function must have a statically known size

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds

Hello,

I was trying to spawn an async block inside another async function with Tokio (which requires the async block to be Future<Output = ()> + Send + 'static, so I had to borrow other_trait as 'static as well). Rust tells me somehow my code is an E0700.

The minified version of my code as following:

trait AnotherTrait: Send + Sync {
    fn test(&self);
}

trait Test2 {
    // This one without async fn
    fn test2<'a>(&self, other_trait: &'static impl AnotherTrait) -> Result<&'a str, ()>;
}

use async_trait::async_trait;
#[async_trait]
trait Test {
    // This one with async fn
    async fn test<'a>(&self, other_trait: &'static impl AnotherTrait) -> Result<&'a str, ()>;
}

use tokio::runtime;

struct ImplTest {}

impl Test2 for ImplTest {
    fn test2<'a>(&self, other_trait: &'static impl AnotherTrait) -> Result<&'a str, ()> {
        println!("Hello, world!");

        match runtime::Runtime::new() {
            Err(e) => panic!(e),
            Ok(t) => t.spawn(async move {
                other_trait.test();
            }),
        };

        Ok("Ok")
    }
}

#[async_trait]
impl Test for ImplTest {
    async fn test<'a>(&self, other_trait: &'static impl AnotherTrait) -> Result<&'a str, ()> {
        println!("Hello, world!");

        match runtime::Runtime::new() {
            Err(e) => panic!(e),
            Ok(t) => t.spawn(async move {
                other_trait.test();
            }),
        };

        Ok("Ok")
    }
}

fn main() {
    ImplTest {};
}

Cargo.toml file:

[package]
name = "async_trait_E0700"
version = "0.1.0"
authors = ["Noop"]
edition = "2018"

[dependencies]
async-trait = "0.1.17"
futures-preview = {version = "0.3.0-alpha.18", features = ["async-await"]}
tokio = "0.2.0-alpha.5"

Error message:

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
  --> src/main.rs:38:74
   |
38 |     async fn test<'a>(&self, other_trait: &'static impl AnotherTrait) -> Result<&'a str, ()> {
   |                                                                          ^^^^^^^^^^^^^^^^^^^
   |
note: hidden type `impl std::future::Future` captures the scope of call-site for function at 38:94
  --> src/main.rs:38:94
   |
38 |       async fn test<'a>(&self, other_trait: &'static impl AnotherTrait) -> Result<&'a str, ()> {
   |  ______________________________________________________________________________________________^
39 | |         println!("Hello, world!");
40 | |
41 | |         match runtime::Runtime::new() {
...  |
48 | |         Ok("Ok")
49 | |     }
   | |_____^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0700`.
error: could not compile `async_trait_E0700`.

I'm still learning all the pieces of the puzzle of Rust, so I'm not sure about whether it's my mistake or a bug. Sorry for bothering if it's me been dumb :(

PS: I've read the #15, but not sure my problem is related.

Thank you!

SmallBox?

Out of curiosity, might this library benefit from using SmallBoxes to help reduce the overhead of boxing? (Hopefully my question isn't completely off...)

async-trait should add `must_use` declaration

async-trait should add #[must_use] declarations on async trait functions. This compiler warning is rather important -- pretty easy to forget to call .await and then have a function call not actually execute that looks like it should be executing.

Lifetime bounds on method do not match the trait declaration

With an impl like this:

#[async_trait]
impl<C> ManageConnection for OkManager<C>
where
    C: Default + Send + Sync + 'static,
{
    type Connection = C;
    type Error = Error;

    async fn connect(
        &self,
    ) -> Result<Self::Connection, Self::Error> {
        Ok(Default::default())
    }

    async fn is_valid(
        &self,
        conn: Self::Connection,
    ) -> Result<Self::Connection, (Self::Error, Self::Connection)> {
        Ok(conn)
    }

    fn has_broken(&self, _: &mut Self::Connection) -> bool {
        false
    }
}

I get errors from the compiler:

error[E0195]: lifetime parameters or bounds on method `connect` do not match the trait declaration
  --> tests/test.rs:48:1
   |
48 | #[async_trait]
   | ^^^^^^^^^^^^^^ lifetimes do not match method in trait

I guess this is because async-trait doesn't see/understand the 'static bound for the type parameter, and then add its own bound, when it probably doesn't have too?

Macro expansion error inside #[async_trait] item points to wrong span

The following code:

use async_trait::async_trait;

macro_rules! picky {
    { stuff: { $contents:expr } } => { println!("stuff: {}", $contents); }
}

#[async_trait]
trait Foo {
    async fn foo() -> i32;
}

struct Bar;

#[async_trait]
impl Foo for Bar {
    async fn foo() -> i32 {
        picky!({ 123 });
        42
    }
}

emits the following error:

error: no rules expected the token `{`
  --> src/main.rs:16:1
   |
5  | macro_rules! picky {
   | ------------------ when calling this macro
...
16 | #[async_trait]
   | ^^^^^^^^^^^^^^ no rules expected this token in macro call

Can you spot the problem? We forgot stuff: inside picky!(). However, the "no rules expected this token" note points to #[async_trait] instead of the unexpected { token.

When I make the async fn's non-async (leaving #[async_trait]), the error message looks correct. I also can't reproduce using normal macros, so I suspect the issue is with async-trait.

`mut self` is expended as `_self`

#[async_trait]
pub trait T {
    async fn f(self);
}

struct S {}

#[async_trait]
impl T for S {
    async fn f(mut self) {
        (&mut self).do_something();
    }
}

would give error

                                  ---- help: consider changing this to be mutable: `mut _self`
    (&mut self)
       ^^^^^^^^^^^ cannot borrow as mutable

Failed to work with generic and DashMap

Moved from xacrimon/dashmap#55 (comment)

use std;
use async_trait::async_trait;
use dashmap::DashMap;
use std::collections::HashMap;
use tokio;

struct Foo {}
struct Gar<T: Bar> {
    map: DashMap<u32, T>,
}

#[async_trait]
trait Bar {
    async fn bar(&self) -> u32;
}

#[async_trait]
impl Bar for Foo {
    async fn bar(&self) -> u32{
        0
    }
}

#[async_trait]
trait GarTrait {
    async fn coo(&self) -> Vec<u32>;
}

#[async_trait]
impl<T> GarTrait for Gar<T> where T: Bar + Send + Sync,{
    async fn coo(&self) -> Vec<u32> {
        let mut a = Vec::new();
        for item in self.map.iter() {
            let bar= item.value();
            let i: u32 = bar.bar().await;
            a.push(i);
        }
        a
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>>{
    let g = Gar::<Foo>{map:DashMap::new()};
    g.coo().await;
    Ok(())
}

cargo build complaints error

$ cargo build
   Compiling t v0.1.0 (-)
warning: unused import: `std::collections::HashMap`
 --> src/main.rs:4:5
  |
4 | use std::collections::HashMap;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0311]: the parameter type `T` may not live long enough
  --> src/main.rs:31:37
   |
31 |       async fn coo(&self) -> Vec<u32> {
   |  _____________________________________^
32 | |         let mut a = Vec::new();
33 | |         for item in self.map.iter() {
34 | |             let bar= item.value();
...  |
38 | |         a
39 | |     }
   | |_____^
   |
   = help: consider adding an explicit lifetime bound for `T`
   = note: the parameter type `T` must be valid for any other region...
note: ...so that the type `T` will meet its required lifetime bounds
  --> src/main.rs:31:37
   |
31 |       async fn coo(&self) -> Vec<u32> {
   |  _____________________________________^
32 | |         let mut a = Vec::new();
33 | |         for item in self.map.iter() {
34 | |             let bar= item.value();
...  |
38 | |         a
39 | |     }
   | |_____^

error: aborting due to previous error

error: could not compile `t`.

To learn more, run the command again with --verbose.

Note: It's ok to compile when using HashMap, or set T: 'static. Though setting 'static seems not a correct way to fix it.

Cargo.toml

[dependencies]
tokio = { version = "*", features = ["full"] }
async-trait = "*"
dashmap = "*"

Cannot infer type of returned expression

use async_trait::async_trait;

#[async_trait]
trait Trait {
    async fn func(&self) -> &[&str];
}

struct Struct;

#[async_trait]
impl Trait for Struct {
    async fn func(&self) -> &[&str] {
        &[""]
    }
}
error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == &[&str]`
  --> src/lib.rs:12:29
   |
12 |     async fn func(&self) -> &[&str] {
   |                             ^^^^^^^ expected array of 1 elements, found slice
   |
   = note: expected type `&[&str; 1]`
              found type `&[&str]`
   = note: the return type of a function must have a statically known size

Remove the async keyword and there is no error.

`#[allow(clippy::missing_docs_in_private_items)]`

#[warn(missing_docs, clippy::missing_docs_in_private_items)] always warn that functions lack documents, even if there are documents.

How to reproduce

Cargo.toml:

[package]
name = "async-trait-test"
version = "0.0.0"
edition = "2018"

[dependencies]
async-trait = { git = "https://github.com/dtolnay/async-trait.git" }

lib.rs:

//! Test.
#![warn(missing_docs, clippy::missing_docs_in_private_items)]

use async_trait::async_trait;

/// Test trait.
#[async_trait]
trait Trait {
    /// Does foo.
    async fn foo(&self);
}

/// Foo processor.
struct Fooer;

#[async_trait]
impl Trait for Fooer {
    /// Does foo using `Fooer`.
    async fn foo(&self) {}
}

Expected result

No warnings.

Actual result

clippy warns about missing documentation.

$ cargo clippy
    Checking async-trait-test v0.0.0 (/tmp/lo48576.e976b1e9-64d3-4703-acea-09dc331c1600/transient/async-trait-test)
warning: missing documentation for a function
  --> src/lib.rs:19:5
   |
19 |     async fn foo(&self) {}
   |     ^^^^^^^^^^^^^^^^^^^^^^
   |
note: lint level defined here
  --> src/lib.rs:2:23
   |
2  | #![warn(missing_docs, clippy::missing_docs_in_private_items)]
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items

    Finished dev [unoptimized + debuginfo] target(s) in 0.10s

Very vague and unhelpful error "implementation of `std::iter::Iterator` is not general enough" under certain circumstances

I've run into a really strange issue when using async-trait that I'm not sure what to do with. It feels to me like a compiler bug, but I can't reproduce it without using async-trait so decided to start with an issue here and see where it goes.

I have a very simple project, with dependencies on only async-trait and itertools (which is also required in order to repro this behavior). See this gist for the full source code.

I have the following async trait and impl:

#[async_trait]
trait DoSomethingAsync {
    async fn do_something<ITER: IntoIterator<Item = Foo>>(foos: ITER)
    where
        ITER: Send + 'static,
        <ITER as IntoIterator>::IntoIter: Send + 'static;
}

struct Doer {}

#[async_trait]
impl DoSomethingAsync for Doer {
    async fn do_something<ITER: IntoIterator<Item = Foo>>(foos: ITER)
    where
        ITER: Send + 'static,
        <ITER as IntoIterator>::IntoIter: Send + 'static,
    {
        // Compilation will fail with the message:
        // implementation of `std::iter::Iterator` is not general enough
        do_something(foos).await
    }
}

The definition of Foo doesn't seem to be important. In this case it's:

struct Foo(String);

The function do_something is implemented thus:

async fn do_something<ITER: IntoIterator<Item = Foo>>(foos: ITER) {
    let foos: Vec<_> = foos.into_iter().collect();

    // If this line is commented out, then the unexpected behavior does not happen.
    // It seems the use of the Iterator implementation returned by `unique()` is somehow a part of
    // the problem.
    let foos = foos.iter().map(|foo| foo.0.to_lowercase()).unique();

    // If this line is uncommented, the unexpected behavior does not happen.  It seems that the
    // type inference involved in resolving `collect()`'s return type to `Vec<_>` is part of the
    // problem.
    //let foos: Vec<_> = foos.collect();
    let _uniques = do_something_with_uniques(foos.collect()).await;
}

async fn do_something_with_uniques(uniques: Vec<String>) -> Vec<String> {
    uniques.into_iter().collect()
}

When I compile this project, the error I get is:

error: implementation of `std::iter::Iterator` is not general enough
    --> src/main.rs:41:5
     |
41   | /     {
42   | |         // Compilation will fail with the message:
43   | |         // implementation of `std::iter::Iterator` is not general enough
44   | |         do_something(foos).await
45   | |     }
     | |_____^ implementation of `std::iter::Iterator` is not general enough
     |
     = note: `std::iter::Iterator` would have to be implemented for the type `std::slice::Iter<'0, Foo>`, for any lifetime `'0`...
     = note: ...but `std::iter::Iterator` is actually implemented for the type `std::slice::Iter<'1, Foo>`, for some specific lifetime `'1`

Note that the span of this error is the implementation of do_something on Doer. Not the specific line calling do_something; the entire function body.

The error can be eliminated by changing this line:

let _uniques = do_something_with_uniques(foos.collect()).await;

to this:

let foos: Vec<_> = foos.collect();
let _uniques = do_something_with_uniques(foos).await;

But that change is deep into the call tree from where the error is being reported, and the error message itself is almost completely devoid of meaningful hints as to the nature of the problem. I spent hours narrowing down a very deep call tree before I was able to isolate the problem.

I have an easy workaround, which is to not rely on type inference and explicitly pass foos as a Vec, but this was such a nasty bug to work through the least I can do is post it in case anyone else runs into it.

FWIW I ran into this with the latest release of async-trait, using Rust 1.41, but I've also reproduced it with nightly.

self parameter gets expanded as module self in macro

Minimal reproduction

macro_rules! implement_commands {
    (
        $tyargs:ident : $ty:ident
    ) => {
        #[async_trait]
        pub trait AsyncCommands: Sized {
            async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
                self.f(x).await
            }
        }
    };
}

implement_commands! { K: Send }
error[E0424]: expected value, found module `self`
   --> tests/test.rs:434:9
    |
434 |         #[async_trait]
    |         ^^^^^^^^^^^^^^ `self` value is a keyword only available in methods with `self` parameter
...
443 | implement_commands! { K: Send }
    | ------------------------------- in this macro invocation

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds

With this seemingly ok code:

#![feature(async_await)]

use async_trait::async_trait;
use slog::Logger;

#[async_trait]
trait MyTrait {
    async fn myfn(&self, logger: Logger);
}

struct MyImpl;

#[async_trait]
impl MyTrait for MyImpl {
    async fn myfn(&self, _logger: Logger) {}
}

I get this odd error:

   Compiling redacted v0.1.0 (/redacted)
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
  --> tests/test.rs:15:43
   |
15 |     async fn myfn(&self, _logger: Logger) {}
   |                                           ^
   |
note: hidden type `impl std::future::Future` captures the scope of call-site for function at 15:43
  --> tests/test.rs:15:43
   |
15 |     async fn myfn(&self, _logger: Logger) {}
   |                                           ^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0700`.
error: Could not compile `redacted`.

To learn more, run the command again with --verbose.

The error is caused by slog::Logger.

This seems to be a bug. As a workaround, I'm currently passing the logger in a wrapper-struct, but I hope to get this solved.

PS: I have no idea what's going on here, and how to simplify the example further.

Support trait methods with const generic parameters

#![feature(const_generics)]

use async_trait::async_trait;

#[async_trait]
trait Trait {
    async fn const_generic<const C: usize>() {}
}

The code generated for this by #[async_trait] currently fails to compile with:

error[E0282]: type annotations needed
 --> src/main.rs:7:46
  |
7 |     async fn const_generic<const C: usize>() {}
  |                                              ^^ cannot infer type for struct `std::pin::Pin<std::boxed::Box<impl std::future::Future>>`

lifetime parameters or bounds on method <...> do not match the trait declaration

Hi me again, this time is a lifetime error when I return self:

extern crate async_trait;

use async_trait::async_trait;
use futures::executor::block_on;

#[async_trait]
pub trait State<'a> {
    async fn add_str(mut self, more_str: &'a str) -> Self where Self: Sized;
    async fn add_more_str(mut self, str1: &'a str, str2: &'a str) -> Self where Self: Sized {
        let self1 = self.add_str(str1).await;
        let self2 = self1.add_str(str2).await;
        self2
    }
}

#[derive(Debug)]
pub struct RealState<'a>(&'a str);
#[async_trait]
impl <'a> State<'a> for RealState<'a> {
    fn add_str(mut self, more_str: &'a str) -> Self {
        self.0 = (self.0.to_owned() + more_str).as_ref();
        self
    }
}

fn main() {
    let state = RealState("");
    let state1 = block_on(state.add_more_str("hello", " world"));
    println!("{:?}", state1);
}

And will get an error:

error[E0195]: lifetime parameters or bounds on method `add_str` do not match the trait declaration
  --> src/lifetime-error.rs:20:15
   |
6  | #[async_trait]
   | -------------- lifetimes in impl do not match this method in trait
...
20 |     fn add_str(mut self, more_str: &'a str) -> Self {
   |               ^ lifetimes do not match method in trait

?Send -> !Send

?Send annotation should be !Send I believe since it's opting out of a trait bound

Self type in trait implementation causes panic in #[async_trait]

Example Code:

use async_trait::async_trait;

struct Struct;

#[async_trait]
pub trait Trait {
    async fn foo();
}

#[async_trait]
impl Trait for Struct {
    async fn foo() {
        let _ = Self;
        // let _ = Struct;
    }
}

Error:

error: custom attribute panicked
  --> src/lib.rs:19:1
   |
19 | #[async_trait]
   | ^^^^^^^^^^^^^^
   |
   = help: message: called `Option::unwrap()` on a `None` value

I traced the error to using Self instead of Struct. non-async functions are not affected. Also the error is different if I change it to Struct { x: u8 }, but not if I cange it to Struct(u8);:

error[E0401]: can't use generic parameters from outer function
  --> src/lib.rs:22:17
   |
20 | impl Trait for Struct {
   | ---- `Self` type implicitly declared here, by this `impl`
21 |     async fn foo() {
22 |         let _ = Self { x: 0 };
   |                 ^^^^
   |                 |
   |                 use of generic parameter from outer function
   |                 use a type here instead

This time not a panic, but this would compile with Struct instead of Self or in a non-async function.

using async-trait0.1.19 & Rust 1.39.0

PS. thanks for this crate, it's awesome!

mut self doesn't work with feature support_old_nightly

Given:

// main.rs
use async_trait::async_trait;

#[async_trait]
trait Trait {
    async fn operation(mut self);
}

struct Struct {
    child: String,
}

#[async_trait]
impl Trait for Struct {
    async fn operation(mut self) {
        let _ = &mut self.child;
    }
}

fn main() {
    println!("Hello, world!");
}

# Cargo.toml
[package]
name = "async-trait"
version = "0.1.0"
edition = "2018"

[dependencies]
async-trait = {version = "0.1.27", features = ["support_old_nightly"]}

I get the error using the latest Rust nightly:

error[E0596]: cannot borrow `self.child` as mutable, as `self` is not declared as mutable
  --> src\main.rs:15:17
   |
14 |     async fn operation(mut self) {
   |                            ---- help: consider changing this to be mutable: `mut self`
15 |         let _ = &mut self.child;
   |                 ^^^^^^^^^^^^^^^ cannot borrow as mutable

The support_old_nightly feature seems to be the issue.

Return future with lifetime that's different from `&self`s

I have a Stream that needs to run a Future from a trait method on each iteration. I've managed to get it to work using a LocaslBoxFuture:

pub trait Make {
    // working
    fn make<'a, T: Default + 'a>(&self) -> LocalBoxFuture<'a, T> {
        Box::pin(future::ready(T::default()))
    }
}

struct Foo {}
impl Make for Foo {}

fn main() {
    let f = Foo {};
    block_on_stream(stream::empty().map(move |_: ()| f.make::<bool>()));
}

However, I haven't been able to figure out how to accomplish the same with async_trait. For example, attempting the following fails:

#[async_trait]
pub trait Make {
    // broken
    async fn make<'a, T: Default + 'a>(&self) -> T {
        T::default()
    }
}

With error:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:20:56
   |
20 |     block_on_stream(stream::empty().map(move |_: ()| f.make::<bool>()));
   |                                                        ^^^^
   |
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 20:41...
  --> src/main.rs:20:41
   |
20 |     block_on_stream(stream::empty().map(move |_: ()| f.make::<bool>()));
   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `f`
  --> src/main.rs:20:54
   |
20 |     block_on_stream(stream::empty().map(move |_: ()| f.make::<bool>()));
   |                                                      ^
note: but, the lifetime must be valid for the method call at 20:21...
  --> src/main.rs:20:21
   |
20 |     block_on_stream(stream::empty().map(move |_: ()| f.make::<bool>()));
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that a type/lifetime parameter is in scope here
  --> src/main.rs:20:21
   |
20 |     block_on_stream(stream::empty().map(move |_: ()| f.make::<bool>()));
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

error: could not compile `stream-async-trait`.

I've tried various permutations with 'async_trait and 'a leading to similar results.

I'm trying to figure out if what I'm attempting is supported and I'm just missing something?
Perhaps this is related to #8 (I don't have quite a strong enough handle on Futures/lifetimes to tell for sure)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.