dtolnay / async-trait

Type erasure for async trait methods
Apache License 2.0
1.84k stars 85 forks source link

Remove defaults from trait params when using them in function definition #123

Closed tyranron closed 4 years ago

tyranron commented 4 years ago

Synopsis

At the moment, if trait has type/const parameters with default values and also has a default method implementation, like the following:

#[async_trait]
trait Trait<T = ()> {
    async fn f(&self) -> &str
    where
        T: 'async_trait,
    {
        "default"
    }
}

The expanded code is:

trait Trait<T = ()> {
    #[must_use]
    fn f<'life0, 'async_trait>(
        &'life0 self,
    ) -> ::core::pin::Pin<
        Box<dyn ::core::future::Future<Output = &str> + ::core::marker::Send + 'async_trait>,
    >
    where
        T: 'async_trait,
        'life0: 'async_trait,
        Self: ::core::marker::Sync + 'async_trait,
    {
        #[allow(
            unused_parens,
            clippy::missing_docs_in_private_items,
            clippy::needless_lifetimes,
            clippy::ptr_arg,
            clippy::trivially_copy_pass_by_ref,
            clippy::type_repetition_in_bounds,
            clippy::used_underscore_binding
        )]
        async fn __f<
            'async_trait,
            T = (),
            AsyncTrait: ?Sized + Trait<T> + ::core::marker::Sync,
        >(
            _self: &AsyncTrait,
        ) -> &str
        where
            (): Sized,
            T: 'async_trait,
        {
            "default"
        }
        Box::pin(__f::<T, Self>(self))
    }
}

And rustc complains with the error:

error: type parameters with a default must be trailing
   --> tests/test.rs:987:17
    |
987 |     trait Trait<T = ()> {
    |                 ^
error: could not compile `async-trait`.

error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
   --> tests/test.rs:987:17
    |
987 |     trait Trait<T = ()> {
    |                 ^
    |
    = note: `#[deny(invalid_type_param_default)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>

Solution

Filter out defaults when reusing trait generics for function definition.