dtolnay / async-trait

Type erasure for async trait methods
Apache License 2.0
1.81k stars 84 forks source link

default impl for methods with `impl trait` arguments? #126

Closed wfraser closed 3 years ago

wfraser commented 4 years ago

Given the code:

use async_trait::async_trait; // 0.1.36
use tokio; // 0.2.21

#[async_trait]
trait MyTrait {
    async fn blah(&self, values: impl Iterator<Item = i32> + Send + 'async_trait) {
        println!("this is the default");
    }
}

struct S;

#[async_trait]
impl MyTrait for S {
    async fn blah(&self, values: impl Iterator<Item = i32> + Send + 'async_trait) {
        for value in values {
            println!("{}", value);
        }
    }
}

#[tokio::main]
async fn main() {
    let s = S;
    s.blah([1, 2, 3].iter().cloned()).await;
}

this fails to compile with the error:

error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
 --> src/main.rs:4:1
  |
4 | #[async_trait]
  | ^^^^^^^^^^^^^^ explicit generic argument not allowed
  |
  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

If I remove the default body, it works.

Is this intended to be supported? I can work around it by boxing and using dyn, i.e. values: Box<dyn Iterator<Item=i32> + Send + 'async_trait> but that's not ideal.

Thanks for this crate!

wfraser commented 4 years ago

Looks like the expanded code is: (cleaned up a little)

trait MyTrait {
    #[must_use]
    fn blah<'life0, 'async_trait>(&'life0 self, values: impl Iterator<Item = i32> + Send + 'async_trait)
        -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
        where 'life0: 'async_trait,
              Self: Sync + 'async_trait
    {
        async fn __blah<'async_trait, AsyncTrait: ?Sized + MyTrait + Sync>(
            _self: &AsyncTrait,
            values: impl Iterator<Item = i32> + Send + 'async_trait,
        ) {
            println!( ... );
        }
        Box::pin(__blah::<Self>(self, values))
    }
}

and rustc does not like the explicit generic argument in __blah::<Self>(self, values). Simply removing that ::<Self> turbofish works for this case at least.

attila-lin commented 3 years ago

Same issue.