Repository: dtolnay/async-trait (rust)

Issue:
Unsize coercion fails if end of method is unreachable
The following async trait fails to compile. Notice that the same method body is fine in an ordinary async fn outside of an async trait.

This worked prior to #143.

```rust
use async_trait::async_trait;

struct Thing;
trait Ret {}
impl Ret for Thing {}

async fn ok() -> &'static dyn Ret {
    return &Thing;
}

#[async_trait]
trait Trait {
    async fn fail() -> &'static dyn Ret {
        return &Thing;
    }
}
```

```console
error[E0308]: mismatched types
  --> src/main.rs:13:41
   |
13 |       async fn fail() -> &'static dyn Ret {
   |  _________________________________________^
14 | |         return &Thing;
15 | |     }
   | |_____^ expected struct `Thing`, found trait object `dyn Ret`
   |
   = note:   expected type `&Thing`
           found reference `&'static (dyn Ret + 'static)`
note: return type inferred to be `&Thing` here
  --> src/main.rs:14:16
   |
14 |         return &Thing;
   |                ^^^^^^

error[E0271]: type mismatch resolving `<impl Future as Future>::Output == &'static (dyn Ret + 'static)`
  --> src/main.rs:13:41
   |
13 |       async fn fail() -> &'static dyn Ret {
   |  _________________________________________^
14 | |         return &Thing;
15 | |     }
   | |_____^ expected trait object `dyn Ret`, found struct `Thing`
   |
   = note: expected reference `&'static (dyn Ret + 'static)`
              found reference `&Thing`
   = note: required for the cast to the object type `dyn Future<Output = &'static (dyn Ret + 'static)> + Send`
```

Pull request description:
Prepend early return to force unsize coercion
Fixes #149.

Patch:
diff --git a/src/expand.rs b/src/expand.rs
index b0ebb4c..06c4ba3 100644
--- a/src/expand.rs
+++ b/src/expand.rs
@@ -350,6 +350,9 @@ fn transform_block(sig: &mut Signature, block: &mut Block) {
             let _: () = { #(#decls)* #(#stmts)* };
         },
         ReturnType::Type(_, ret) => quote_spanned! {block.brace_token.span=>
+            if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<#ret> {
+                return __ret;
+            }
             let __ret: #ret = { #(#decls)* #(#stmts)* };
             #[allow(unreachable_code)]
             __ret


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index a97af36..06c0918 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1258,3 +1258,23 @@ pub mod issue147 {
         }
     }
 }
+
+// https://github.com/dtolnay/async-trait/issues/149
+pub mod issue149 {
+    use async_trait::async_trait;
+
+    pub struct Thing;
+    pub trait Ret {}
+    impl Ret for Thing {}
+
+    pub async fn ok() -> &'static dyn Ret {
+        return &Thing;
+    }
+
+    #[async_trait]
+    pub trait Trait {
+        async fn fail() -> &'static dyn Ret {
+            return &Thing;
+        }
+    }
+}