dtolnay / async-trait

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

Generic parameters in functions #275

Closed Tockra closed 1 month ago

Tockra commented 1 month ago

Hi is there a chance that we can use generic trait functions ?

I would like to have a trait like this:

#[async-trait]
trait MyTrait<T> {
     async fn my_func<E>(param: E) -> T;
}

But this does not work. I have to build for each concrete type E a own function. That blows my trait :(

Is there a workaround or a plan to support this?

T

dtolnay commented 1 month ago

This is already supported. If you need Send futures, E needs to be Send:

#[async_trait]
trait MyTrait<T> {
    async fn my_func<E: Send>(param: E) -> T;
}

Otherwise:

#[async_trait(?Send)]
trait MyTrait<T> {
    async fn my_func<E>(param: E) -> T;
}
Tockra commented 1 month ago

Hmm if I use generics with some restrictions and then use &dyn MyTrait I see:

error[E0038]: the trait `MyTrait` cannot be made into an object
   --> src/db/mongo/mod.rs:518:15
    |
518 |     service: &dyn MyTrait,
    |               ^^^^^^^^^^^^^^^^^^^^^^ `MyTrait` cannot be made into an object
    |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> src/db/mod.rs:107:14
    |
25  | pub trait MyTrait:
    |           --------------- this trait cannot be made into an object...
...
107 |     async fn my_method_with_generics<E: Clone + Send + Sync + Into<Bson>>(
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `my_method_with_generics` has generic type parameters
    = help: consider moving `my_method_with_generics` to another trait
    = help: only type `MyTrait` is seen to implement the trait in this crate, consider using it directly instead
    = note: `MyTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type