Repository: dtolnay/async-trait
Pull request #123 (2020-08-28 13:57:14)

Remove defaults from trait params when using them in function definition
## Synopsis

At the moment, if trait has type/const parameters with default values and also has a default method implementation, like the following:
```rust
#[async_trait]
trait Trait<T = ()> {
    async fn f(&self) -> &str
    where
        T: 'async_trait,
    {
        "default"
    }
}
```

The expanded code is:
```rust
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.


Patch:
diff --git a/src/expand.rs b/src/expand.rs
index 7c3ab5a..304347a 100644
--- a/src/expand.rs
+++ b/src/expand.rs
@@ -284,6 +284,17 @@ fn transform_block(
     };
 
     let mut outer_generics = generics.clone();
+    for p in &mut outer_generics.params {
+        match p {
+            GenericParam::Type(t) => {
+                let _ = t.default.take();
+            }
+            GenericParam::Const(c) => {
+                let _ = c.default.take();
+            }
+            GenericParam::Lifetime(_) => {}
+        }
+    }
     if !has_self {
         if let Some(mut where_clause) = outer_generics.where_clause {
             where_clause.predicates = where_clause


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index 4ecab07..a4e13a3 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -884,7 +884,7 @@ pub mod issue92 {
 }
 
 // https://github.com/dtolnay/async-trait/issues/104
-mod issue104 {
+pub mod issue104 {
     use async_trait::async_trait;
 
     #[async_trait]
@@ -909,7 +909,7 @@ mod issue104 {
 }
 
 // https://github.com/dtolnay/async-trait/issues/106
-mod issue106 {
+pub mod issue106 {
     use async_trait::async_trait;
     use std::future::Future;
 
@@ -941,7 +941,7 @@ mod issue106 {
 }
 
 // https://github.com/dtolnay/async-trait/issues/110
-mod issue110 {
+pub mod issue110 {
     #![deny(clippy::all)]
 
     use async_trait::async_trait;
@@ -963,7 +963,7 @@ mod issue110 {
 }
 
 // https://github.com/dtolnay/async-trait/issues/120
-mod issue120 {
+pub mod issue120 {
     #![deny(clippy::trivially_copy_pass_by_ref)]
 
     use async_trait::async_trait;
@@ -978,3 +978,21 @@ mod issue120 {
         async fn f(&self) {}
     }
 }
+
+// https://github.com/dtolnay/async-trait/pulls/123
+pub mod pull123 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    trait Trait<T = ()> {
+        async fn f(&self) -> &str
+        where
+            T: 'async_trait,
+        {
+            "default"
+        }
+    }
+
+    #[async_trait]
+    impl<T> Trait<T> for () {}
+}