Import async-trait crate.

Bug: 164106399
Bug: 158290206
Test: mm
Change-Id: I0c4a491b785134e4ac1d5572e5ff94b8699dc0bc
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..c4c65e4
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "89923af3d553c990336ec29a68e50e15efff1734"
+  }
+}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..1ee3325
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,34 @@
+name: CI
+
+on:
+  push:
+  pull_request:
+  schedule: [cron: "40 1 * * *"]
+
+jobs:
+  test:
+    name: Rust ${{matrix.rust}}
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        rust: [beta, stable, 1.39.0]
+        include:
+          - rust: nightly
+            rustflags: --cfg async_trait_nightly_testing
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{matrix.rust}}
+      - run: cargo test
+        env:
+          RUSTFLAGS: ${{matrix.rustflags}}
+
+  clippy:
+    name: Clippy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@clippy
+      - run: cargo clippy --tests -- -Dclippy::all
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6936990
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/target
+**/*.rs.bk
+Cargo.lock
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..6e5e11d
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,19 @@
+// This file is generated by cargo2android.py --run --device --dependencies.
+
+rust_proc_macro {
+    name: "libasync_trait",
+    crate_name: "async_trait",
+    srcs: ["src/lib.rs"],
+    edition: "2018",
+    rustlibs: [
+        "libproc_macro2",
+        "libquote",
+        "libsyn",
+    ],
+}
+
+// dependent_library ["feature_list"]
+//   proc-macro2-1.0.19 "default,proc-macro"
+//   quote-1.0.7 "default,proc-macro"
+//   syn-1.0.38 "clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,quote,visit,visit-mut"
+//   unicode-xid-0.2.1 "default"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..675035a
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,51 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "async-trait"
+version = "0.1.36"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+description = "Type erasure for async trait methods"
+documentation = "https://docs.rs/async-trait"
+readme = "README.md"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/async-trait"
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[lib]
+proc-macro = true
+[dependencies.proc-macro2]
+version = "1.0"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.syn]
+version = "1.0"
+features = ["full", "visit-mut"]
+[dev-dependencies.rustversion]
+version = "1.0"
+
+[dev-dependencies.tracing]
+version = "0.1.14"
+
+[dev-dependencies.tracing-attributes]
+version = "0.1.8"
+
+[dev-dependencies.tracing-futures]
+version = "0.2"
+
+[dev-dependencies.trybuild]
+version = "1.0.19"
+features = ["diff"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..2921a5f
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,28 @@
+[package]
+name = "async-trait"
+version = "0.1.36"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "Type erasure for async trait methods"
+repository = "https://github.com/dtolnay/async-trait"
+documentation = "https://docs.rs/async-trait"
+readme = "README.md"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1.0"
+quote = "1.0"
+syn = { version = "1.0", features = ["full", "visit-mut"] }
+
+[dev-dependencies]
+rustversion = "1.0"
+tracing = "0.1.14"
+tracing-attributes = "0.1.8"
+tracing-futures = "0.2"
+trybuild = { version = "1.0.19", features = ["diff"] }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/LICENSE b/LICENSE
new file mode 120000
index 0000000..6b579aa
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+LICENSE-APACHE
\ No newline at end of file
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..31aa793
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..889b98f
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "async-trait"
+description: "Async trait methods."
+third_party {
+  url {
+    type: HOMEPAGE
+    value: "https://crates.io/crates/async-trait"
+  }
+  url {
+    type: GIT
+    value: "https://github.com/dtolnay/async-trait"
+  }
+  version: "0.1.36"
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2020
+    month: 8
+    day: 11
+  }
+}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7d3e050
--- /dev/null
+++ b/README.md
@@ -0,0 +1,262 @@
+Async trait methods
+===================
+
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/async--trait-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/async-trait)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/async-trait.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/async-trait)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-async--trait-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/async-trait)
+[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/async-trait/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/async-trait/actions?query=branch%3Amaster)
+
+The initial round of stabilizations for the async/await language feature in Rust
+1.39 did not include support for async fn in traits. Trying to include an async
+fn in a trait produces the following error:
+
+```rust
+trait MyTrait {
+    async fn f() {}
+}
+```
+
+```console
+error[E0706]: trait fns cannot be declared `async`
+ --> src/main.rs:4:5
+  |
+4 |     async fn f() {}
+  |     ^^^^^^^^^^^^^^^
+```
+
+This crate provides an attribute macro to make async fn in traits work.
+
+Please refer to [*why async fn in traits are hard*][hard] for a deeper analysis
+of how this implementation differs from what the compiler and language hope to
+deliver in the future.
+
+[hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
+
+<br>
+
+## Example
+
+This example implements the core of a highly effective advertising platform
+using async fn in a trait.
+
+The only thing to notice here is that we write an `#[async_trait]` macro on top
+of traits and trait impls that contain async fn, and then they work.
+
+```rust
+use async_trait::async_trait;
+
+#[async_trait]
+trait Advertisement {
+    async fn run(&self);
+}
+
+struct Modal;
+
+#[async_trait]
+impl Advertisement for Modal {
+    async fn run(&self) {
+        self.render_fullscreen().await;
+        for _ in 0..4u16 {
+            remind_user_to_join_mailing_list().await;
+        }
+        self.hide_for_now().await;
+    }
+}
+
+struct AutoplayingVideo {
+    media_url: String,
+}
+
+#[async_trait]
+impl Advertisement for AutoplayingVideo {
+    async fn run(&self) {
+        let stream = connect(&self.media_url).await;
+        stream.play().await;
+
+        // Video probably persuaded user to join our mailing list!
+        Modal.run().await;
+    }
+}
+```
+
+<br>
+
+## Supported features
+
+It is the intention that all features of Rust traits should work nicely with
+\#\[async_trait\], but the edge cases are numerous. *Please file an issue if you
+see unexpected borrow checker errors, type errors, or warnings.* There is no use
+of `unsafe` in the expanded code, so rest assured that if your code compiles it
+can't be that badly broken.
+
+- &#128077;&ensp;Self by value, by reference, by mut reference, or no self;
+- &#128077;&ensp;Any number of arguments, any return value;
+- &#128077;&ensp;Generic type parameters and lifetime parameters;
+- &#128077;&ensp;Associated types;
+- &#128077;&ensp;Having async and non-async functions in the same trait;
+- &#128077;&ensp;Default implementations provided by the trait;
+- &#128077;&ensp;Elided lifetimes;
+- &#128077;&ensp;Dyn-capable traits.
+
+<br>
+
+## Explanation
+
+Async fns get transformed into methods that return `Pin<Box<dyn Future + Send +
+'async>>` and delegate to a private async freestanding function.
+
+For example the `impl Advertisement for AutoplayingVideo` above would be
+expanded as:
+
+```rust
+impl Advertisement for AutoplayingVideo {
+    fn run<'async>(
+        &'async self,
+    ) -> Pin<Box<dyn std::future::Future<Output = ()> + Send + 'async>>
+    where
+        Self: Sync + 'async,
+    {
+        async fn run(_self: &AutoplayingVideo) {
+            /* the original method body */
+        }
+
+        Box::pin(run(self))
+    }
+}
+```
+
+<br>
+
+## Non-threadsafe futures
+
+Not all async traits need futures that are `dyn Future + Send`. To avoid having
+Send and Sync bounds placed on the async trait methods, invoke the async trait
+macro as `#[async_trait(?Send)]` on both the trait and the impl blocks.
+
+<br>
+
+## Elided lifetimes
+
+Be aware that async fn syntax does not allow lifetime elision outside of `&` and
+`&mut` references. (This is true even when not using #\[async_trait\].)
+Lifetimes must be named or marked by the placeholder `'_`.
+
+Fortunately the compiler is able to diagnose missing lifetimes with a good error
+message.
+
+```rust
+type Elided<'a> = &'a usize;
+
+#[async_trait]
+trait Test {
+    async fn test(not_okay: Elided, okay: &usize) {}
+}
+```
+
+```console
+error[E0726]: implicit elided lifetime not allowed here
+ --> src/main.rs:9:29
+  |
+9 |     async fn test(not_okay: Elided, okay: &usize) {}
+  |                             ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+```
+
+The fix is to name the lifetime or use `'_`.
+
+```rust
+#[async_trait]
+trait Test {
+    // either
+    async fn test<'e>(elided: Elided<'e>) {}
+    // or
+    async fn test(elided: Elided<'_>) {}
+}
+```
+
+<br>
+
+## Dyn traits
+
+Traits with async methods can be used as trait objects as long as they meet the
+usual requirements for dyn -- no methods with type parameters, no self by value,
+no associated types, etc.
+
+```rust
+#[async_trait]
+pub trait ObjectSafe {
+    async fn f(&self);
+    async fn g(&mut self);
+}
+
+impl ObjectSafe for MyType {...}
+
+let value: MyType = ...;
+let object = &value as &dyn ObjectSafe;  // make trait object
+```
+
+The one wrinkle is in traits that provide default implementations of async
+methods. In order for the default implementation to produce a future that is
+Send, the async\_trait macro must emit a bound of `Self: Sync` on trait methods
+that take `&self` and a bound `Self: Send` on trait methods that take `&mut
+self`. An example of the former is visible in the expanded code in the
+explanation section above.
+
+If you make a trait with async methods that have default implementations,
+everything will work except that the trait cannot be used as a trait object.
+Creating a value of type `&dyn Trait` will produce an error that looks like
+this:
+
+```console
+error: the trait `Test` cannot be made into an object
+ --> src/main.rs:8:5
+  |
+8 |     async fn cannot_dyn(&self) {}
+  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+```
+
+For traits that need to be object safe and need to have default implementations
+for some async methods, there are two resolutions. Either you can add Send
+and/or Sync as supertraits (Send if there are `&mut self` methods with default
+implementations, Sync if there are `&self` methods with default implementions)
+to constrain all implementors of the trait such that the default implementations
+are applicable to them:
+
+```rust
+#[async_trait]
+pub trait ObjectSafe: Sync {  // added supertrait
+    async fn can_dyn(&self) {}
+}
+
+let object = &value as &dyn ObjectSafe;
+```
+
+or you can strike the problematic methods from your trait object by bounding
+them with `Self: Sized`:
+
+```rust
+#[async_trait]
+pub trait ObjectSafe {
+    async fn cannot_dyn(&self) where Self: Sized {}
+
+    // presumably other methods
+}
+
+let object = &value as &dyn ObjectSafe;
+```
+
+<br>
+
+#### License
+
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+</sup>
+
+<br>
+
+<sub>
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
+</sub>
diff --git a/src/args.rs b/src/args.rs
new file mode 100644
index 0000000..72d97e9
--- /dev/null
+++ b/src/args.rs
@@ -0,0 +1,36 @@
+use proc_macro2::Span;
+use syn::parse::{Error, Parse, ParseStream, Result};
+use syn::Token;
+
+#[derive(Copy, Clone)]
+pub struct Args {
+    pub local: bool,
+}
+
+mod kw {
+    syn::custom_keyword!(Send);
+}
+
+impl Parse for Args {
+    fn parse(input: ParseStream) -> Result<Self> {
+        match try_parse(input) {
+            Ok(args) if input.is_empty() => Ok(args),
+            _ => Err(error()),
+        }
+    }
+}
+
+fn try_parse(input: ParseStream) -> Result<Args> {
+    if input.peek(Token![?]) {
+        input.parse::<Token![?]>()?;
+        input.parse::<kw::Send>()?;
+        Ok(Args { local: true })
+    } else {
+        Ok(Args { local: false })
+    }
+}
+
+fn error() -> Error {
+    let msg = "expected #[async_trait] or #[async_trait(?Send)]";
+    Error::new(Span::call_site(), msg)
+}
diff --git a/src/expand.rs b/src/expand.rs
new file mode 100644
index 0000000..7d0cec2
--- /dev/null
+++ b/src/expand.rs
@@ -0,0 +1,475 @@
+use crate::lifetime::{has_async_lifetime, CollectLifetimes};
+use crate::parse::Item;
+use crate::receiver::{
+    has_self_in_block, has_self_in_sig, has_self_in_where_predicate, ReplaceReceiver,
+};
+use proc_macro2::{Span, TokenStream};
+use quote::{format_ident, quote, quote_spanned, ToTokens};
+use std::mem;
+use syn::punctuated::Punctuated;
+use syn::visit_mut::VisitMut;
+use syn::{
+    parse_quote, Block, FnArg, GenericParam, Generics, Ident, ImplItem, Lifetime, Pat, PatIdent,
+    Path, Receiver, ReturnType, Signature, Stmt, Token, TraitItem, Type, TypeParam, TypeParamBound,
+    WhereClause,
+};
+
+impl ToTokens for Item {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        match self {
+            Item::Trait(item) => item.to_tokens(tokens),
+            Item::Impl(item) => item.to_tokens(tokens),
+        }
+    }
+}
+
+#[derive(Clone, Copy)]
+enum Context<'a> {
+    Trait {
+        name: &'a Ident,
+        generics: &'a Generics,
+        supertraits: &'a Supertraits,
+    },
+    Impl {
+        impl_generics: &'a Generics,
+        receiver: &'a Type,
+        as_trait: &'a Path,
+    },
+}
+
+impl Context<'_> {
+    fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a GenericParam> {
+        let generics = match self {
+            Context::Trait { generics, .. } => generics,
+            Context::Impl { impl_generics, .. } => impl_generics,
+        };
+        generics.params.iter().filter(move |param| {
+            if let GenericParam::Lifetime(param) = param {
+                used.contains(&param.lifetime)
+            } else {
+                false
+            }
+        })
+    }
+}
+
+type Supertraits = Punctuated<TypeParamBound, Token![+]>;
+
+pub fn expand(input: &mut Item, is_local: bool) {
+    match input {
+        Item::Trait(input) => {
+            let context = Context::Trait {
+                name: &input.ident,
+                generics: &input.generics,
+                supertraits: &input.supertraits,
+            };
+            for inner in &mut input.items {
+                if let TraitItem::Method(method) = inner {
+                    let sig = &mut method.sig;
+                    if sig.asyncness.is_some() {
+                        let block = &mut method.default;
+                        let mut has_self = has_self_in_sig(sig);
+                        if let Some(block) = block {
+                            has_self |= has_self_in_block(block);
+                            transform_block(context, sig, block, has_self, is_local);
+                        }
+                        let has_default = method.default.is_some();
+                        transform_sig(context, sig, has_self, has_default, is_local);
+                        method.attrs.push(parse_quote!(#[must_use]));
+                    }
+                }
+            }
+        }
+        Item::Impl(input) => {
+            let mut lifetimes = CollectLifetimes::new("'impl");
+            lifetimes.visit_type_mut(&mut *input.self_ty);
+            lifetimes.visit_path_mut(&mut input.trait_.as_mut().unwrap().1);
+            let params = &input.generics.params;
+            let elided = lifetimes.elided;
+            input.generics.params = parse_quote!(#(#elided,)* #params);
+
+            let context = Context::Impl {
+                impl_generics: &input.generics,
+                receiver: &input.self_ty,
+                as_trait: &input.trait_.as_ref().unwrap().1,
+            };
+            for inner in &mut input.items {
+                if let ImplItem::Method(method) = inner {
+                    let sig = &mut method.sig;
+                    if sig.asyncness.is_some() {
+                        let block = &mut method.block;
+                        let has_self = has_self_in_sig(sig) || has_self_in_block(block);
+                        transform_block(context, sig, block, has_self, is_local);
+                        transform_sig(context, sig, has_self, false, is_local);
+                    }
+                }
+            }
+        }
+    }
+}
+
+// Input:
+//     async fn f<T>(&self, x: &T) -> Ret;
+//
+// Output:
+//     fn f<'life0, 'life1, 'async_trait, T>(
+//         &'life0 self,
+//         x: &'life1 T,
+//     ) -> Pin<Box<dyn Future<Output = Ret> + Send + 'async_trait>>
+//     where
+//         'life0: 'async_trait,
+//         'life1: 'async_trait,
+//         T: 'async_trait,
+//         Self: Sync + 'async_trait;
+fn transform_sig(
+    context: Context,
+    sig: &mut Signature,
+    has_self: bool,
+    has_default: bool,
+    is_local: bool,
+) {
+    sig.fn_token.span = sig.asyncness.take().unwrap().span;
+
+    let ret = match &sig.output {
+        ReturnType::Default => quote!(()),
+        ReturnType::Type(_, ret) => quote!(#ret),
+    };
+
+    let mut lifetimes = CollectLifetimes::new("'life");
+    for arg in sig.inputs.iter_mut() {
+        match arg {
+            FnArg::Receiver(arg) => lifetimes.visit_receiver_mut(arg),
+            FnArg::Typed(arg) => lifetimes.visit_type_mut(&mut arg.ty),
+        }
+    }
+
+    let where_clause = sig
+        .generics
+        .where_clause
+        .get_or_insert_with(|| WhereClause {
+            where_token: Default::default(),
+            predicates: Punctuated::new(),
+        });
+    for param in sig
+        .generics
+        .params
+        .iter()
+        .chain(context.lifetimes(&lifetimes.explicit))
+    {
+        match param {
+            GenericParam::Type(param) => {
+                let param = &param.ident;
+                where_clause
+                    .predicates
+                    .push(parse_quote!(#param: 'async_trait));
+            }
+            GenericParam::Lifetime(param) => {
+                let param = &param.lifetime;
+                where_clause
+                    .predicates
+                    .push(parse_quote!(#param: 'async_trait));
+            }
+            GenericParam::Const(_) => {}
+        }
+    }
+    for elided in lifetimes.elided {
+        sig.generics.params.push(parse_quote!(#elided));
+        where_clause
+            .predicates
+            .push(parse_quote!(#elided: 'async_trait));
+    }
+    sig.generics.params.push(parse_quote!('async_trait));
+    if has_self {
+        let bound: Ident = match sig.inputs.iter().next() {
+            Some(FnArg::Receiver(Receiver {
+                reference: Some(_),
+                mutability: None,
+                ..
+            })) => parse_quote!(Sync),
+            Some(FnArg::Typed(arg))
+                if match (arg.pat.as_ref(), arg.ty.as_ref()) {
+                    (Pat::Ident(pat), Type::Reference(ty)) => {
+                        pat.ident == "self" && ty.mutability.is_none()
+                    }
+                    _ => false,
+                } =>
+            {
+                parse_quote!(Sync)
+            }
+            _ => parse_quote!(Send),
+        };
+        let assume_bound = match context {
+            Context::Trait { supertraits, .. } => !has_default || has_bound(supertraits, &bound),
+            Context::Impl { .. } => true,
+        };
+        where_clause.predicates.push(if assume_bound || is_local {
+            parse_quote!(Self: 'async_trait)
+        } else {
+            parse_quote!(Self: ::core::marker::#bound + 'async_trait)
+        });
+    }
+
+    for (i, arg) in sig.inputs.iter_mut().enumerate() {
+        match arg {
+            FnArg::Receiver(Receiver {
+                reference: Some(_), ..
+            }) => {}
+            FnArg::Receiver(arg) => arg.mutability = None,
+            FnArg::Typed(arg) => {
+                if let Pat::Ident(ident) = &mut *arg.pat {
+                    ident.by_ref = None;
+                    ident.mutability = None;
+                } else {
+                    let positional = positional_arg(i);
+                    *arg.pat = parse_quote!(#positional);
+                }
+            }
+        }
+    }
+
+    let bounds = if is_local {
+        quote!('async_trait)
+    } else {
+        quote!(::core::marker::Send + 'async_trait)
+    };
+
+    sig.output = parse_quote! {
+        -> ::core::pin::Pin<Box<
+            dyn ::core::future::Future<Output = #ret> + #bounds
+        >>
+    };
+}
+
+// Input:
+//     async fn f<T>(&self, x: &T) -> Ret {
+//         self + x
+//     }
+//
+// Output:
+//     async fn f<T, AsyncTrait>(_self: &AsyncTrait, x: &T) -> Ret {
+//         _self + x
+//     }
+//     Box::pin(async_trait_method::<T, Self>(self, x))
+fn transform_block(
+    context: Context,
+    sig: &mut Signature,
+    block: &mut Block,
+    has_self: bool,
+    is_local: bool,
+) {
+    if let Some(Stmt::Item(syn::Item::Verbatim(item))) = block.stmts.first() {
+        if block.stmts.len() == 1 && item.to_string() == ";" {
+            return;
+        }
+    }
+
+    let inner = format_ident!("__{}", sig.ident);
+    let args = sig.inputs.iter().enumerate().map(|(i, arg)| match arg {
+        FnArg::Receiver(Receiver { self_token, .. }) => quote!(#self_token),
+        FnArg::Typed(arg) => {
+            if let Pat::Ident(PatIdent { ident, .. }) = &*arg.pat {
+                quote!(#ident)
+            } else {
+                positional_arg(i).into_token_stream()
+            }
+        }
+    });
+
+    let mut standalone = sig.clone();
+    standalone.ident = inner.clone();
+
+    let generics = match context {
+        Context::Trait { generics, .. } => generics,
+        Context::Impl { impl_generics, .. } => impl_generics,
+    };
+
+    let mut outer_generics = generics.clone();
+    if !has_self {
+        if let Some(mut where_clause) = outer_generics.where_clause {
+            where_clause.predicates = where_clause
+                .predicates
+                .into_iter()
+                .filter_map(|mut pred| {
+                    if has_self_in_where_predicate(&mut pred) {
+                        None
+                    } else {
+                        Some(pred)
+                    }
+                })
+                .collect();
+            outer_generics.where_clause = Some(where_clause);
+        }
+    }
+
+    let fn_generics = mem::replace(&mut standalone.generics, outer_generics);
+    standalone.generics.params.extend(fn_generics.params);
+    if let Some(where_clause) = fn_generics.where_clause {
+        standalone
+            .generics
+            .make_where_clause()
+            .predicates
+            .extend(where_clause.predicates);
+    }
+
+    if has_async_lifetime(&mut standalone, block) {
+        standalone.generics.params.push(parse_quote!('async_trait));
+    }
+
+    let mut types = standalone
+        .generics
+        .type_params()
+        .map(|param| param.ident.clone())
+        .collect::<Vec<_>>();
+
+    let mut self_bound = None::<TypeParamBound>;
+    match standalone.inputs.iter_mut().next() {
+        Some(
+            arg @ FnArg::Receiver(Receiver {
+                reference: Some(_), ..
+            }),
+        ) => {
+            let (lifetime, mutability, self_token) = match arg {
+                FnArg::Receiver(Receiver {
+                    reference: Some((_, lifetime)),
+                    mutability,
+                    self_token,
+                    ..
+                }) => (lifetime, mutability, self_token),
+                _ => unreachable!(),
+            };
+            let under_self = Ident::new("_self", self_token.span);
+            match context {
+                Context::Trait { .. } => {
+                    self_bound = Some(match mutability {
+                        Some(_) => parse_quote!(::core::marker::Send),
+                        None => parse_quote!(::core::marker::Sync),
+                    });
+                    *arg = parse_quote! {
+                        #under_self: &#lifetime #mutability AsyncTrait
+                    };
+                }
+                Context::Impl { receiver, .. } => {
+                    let mut ty = quote!(#receiver);
+                    if let Type::TraitObject(trait_object) = receiver {
+                        if trait_object.dyn_token.is_none() {
+                            ty = quote!(dyn #ty);
+                        }
+                        if trait_object.bounds.len() > 1 {
+                            ty = quote!((#ty));
+                        }
+                    }
+                    *arg = parse_quote! {
+                        #under_self: &#lifetime #mutability #ty
+                    };
+                }
+            }
+        }
+        Some(arg @ FnArg::Receiver(_)) => {
+            let (self_token, mutability) = match arg {
+                FnArg::Receiver(Receiver {
+                    self_token,
+                    mutability,
+                    ..
+                }) => (self_token, mutability),
+                _ => unreachable!(),
+            };
+            let under_self = Ident::new("_self", self_token.span);
+            match context {
+                Context::Trait { .. } => {
+                    self_bound = Some(parse_quote!(::core::marker::Send));
+                    *arg = parse_quote! {
+                        #mutability #under_self: AsyncTrait
+                    };
+                }
+                Context::Impl { receiver, .. } => {
+                    *arg = parse_quote! {
+                        #mutability #under_self: #receiver
+                    };
+                }
+            }
+        }
+        Some(FnArg::Typed(arg)) => {
+            if let Pat::Ident(arg) = &mut *arg.pat {
+                if arg.ident == "self" {
+                    arg.ident = Ident::new("_self", arg.ident.span());
+                }
+            }
+        }
+        _ => {}
+    }
+
+    if let Context::Trait { name, generics, .. } = context {
+        if has_self {
+            let (_, generics, _) = generics.split_for_impl();
+            let mut self_param: TypeParam = parse_quote!(AsyncTrait: ?Sized + #name #generics);
+            if !is_local {
+                self_param.bounds.extend(self_bound);
+            }
+            standalone
+                .generics
+                .params
+                .push(GenericParam::Type(self_param));
+            types.push(Ident::new("Self", Span::call_site()));
+        }
+    }
+
+    if let Some(where_clause) = &mut standalone.generics.where_clause {
+        // Work around an input bound like `where Self::Output: Send` expanding
+        // to `where <AsyncTrait>::Output: Send` which is illegal syntax because
+        // `where<T>` is reserved for future use... :(
+        where_clause.predicates.insert(0, parse_quote!((): Sized));
+    }
+
+    let mut replace = match context {
+        Context::Trait { .. } => ReplaceReceiver::with(parse_quote!(AsyncTrait)),
+        Context::Impl {
+            receiver, as_trait, ..
+        } => ReplaceReceiver::with_as_trait(receiver.clone(), as_trait.clone()),
+    };
+    replace.visit_signature_mut(&mut standalone);
+    replace.visit_block_mut(block);
+
+    let mut generics = types;
+    let consts = standalone
+        .generics
+        .const_params()
+        .map(|param| param.ident.clone());
+    generics.extend(consts);
+
+    let allow_non_snake_case = if sig.ident != sig.ident.to_string().to_lowercase() {
+        Some(quote!(non_snake_case,))
+    } else {
+        None
+    };
+
+    let brace = block.brace_token;
+    let box_pin = quote_spanned!(brace.span=> {
+        #[allow(
+            #allow_non_snake_case
+            clippy::missing_docs_in_private_items,
+            clippy::needless_lifetimes,
+            clippy::ptr_arg,
+            clippy::type_repetition_in_bounds,
+            clippy::used_underscore_binding,
+        )]
+        #standalone #block
+        Box::pin(#inner::<#(#generics),*>(#(#args),*))
+    });
+    *block = parse_quote!(#box_pin);
+    block.brace_token = brace;
+}
+
+fn positional_arg(i: usize) -> Ident {
+    format_ident!("__arg{}", i)
+}
+
+fn has_bound(supertraits: &Supertraits, marker: &Ident) -> bool {
+    for bound in supertraits {
+        if let TypeParamBound::Trait(bound) = bound {
+            if bound.path.is_ident(marker) {
+                return true;
+            }
+        }
+    }
+    false
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..f0102d8
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,328 @@
+//! [![github]](https://github.com/dtolnay/async-trait)&ensp;[![crates-io]](https://crates.io/crates/async-trait)&ensp;[![docs-rs]](https://docs.rs/async-trait)
+//!
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
+//!
+//! <br>
+//!
+//! <h5>Type erasure for async trait methods</h5>
+//!
+//! The initial round of stabilizations for the async/await language feature in
+//! Rust 1.39 did not include support for async fn in traits. Trying to include
+//! an async fn in a trait produces the following error:
+//!
+//! ```compile_fail
+//! trait MyTrait {
+//!     async fn f() {}
+//! }
+//! ```
+//!
+//! ```text
+//! error[E0706]: trait fns cannot be declared `async`
+//!  --> src/main.rs:4:5
+//!   |
+//! 4 |     async fn f() {}
+//!   |     ^^^^^^^^^^^^^^^
+//! ```
+//!
+//! This crate provides an attribute macro to make async fn in traits work.
+//!
+//! Please refer to [*why async fn in traits are hard*][hard] for a deeper
+//! analysis of how this implementation differs from what the compiler and
+//! language hope to deliver in the future.
+//!
+//! [hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
+//!
+//! <br>
+//!
+//! # Example
+//!
+//! This example implements the core of a highly effective advertising platform
+//! using async fn in a trait.
+//!
+//! The only thing to notice here is that we write an `#[async_trait]` macro on
+//! top of traits and trait impls that contain async fn, and then they work.
+//!
+//! ```
+//! use async_trait::async_trait;
+//!
+//! #[async_trait]
+//! trait Advertisement {
+//!     async fn run(&self);
+//! }
+//!
+//! struct Modal;
+//!
+//! #[async_trait]
+//! impl Advertisement for Modal {
+//!     async fn run(&self) {
+//!         self.render_fullscreen().await;
+//!         for _ in 0..4u16 {
+//!             remind_user_to_join_mailing_list().await;
+//!         }
+//!         self.hide_for_now().await;
+//!     }
+//! }
+//!
+//! struct AutoplayingVideo {
+//!     media_url: String,
+//! }
+//!
+//! #[async_trait]
+//! impl Advertisement for AutoplayingVideo {
+//!     async fn run(&self) {
+//!         let stream = connect(&self.media_url).await;
+//!         stream.play().await;
+//!
+//!         // Video probably persuaded user to join our mailing list!
+//!         Modal.run().await;
+//!     }
+//! }
+//! #
+//! # impl Modal {
+//! #     async fn render_fullscreen(&self) {}
+//! #     async fn hide_for_now(&self) {}
+//! # }
+//! #
+//! # async fn remind_user_to_join_mailing_list() {}
+//! #
+//! # struct Stream;
+//! # async fn connect(_media_url: &str) -> Stream { Stream }
+//! # impl Stream {
+//! #     async fn play(&self) {}
+//! # }
+//! ```
+//!
+//! <br><br>
+//!
+//! # Supported features
+//!
+//! It is the intention that all features of Rust traits should work nicely with
+//! #\[async_trait\], but the edge cases are numerous. Please file an issue if
+//! you see unexpected borrow checker errors, type errors, or warnings. There is
+//! no use of `unsafe` in the expanded code, so rest assured that if your code
+//! compiles it can't be that badly broken.
+//!
+//! > &#9745;&emsp;Self by value, by reference, by mut reference, or no self;<br>
+//! > &#9745;&emsp;Any number of arguments, any return value;<br>
+//! > &#9745;&emsp;Generic type parameters and lifetime parameters;<br>
+//! > &#9745;&emsp;Associated types;<br>
+//! > &#9745;&emsp;Having async and non-async functions in the same trait;<br>
+//! > &#9745;&emsp;Default implementations provided by the trait;<br>
+//! > &#9745;&emsp;Elided lifetimes;<br>
+//! > &#9745;&emsp;Dyn-capable traits.<br>
+//!
+//! <br>
+//!
+//! # Explanation
+//!
+//! Async fns get transformed into methods that return `Pin<Box<dyn Future +
+//! Send + 'async>>` and delegate to a private async freestanding function.
+//!
+//! For example the `impl Advertisement for AutoplayingVideo` above would be
+//! expanded as:
+//!
+//! ```
+//! # const IGNORE: &str = stringify! {
+//! impl Advertisement for AutoplayingVideo {
+//!     fn run<'async>(
+//!         &'async self,
+//!     ) -> Pin<Box<dyn core::future::Future<Output = ()> + Send + 'async>>
+//!     where
+//!         Self: Sync + 'async,
+//!     {
+//!         async fn run(_self: &AutoplayingVideo) {
+//!             /* the original method body */
+//!         }
+//!
+//!         Box::pin(run(self))
+//!     }
+//! }
+//! # };
+//! ```
+//!
+//! <br><br>
+//!
+//! # Non-threadsafe futures
+//!
+//! Not all async traits need futures that are `dyn Future + Send`. To avoid
+//! having Send and Sync bounds placed on the async trait methods, invoke the
+//! async trait macro as `#[async_trait(?Send)]` on both the trait and the impl
+//! blocks.
+//!
+//! <br>
+//!
+//! # Elided lifetimes
+//!
+//! Be aware that async fn syntax does not allow lifetime elision outside of `&`
+//! and `&mut` references. (This is true even when not using #\[async_trait\].)
+//! Lifetimes must be named or marked by the placeholder `'_`.
+//!
+//! Fortunately the compiler is able to diagnose missing lifetimes with a good
+//! error message.
+//!
+//! ```compile_fail
+//! # use async_trait::async_trait;
+//! #
+//! type Elided<'a> = &'a usize;
+//!
+//! #[async_trait]
+//! trait Test {
+//!     async fn test(not_okay: Elided, okay: &usize) {}
+//! }
+//! ```
+//!
+//! ```text
+//! error[E0726]: implicit elided lifetime not allowed here
+//!  --> src/main.rs:9:29
+//!   |
+//! 9 |     async fn test(not_okay: Elided, okay: &usize) {}
+//!   |                             ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+//! ```
+//!
+//! The fix is to name the lifetime or use `'_`.
+//!
+//! ```
+//! # use async_trait::async_trait;
+//! #
+//! # type Elided<'a> = &'a usize;
+//! #
+//! #[async_trait]
+//! trait Test {
+//!     // either
+//!     async fn test<'e>(elided: Elided<'e>) {}
+//! # }
+//! # #[async_trait]
+//! # trait Test2 {
+//!     // or
+//!     async fn test(elided: Elided<'_>) {}
+//! }
+//! ```
+//!
+//! <br><br>
+//!
+//! # Dyn traits
+//!
+//! Traits with async methods can be used as trait objects as long as they meet
+//! the usual requirements for dyn -- no methods with type parameters, no self
+//! by value, no associated types, etc.
+//!
+//! ```
+//! # use async_trait::async_trait;
+//! #
+//! #[async_trait]
+//! pub trait ObjectSafe {
+//!     async fn f(&self);
+//!     async fn g(&mut self);
+//! }
+//!
+//! # const IGNORE: &str = stringify! {
+//! impl ObjectSafe for MyType {...}
+//!
+//! let value: MyType = ...;
+//! # };
+//! #
+//! # struct MyType;
+//! #
+//! # #[async_trait]
+//! # impl ObjectSafe for MyType {
+//! #     async fn f(&self) {}
+//! #     async fn g(&mut self) {}
+//! # }
+//! #
+//! # let value: MyType = MyType;
+//! let object = &value as &dyn ObjectSafe;  // make trait object
+//! ```
+//!
+//! The one wrinkle is in traits that provide default implementations of async
+//! methods. In order for the default implementation to produce a future that is
+//! Send, the async_trait macro must emit a bound of `Self: Sync` on trait
+//! methods that take `&self` and a bound `Self: Send` on trait methods that
+//! take `&mut self`. An example of the former is visible in the expanded code
+//! in the explanation section above.
+//!
+//! If you make a trait with async methods that have default implementations,
+//! everything will work except that the trait cannot be used as a trait object.
+//! Creating a value of type `&dyn Trait` will produce an error that looks like
+//! this:
+//!
+//! ```text
+//! error: the trait `Test` cannot be made into an object
+//!  --> src/main.rs:8:5
+//!   |
+//! 8 |     async fn cannot_dyn(&self) {}
+//!   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//! ```
+//!
+//! For traits that need to be object safe and need to have default
+//! implementations for some async methods, there are two resolutions. Either
+//! you can add Send and/or Sync as supertraits (Send if there are `&mut self`
+//! methods with default implementations, Sync if there are `&self` methods with
+//! default implementions) to constrain all implementors of the trait such that
+//! the default implementations are applicable to them:
+//!
+//! ```
+//! # use async_trait::async_trait;
+//! #
+//! #[async_trait]
+//! pub trait ObjectSafe: Sync {  // added supertrait
+//!     async fn can_dyn(&self) {}
+//! }
+//! #
+//! # struct MyType;
+//! #
+//! # #[async_trait]
+//! # impl ObjectSafe for MyType {}
+//! #
+//! # let value = MyType;
+//!
+//! let object = &value as &dyn ObjectSafe;
+//! ```
+//!
+//! or you can strike the problematic methods from your trait object by
+//! bounding them with `Self: Sized`:
+//!
+//! ```
+//! # use async_trait::async_trait;
+//! #
+//! #[async_trait]
+//! pub trait ObjectSafe {
+//!     async fn cannot_dyn(&self) where Self: Sized {}
+//!
+//!     // presumably other methods
+//! }
+//! #
+//! # struct MyType;
+//! #
+//! # #[async_trait]
+//! # impl ObjectSafe for MyType {}
+//! #
+//! # let value = MyType;
+//!
+//! let object = &value as &dyn ObjectSafe;
+//! ```
+
+extern crate proc_macro;
+
+mod args;
+mod expand;
+mod lifetime;
+mod parse;
+mod receiver;
+mod respan;
+
+use crate::args::Args;
+use crate::expand::expand;
+use crate::parse::Item;
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::parse_macro_input;
+
+#[proc_macro_attribute]
+pub fn async_trait(args: TokenStream, input: TokenStream) -> TokenStream {
+    let args = parse_macro_input!(args as Args);
+    let mut item = parse_macro_input!(input as Item);
+    expand(&mut item, args.local);
+    TokenStream::from(quote!(#item))
+}
diff --git a/src/lifetime.rs b/src/lifetime.rs
new file mode 100644
index 0000000..9d2066b
--- /dev/null
+++ b/src/lifetime.rs
@@ -0,0 +1,80 @@
+use proc_macro2::Span;
+use syn::visit_mut::{self, VisitMut};
+use syn::{Block, GenericArgument, Item, Lifetime, Receiver, Signature, TypeReference};
+
+pub fn has_async_lifetime(sig: &mut Signature, block: &mut Block) -> bool {
+    let mut visitor = HasAsyncLifetime(false);
+    visitor.visit_signature_mut(sig);
+    visitor.visit_block_mut(block);
+    visitor.0
+}
+
+struct HasAsyncLifetime(bool);
+
+impl VisitMut for HasAsyncLifetime {
+    fn visit_lifetime_mut(&mut self, life: &mut Lifetime) {
+        self.0 |= life.to_string() == "'async_trait";
+    }
+
+    fn visit_item_mut(&mut self, _: &mut Item) {
+        // Do not recurse into nested items.
+    }
+}
+
+pub struct CollectLifetimes {
+    pub elided: Vec<Lifetime>,
+    pub explicit: Vec<Lifetime>,
+    pub name: &'static str,
+}
+
+impl CollectLifetimes {
+    pub fn new(name: &'static str) -> Self {
+        CollectLifetimes {
+            elided: Vec::new(),
+            explicit: Vec::new(),
+            name,
+        }
+    }
+
+    fn visit_opt_lifetime(&mut self, lifetime: &mut Option<Lifetime>) {
+        match lifetime {
+            None => *lifetime = Some(self.next_lifetime()),
+            Some(lifetime) => self.visit_lifetime(lifetime),
+        }
+    }
+
+    fn visit_lifetime(&mut self, lifetime: &mut Lifetime) {
+        if lifetime.ident == "_" {
+            *lifetime = self.next_lifetime();
+        } else {
+            self.explicit.push(lifetime.clone());
+        }
+    }
+
+    fn next_lifetime(&mut self) -> Lifetime {
+        let name = format!("{}{}", self.name, self.elided.len());
+        let life = Lifetime::new(&name, Span::call_site());
+        self.elided.push(life.clone());
+        life
+    }
+}
+
+impl VisitMut for CollectLifetimes {
+    fn visit_receiver_mut(&mut self, arg: &mut Receiver) {
+        if let Some((_, lifetime)) = &mut arg.reference {
+            self.visit_opt_lifetime(lifetime);
+        }
+    }
+
+    fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
+        self.visit_opt_lifetime(&mut ty.lifetime);
+        visit_mut::visit_type_reference_mut(self, ty);
+    }
+
+    fn visit_generic_argument_mut(&mut self, gen: &mut GenericArgument) {
+        if let GenericArgument::Lifetime(lifetime) = gen {
+            self.visit_lifetime(lifetime);
+        }
+        visit_mut::visit_generic_argument_mut(self, gen);
+    }
+}
diff --git a/src/parse.rs b/src/parse.rs
new file mode 100644
index 0000000..ebd2535
--- /dev/null
+++ b/src/parse.rs
@@ -0,0 +1,34 @@
+use proc_macro2::Span;
+use syn::parse::{Error, Parse, ParseStream, Result};
+use syn::{Attribute, ItemImpl, ItemTrait, Token};
+
+pub enum Item {
+    Trait(ItemTrait),
+    Impl(ItemImpl),
+}
+
+impl Parse for Item {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let attrs = input.call(Attribute::parse_outer)?;
+        let mut lookahead = input.lookahead1();
+        if lookahead.peek(Token![unsafe]) {
+            let ahead = input.fork();
+            ahead.parse::<Token![unsafe]>()?;
+            lookahead = ahead.lookahead1();
+        }
+        if lookahead.peek(Token![pub]) || lookahead.peek(Token![trait]) {
+            let mut item: ItemTrait = input.parse()?;
+            item.attrs = attrs;
+            Ok(Item::Trait(item))
+        } else if lookahead.peek(Token![impl]) {
+            let mut item: ItemImpl = input.parse()?;
+            if item.trait_.is_none() {
+                return Err(Error::new(Span::call_site(), "expected a trait impl"));
+            }
+            item.attrs = attrs;
+            Ok(Item::Impl(item))
+        } else {
+            Err(lookahead.error())
+        }
+    }
+}
diff --git a/src/receiver.rs b/src/receiver.rs
new file mode 100644
index 0000000..1e9e397
--- /dev/null
+++ b/src/receiver.rs
@@ -0,0 +1,307 @@
+use crate::respan::respan;
+use proc_macro2::{Group, Spacing, Span, TokenStream, TokenTree};
+use quote::{quote, quote_spanned};
+use std::iter::FromIterator;
+use std::mem;
+use syn::punctuated::Punctuated;
+use syn::visit_mut::{self, VisitMut};
+use syn::{
+    parse_quote, Block, Error, ExprPath, ExprStruct, Ident, Item, Macro, PatPath, PatStruct,
+    PatTupleStruct, Path, PathArguments, QSelf, Receiver, Signature, Token, Type, TypePath,
+    WherePredicate,
+};
+
+pub fn has_self_in_sig(sig: &mut Signature) -> bool {
+    let mut visitor = HasSelf(false);
+    visitor.visit_signature_mut(sig);
+    visitor.0
+}
+
+pub fn has_self_in_where_predicate(where_predicate: &mut WherePredicate) -> bool {
+    let mut visitor = HasSelf(false);
+    visitor.visit_where_predicate_mut(where_predicate);
+    visitor.0
+}
+
+pub fn has_self_in_block(block: &mut Block) -> bool {
+    let mut visitor = HasSelf(false);
+    visitor.visit_block_mut(block);
+    visitor.0
+}
+
+struct HasSelf(bool);
+
+impl VisitMut for HasSelf {
+    fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
+        self.0 |= expr.path.segments[0].ident == "Self";
+        visit_mut::visit_expr_path_mut(self, expr);
+    }
+
+    fn visit_pat_path_mut(&mut self, pat: &mut PatPath) {
+        self.0 |= pat.path.segments[0].ident == "Self";
+        visit_mut::visit_pat_path_mut(self, pat);
+    }
+
+    fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
+        self.0 |= ty.path.segments[0].ident == "Self";
+        visit_mut::visit_type_path_mut(self, ty);
+    }
+
+    fn visit_receiver_mut(&mut self, _arg: &mut Receiver) {
+        self.0 = true;
+    }
+
+    fn visit_item_mut(&mut self, _: &mut Item) {
+        // Do not recurse into nested items.
+    }
+}
+
+pub struct ReplaceReceiver {
+    pub with: Type,
+    pub as_trait: Option<Path>,
+}
+
+impl ReplaceReceiver {
+    pub fn with(ty: Type) -> Self {
+        ReplaceReceiver {
+            with: ty,
+            as_trait: None,
+        }
+    }
+
+    pub fn with_as_trait(ty: Type, as_trait: Path) -> Self {
+        ReplaceReceiver {
+            with: ty,
+            as_trait: Some(as_trait),
+        }
+    }
+
+    fn self_ty(&self, span: Span) -> Type {
+        respan(&self.with, span)
+    }
+
+    fn self_to_qself_type(&self, qself: &mut Option<QSelf>, path: &mut Path) {
+        let include_as_trait = true;
+        self.self_to_qself(qself, path, include_as_trait);
+    }
+
+    fn self_to_qself_expr(&self, qself: &mut Option<QSelf>, path: &mut Path) {
+        let include_as_trait = false;
+        self.self_to_qself(qself, path, include_as_trait);
+    }
+
+    fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path, include_as_trait: bool) {
+        if path.leading_colon.is_some() {
+            return;
+        }
+
+        let first = &path.segments[0];
+        if first.ident != "Self" || !first.arguments.is_empty() {
+            return;
+        }
+
+        if path.segments.len() == 1 {
+            self.self_to_expr_path(path);
+            return;
+        }
+
+        let span = first.ident.span();
+        *qself = Some(QSelf {
+            lt_token: Token![<](span),
+            ty: Box::new(self.self_ty(span)),
+            position: 0,
+            as_token: None,
+            gt_token: Token![>](span),
+        });
+
+        if include_as_trait && self.as_trait.is_some() {
+            let as_trait = self.as_trait.as_ref().unwrap().clone();
+            path.leading_colon = as_trait.leading_colon;
+            qself.as_mut().unwrap().position = as_trait.segments.len();
+
+            let segments = mem::replace(&mut path.segments, as_trait.segments);
+            path.segments.push_punct(Default::default());
+            path.segments.extend(segments.into_pairs().skip(1));
+        } else {
+            path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
+
+            let segments = mem::replace(&mut path.segments, Punctuated::new());
+            path.segments = segments.into_pairs().skip(1).collect();
+        }
+    }
+
+    fn self_to_expr_path(&self, path: &mut Path) {
+        if path.leading_colon.is_some() {
+            return;
+        }
+
+        let first = &path.segments[0];
+        if first.ident != "Self" || !first.arguments.is_empty() {
+            return;
+        }
+
+        if let Type::Path(self_ty) = self.self_ty(first.ident.span()) {
+            let variant = mem::replace(path, self_ty.path);
+            for segment in &mut path.segments {
+                if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
+                    if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
+                        bracketed.colon2_token = Some(Default::default());
+                    }
+                }
+            }
+            if variant.segments.len() > 1 {
+                path.segments.push_punct(Default::default());
+                path.segments.extend(variant.segments.into_pairs().skip(1));
+            }
+        } else {
+            let span = path.segments[0].ident.span();
+            let msg = "Self type of this impl is unsupported in expression position";
+            let error = Error::new(span, msg).to_compile_error();
+            *path = parse_quote!(::core::marker::PhantomData::<#error>);
+        }
+    }
+
+    fn visit_token_stream(&self, tokens: &mut TokenStream) -> bool {
+        let mut out = Vec::new();
+        let mut modified = false;
+        let mut iter = tokens.clone().into_iter().peekable();
+        while let Some(tt) = iter.next() {
+            match tt {
+                TokenTree::Ident(mut ident) => {
+                    modified |= prepend_underscore_to_self(&mut ident);
+                    if ident == "Self" {
+                        modified = true;
+                        if self.as_trait.is_none() {
+                            let ident = Ident::new("AsyncTrait", ident.span());
+                            out.push(TokenTree::Ident(ident));
+                        } else {
+                            let self_ty = self.self_ty(ident.span());
+                            match iter.peek() {
+                                Some(TokenTree::Punct(p))
+                                    if p.as_char() == ':' && p.spacing() == Spacing::Joint =>
+                                {
+                                    let next = iter.next().unwrap();
+                                    match iter.peek() {
+                                        Some(TokenTree::Punct(p)) if p.as_char() == ':' => {
+                                            let span = ident.span();
+                                            out.extend(quote_spanned!(span=> <#self_ty>));
+                                        }
+                                        _ => out.extend(quote!(#self_ty)),
+                                    }
+                                    out.push(next);
+                                }
+                                _ => out.extend(quote!(#self_ty)),
+                            }
+                        }
+                    } else {
+                        out.push(TokenTree::Ident(ident));
+                    }
+                }
+                TokenTree::Group(group) => {
+                    let mut content = group.stream();
+                    modified |= self.visit_token_stream(&mut content);
+                    let mut new = Group::new(group.delimiter(), content);
+                    new.set_span(group.span());
+                    out.push(TokenTree::Group(new));
+                }
+                other => out.push(other),
+            }
+        }
+        if modified {
+            *tokens = TokenStream::from_iter(out);
+        }
+        modified
+    }
+}
+
+impl VisitMut for ReplaceReceiver {
+    // `Self` -> `Receiver`
+    fn visit_type_mut(&mut self, ty: &mut Type) {
+        if let Type::Path(node) = ty {
+            if node.qself.is_none() && node.path.is_ident("Self") {
+                *ty = self.self_ty(node.path.segments[0].ident.span());
+            } else {
+                self.visit_type_path_mut(node);
+            }
+        } else {
+            visit_mut::visit_type_mut(self, ty);
+        }
+    }
+
+    // `Self::Assoc` -> `<Receiver>::Assoc`
+    fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
+        if ty.qself.is_none() {
+            self.self_to_qself_type(&mut ty.qself, &mut ty.path);
+        }
+        visit_mut::visit_type_path_mut(self, ty);
+    }
+
+    // `Self::method` -> `<Receiver>::method`
+    fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
+        if expr.qself.is_none() {
+            prepend_underscore_to_self(&mut expr.path.segments[0].ident);
+            self.self_to_qself_expr(&mut expr.qself, &mut expr.path);
+        }
+        visit_mut::visit_expr_path_mut(self, expr);
+    }
+
+    fn visit_expr_struct_mut(&mut self, expr: &mut ExprStruct) {
+        self.self_to_expr_path(&mut expr.path);
+        visit_mut::visit_expr_struct_mut(self, expr);
+    }
+
+    fn visit_pat_path_mut(&mut self, pat: &mut PatPath) {
+        if pat.qself.is_none() {
+            self.self_to_qself_expr(&mut pat.qself, &mut pat.path);
+        }
+        visit_mut::visit_pat_path_mut(self, pat);
+    }
+
+    fn visit_pat_struct_mut(&mut self, pat: &mut PatStruct) {
+        self.self_to_expr_path(&mut pat.path);
+        visit_mut::visit_pat_struct_mut(self, pat);
+    }
+
+    fn visit_pat_tuple_struct_mut(&mut self, pat: &mut PatTupleStruct) {
+        self.self_to_expr_path(&mut pat.path);
+        visit_mut::visit_pat_tuple_struct_mut(self, pat);
+    }
+
+    fn visit_item_mut(&mut self, i: &mut Item) {
+        match i {
+            // Visit `macro_rules!` because locally defined macros can refer to `self`.
+            Item::Macro(i) if i.mac.path.is_ident("macro_rules") => {
+                self.visit_macro_mut(&mut i.mac)
+            }
+            // Otherwise, do not recurse into nested items.
+            _ => {}
+        }
+    }
+
+    fn visit_macro_mut(&mut self, i: &mut Macro) {
+        // We can't tell in general whether `self` inside a macro invocation
+        // refers to the self in the argument list or a different self
+        // introduced within the macro. Heuristic: if the macro input contains
+        // `fn`, then `self` is more likely to refer to something other than the
+        // outer function's self argument.
+        if !contains_fn(i.tokens.clone()) {
+            self.visit_token_stream(&mut i.tokens);
+        }
+    }
+}
+
+fn contains_fn(tokens: TokenStream) -> bool {
+    tokens.into_iter().any(|tt| match tt {
+        TokenTree::Ident(ident) => ident == "fn",
+        TokenTree::Group(group) => contains_fn(group.stream()),
+        _ => false,
+    })
+}
+
+fn prepend_underscore_to_self(ident: &mut Ident) -> bool {
+    let modified = ident == "self";
+    if modified {
+        *ident = Ident::new("_self", ident.span());
+    }
+    modified
+}
diff --git a/src/respan.rs b/src/respan.rs
new file mode 100644
index 0000000..38f6612
--- /dev/null
+++ b/src/respan.rs
@@ -0,0 +1,22 @@
+use proc_macro2::{Span, TokenStream};
+use quote::ToTokens;
+use syn::parse::Parse;
+
+pub(crate) fn respan<T>(node: &T, span: Span) -> T
+where
+    T: ToTokens + Parse,
+{
+    let tokens = node.to_token_stream();
+    let respanned = respan_tokens(tokens, span);
+    syn::parse2(respanned).unwrap()
+}
+
+fn respan_tokens(tokens: TokenStream, span: Span) -> TokenStream {
+    tokens
+        .into_iter()
+        .map(|mut token| {
+            token.set_span(span);
+            token
+        })
+        .collect()
+}
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
new file mode 100644
index 0000000..f9aea23
--- /dev/null
+++ b/tests/compiletest.rs
@@ -0,0 +1,6 @@
+#[rustversion::attr(not(nightly), ignore)]
+#[test]
+fn ui() {
+    let t = trybuild::TestCases::new();
+    t.compile_fail("tests/ui/*.rs");
+}
diff --git a/tests/executor/mod.rs b/tests/executor/mod.rs
new file mode 100644
index 0000000..f48b348
--- /dev/null
+++ b/tests/executor/mod.rs
@@ -0,0 +1,35 @@
+use std::future::Future;
+use std::pin::Pin;
+use std::ptr;
+use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
+
+// Executor for a future that resolves immediately (test only).
+pub fn block_on_simple<F: Future>(mut fut: F) -> F::Output {
+    unsafe fn clone(_null: *const ()) -> RawWaker {
+        unimplemented!()
+    }
+
+    unsafe fn wake(_null: *const ()) {
+        unimplemented!()
+    }
+
+    unsafe fn wake_by_ref(_null: *const ()) {
+        unimplemented!()
+    }
+
+    unsafe fn drop(_null: *const ()) {}
+
+    let data = ptr::null();
+    let vtable = &RawWakerVTable::new(clone, wake, wake_by_ref, drop);
+    let raw_waker = RawWaker::new(data, vtable);
+    let waker = unsafe { Waker::from_raw(raw_waker) };
+    let mut cx = Context::from_waker(&waker);
+
+    // fut does not move until it gets dropped.
+    let fut = unsafe { Pin::new_unchecked(&mut fut) };
+
+    match fut.poll(&mut cx) {
+        Poll::Ready(output) => output,
+        Poll::Pending => panic!("future did not resolve immediately"),
+    }
+}
diff --git a/tests/test.rs b/tests/test.rs
new file mode 100644
index 0000000..3ea2d15
--- /dev/null
+++ b/tests/test.rs
@@ -0,0 +1,961 @@
+#![cfg_attr(async_trait_nightly_testing, feature(specialization, const_generics))]
+
+use async_trait::async_trait;
+
+pub mod executor;
+
+// Dummy module to check that the expansion refer to rust's core crate
+mod core {}
+
+#[async_trait]
+trait Trait {
+    type Assoc;
+
+    async fn selfvalue(self)
+    where
+        Self: Sized,
+    {
+    }
+
+    async fn selfref(&self) {}
+
+    async fn selfmut(&mut self) {}
+
+    async fn required() -> Self::Assoc;
+
+    async fn elided_lifetime(_x: &str) {}
+
+    async fn explicit_lifetime<'a>(_x: &'a str) {}
+
+    async fn generic_type_param<T: Send>(x: Box<T>) -> T {
+        *x
+    }
+
+    async fn calls(&self) {
+        self.selfref().await;
+        Self::elided_lifetime("").await;
+        <Self>::elided_lifetime("").await;
+    }
+
+    async fn calls_mut(&mut self) {
+        self.selfmut().await;
+    }
+}
+
+struct Struct;
+
+#[async_trait]
+impl Trait for Struct {
+    type Assoc = ();
+
+    async fn selfvalue(self) {}
+
+    async fn selfref(&self) {}
+
+    async fn selfmut(&mut self) {}
+
+    async fn required() -> Self::Assoc {}
+
+    async fn elided_lifetime(_x: &str) {}
+
+    async fn explicit_lifetime<'a>(_x: &'a str) {}
+
+    async fn generic_type_param<T: Send>(x: Box<T>) -> T {
+        *x
+    }
+
+    async fn calls(&self) {
+        self.selfref().await;
+        Self::elided_lifetime("").await;
+        <Self>::elided_lifetime("").await;
+    }
+
+    async fn calls_mut(&mut self) {
+        self.selfmut().await;
+    }
+}
+
+pub async fn test() {
+    let mut s = Struct;
+    s.selfref().await;
+    s.selfmut().await;
+    s.selfvalue().await;
+
+    Struct::required().await;
+    Struct::elided_lifetime("").await;
+    Struct::explicit_lifetime("").await;
+    Struct::generic_type_param(Box::new("")).await;
+
+    let mut s = Struct;
+    s.calls().await;
+    s.calls_mut().await;
+}
+
+pub async fn test_object_safe_without_default() {
+    #[async_trait]
+    trait ObjectSafe {
+        async fn f(&self);
+    }
+
+    #[async_trait]
+    impl ObjectSafe for Struct {
+        async fn f(&self) {}
+    }
+
+    let object = &Struct as &dyn ObjectSafe;
+    object.f().await;
+}
+
+pub async fn test_object_safe_with_default() {
+    #[async_trait]
+    trait ObjectSafe: Sync {
+        async fn f(&self) {}
+    }
+
+    #[async_trait]
+    impl ObjectSafe for Struct {
+        async fn f(&self) {}
+    }
+
+    let object = &Struct as &dyn ObjectSafe;
+    object.f().await;
+}
+
+pub async fn test_object_no_send() {
+    #[async_trait(?Send)]
+    trait ObjectSafe: Sync {
+        async fn f(&self) {}
+    }
+
+    #[async_trait(?Send)]
+    impl ObjectSafe for Struct {
+        async fn f(&self) {}
+    }
+
+    let object = &Struct as &dyn ObjectSafe;
+    object.f().await;
+}
+
+#[async_trait]
+pub unsafe trait UnsafeTrait {}
+
+#[async_trait]
+unsafe impl UnsafeTrait for () {}
+
+#[async_trait]
+pub(crate) unsafe trait UnsafeTraitPubCrate {}
+
+#[async_trait]
+unsafe trait UnsafeTraitPrivate {}
+
+// https://github.com/dtolnay/async-trait/issues/1
+pub mod issue1 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    trait Issue1 {
+        async fn f<U>(&self);
+    }
+
+    #[async_trait]
+    impl<T: Sync> Issue1 for Vec<T> {
+        async fn f<U>(&self) {}
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/2
+pub mod issue2 {
+    use async_trait::async_trait;
+    use std::future::Future;
+
+    #[async_trait]
+    pub trait Issue2: Future {
+        async fn flatten(self) -> <Self::Output as Future>::Output
+        where
+            Self::Output: Future + Send,
+            Self: Sized,
+        {
+            let nested_future = self.await;
+            nested_future.await
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/9
+pub mod issue9 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Issue9: Sized + Send {
+        async fn f(_x: Self) {}
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/11
+pub mod issue11 {
+    use async_trait::async_trait;
+    use std::sync::Arc;
+
+    #[async_trait]
+    trait Issue11 {
+        async fn example(self: Arc<Self>);
+    }
+
+    struct Struct;
+
+    #[async_trait]
+    impl Issue11 for Struct {
+        async fn example(self: Arc<Self>) {}
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/15
+pub mod issue15 {
+    use async_trait::async_trait;
+    use std::marker::PhantomData;
+
+    trait Trait {}
+
+    #[async_trait]
+    trait Issue15 {
+        async fn myfn(&self, _: PhantomData<dyn Trait + Send>) {}
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/17
+pub mod issue17 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    trait Issue17 {
+        async fn f(&self);
+    }
+
+    struct Struct {
+        string: String,
+    }
+
+    #[async_trait]
+    impl Issue17 for Struct {
+        async fn f(&self) {
+            println!("{}", self.string);
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/23
+pub mod issue23 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Issue23 {
+        async fn f(self);
+
+        async fn g(mut self)
+        where
+            Self: Sized,
+        {
+            do_something(&mut self);
+        }
+    }
+
+    struct S {}
+
+    #[async_trait]
+    impl Issue23 for S {
+        async fn f(mut self) {
+            do_something(&mut self);
+        }
+    }
+
+    fn do_something<T>(_: &mut T) {}
+}
+
+// https://github.com/dtolnay/async-trait/issues/25
+#[cfg(async_trait_nightly_testing)]
+pub mod issue25 {
+    use crate::executor;
+    use async_trait::async_trait;
+    use std::fmt::{Display, Write};
+
+    #[async_trait]
+    trait AsyncToString {
+        async fn async_to_string(&self) -> String;
+    }
+
+    #[async_trait]
+    impl AsyncToString for String {
+        async fn async_to_string(&self) -> String {
+            "special".to_owned()
+        }
+    }
+
+    macro_rules! hide_from_stable_parser {
+        ($($tt:tt)*) => {
+            $($tt)*
+        };
+    }
+
+    hide_from_stable_parser! {
+        #[async_trait]
+        impl<T: ?Sized + Display + Sync> AsyncToString for T {
+            default async fn async_to_string(&self) -> String {
+                let mut buf = String::new();
+                buf.write_fmt(format_args!("{}", self)).unwrap();
+                buf
+            }
+        }
+    }
+
+    #[test]
+    fn test() {
+        let fut = true.async_to_string();
+        assert_eq!(executor::block_on_simple(fut), "true");
+
+        let string = String::new();
+        let fut = string.async_to_string();
+        assert_eq!(executor::block_on_simple(fut), "special");
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/28
+pub mod issue28 {
+    use async_trait::async_trait;
+
+    struct Str<'a>(&'a str);
+
+    #[async_trait]
+    trait Trait1<'a> {
+        async fn f(x: Str<'a>) -> &'a str;
+        async fn g(x: Str<'a>) -> &'a str {
+            x.0
+        }
+    }
+
+    #[async_trait]
+    impl<'a> Trait1<'a> for str {
+        async fn f(x: Str<'a>) -> &'a str {
+            x.0
+        }
+    }
+
+    #[async_trait]
+    trait Trait2 {
+        async fn f();
+    }
+
+    #[async_trait]
+    impl<'a> Trait2 for &'a () {
+        async fn f() {}
+    }
+
+    #[async_trait]
+    trait Trait3<'a, 'b> {
+        async fn f(_: &'a &'b ()); // chain 'a and 'b
+        async fn g(_: &'b ()); // chain 'b only
+        async fn h(); // do not chain
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/31
+pub mod issue31 {
+    use async_trait::async_trait;
+
+    pub struct Struct<'a> {
+        pub name: &'a str,
+    }
+
+    #[async_trait]
+    pub trait Trait<'a> {
+        async fn hello(thing: Struct<'a>) -> String;
+        async fn hello_twice(one: Struct<'a>, two: Struct<'a>) -> String {
+            let str1 = Self::hello(one).await;
+            let str2 = Self::hello(two).await;
+            str1 + &str2
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/42
+pub mod issue42 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Context: Sized {
+        async fn from_parts() -> Self;
+    }
+
+    pub struct TokenContext;
+
+    #[async_trait]
+    impl Context for TokenContext {
+        async fn from_parts() -> TokenContext {
+            TokenContext
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/44
+pub mod issue44 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait StaticWithWhereSelf
+    where
+        Box<Self>: Sized,
+        Self: Sized + Send,
+    {
+        async fn get_one() -> u8 {
+            1
+        }
+    }
+
+    pub struct Struct;
+
+    #[async_trait]
+    impl StaticWithWhereSelf for Struct {}
+}
+
+// https://github.com/dtolnay/async-trait/issues/45
+pub mod issue45 {
+    use crate::executor;
+    use async_trait::async_trait;
+    use std::fmt::Debug;
+    use std::sync::atomic::{AtomicU64, Ordering};
+    use std::sync::{Arc, Mutex};
+    use tracing::event::Event;
+    use tracing::field::{Field, Visit};
+    use tracing::span::{Attributes, Id, Record};
+    use tracing::{info, instrument, subscriber, Metadata, Subscriber};
+
+    #[async_trait]
+    pub trait Parent {
+        async fn foo(&mut self, v: usize);
+    }
+
+    #[async_trait]
+    pub trait Child {
+        async fn bar(&self);
+    }
+
+    #[derive(Debug)]
+    struct Impl(usize);
+
+    #[async_trait]
+    impl Parent for Impl {
+        #[instrument]
+        async fn foo(&mut self, v: usize) {
+            self.0 = v;
+            self.bar().await;
+        }
+    }
+
+    #[async_trait]
+    impl Child for Impl {
+        // Let's check that tracing detects the renaming of the `self` variable
+        // too, as tracing::instrument is not going to be able to skip the
+        // `self` argument if it can't find it in the function signature.
+        #[instrument(skip(self))]
+        async fn bar(&self) {
+            info!(val = self.0);
+        }
+    }
+
+    // A simple subscriber implementation to test the behavior of async-trait
+    // with tokio-rs/tracing. This implementation is not robust against race
+    // conditions, but it's not an issue here as we are only polling on a single
+    // future at a time.
+    #[derive(Debug)]
+    struct SubscriberInner {
+        current_depth: AtomicU64,
+        // We assert that nested functions work. If the fix were to break, we
+        // would see two top-level functions instead of `bar` nested in `foo`.
+        max_depth: AtomicU64,
+        max_span_id: AtomicU64,
+        // Name of the variable / value / depth when the event was recorded.
+        value: Mutex<Option<(&'static str, u64, u64)>>,
+    }
+
+    #[derive(Debug, Clone)]
+    struct TestSubscriber {
+        inner: Arc<SubscriberInner>,
+    }
+
+    impl TestSubscriber {
+        fn new() -> Self {
+            TestSubscriber {
+                inner: Arc::new(SubscriberInner {
+                    current_depth: AtomicU64::new(0),
+                    max_depth: AtomicU64::new(0),
+                    max_span_id: AtomicU64::new(1),
+                    value: Mutex::new(None),
+                }),
+            }
+        }
+    }
+
+    struct U64Visitor(Option<(&'static str, u64)>);
+
+    impl Visit for U64Visitor {
+        fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {}
+
+        fn record_u64(&mut self, field: &Field, value: u64) {
+            self.0 = Some((field.name(), value));
+        }
+    }
+
+    impl Subscriber for TestSubscriber {
+        fn enabled(&self, _metadata: &Metadata) -> bool {
+            true
+        }
+        fn new_span(&self, _span: &Attributes) -> Id {
+            Id::from_u64(self.inner.max_span_id.fetch_add(1, Ordering::AcqRel))
+        }
+        fn record(&self, _span: &Id, _values: &Record) {}
+        fn record_follows_from(&self, _span: &Id, _follows: &Id) {}
+        fn event(&self, event: &Event) {
+            let mut visitor = U64Visitor(None);
+            event.record(&mut visitor);
+            if let Some((s, v)) = visitor.0 {
+                let current_depth = self.inner.current_depth.load(Ordering::Acquire);
+                *self.inner.value.lock().unwrap() = Some((s, v, current_depth));
+            }
+        }
+        fn enter(&self, _span: &Id) {
+            let old_depth = self.inner.current_depth.fetch_add(1, Ordering::AcqRel);
+            if old_depth + 1 > self.inner.max_depth.load(Ordering::Acquire) {
+                self.inner.max_depth.fetch_add(1, Ordering::AcqRel);
+            }
+        }
+        fn exit(&self, _span: &Id) {
+            self.inner.current_depth.fetch_sub(1, Ordering::AcqRel);
+        }
+    }
+
+    #[test]
+    fn tracing() {
+        // Create the future outside of the subscriber, as no call to tracing
+        // should be made until the future is polled.
+        let mut struct_impl = Impl(0);
+        let fut = struct_impl.foo(5);
+        let subscriber = TestSubscriber::new();
+        subscriber::with_default(subscriber.clone(), || executor::block_on_simple(fut));
+        // Did we enter bar inside of foo?
+        assert_eq!(subscriber.inner.max_depth.load(Ordering::Acquire), 2);
+        // Have we exited all spans?
+        assert_eq!(subscriber.inner.current_depth.load(Ordering::Acquire), 0);
+        // Did we create only two spans? Note: spans start at 1, hence the -1.
+        assert_eq!(subscriber.inner.max_span_id.load(Ordering::Acquire) - 1, 2);
+        // Was the value recorded at the right depth i.e. in the right function?
+        // If so, was it the expected value?
+        assert_eq!(*subscriber.inner.value.lock().unwrap(), Some(("val", 5, 2)));
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/46
+pub mod issue46 {
+    use async_trait::async_trait;
+
+    macro_rules! implement_commands_workaround {
+        ($tyargs:tt : $ty:tt) => {
+            #[async_trait]
+            pub trait AsyncCommands1: Sized {
+                async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
+                    self.f(x).await
+                }
+            }
+        };
+    }
+
+    implement_commands_workaround!(K: Send);
+
+    macro_rules! implement_commands {
+        ($tyargs:ident : $ty:ident) => {
+            #[async_trait]
+            pub trait AsyncCommands2: Sized {
+                async fn f<$tyargs: $ty>(&mut self, x: $tyargs) {
+                    self.f(x).await
+                }
+            }
+        };
+    }
+
+    implement_commands!(K: Send);
+}
+
+// https://github.com/dtolnay/async-trait/issues/53
+pub mod issue53 {
+    use async_trait::async_trait;
+
+    pub struct Unit;
+    pub struct Tuple(u8);
+    pub struct Struct {
+        pub x: u8,
+    }
+
+    #[async_trait]
+    pub trait Trait {
+        async fn method();
+    }
+
+    #[async_trait]
+    impl Trait for Unit {
+        async fn method() {
+            let _ = Self;
+        }
+    }
+
+    #[async_trait]
+    impl Trait for Tuple {
+        async fn method() {
+            let _ = Self(0);
+        }
+    }
+
+    #[async_trait]
+    impl Trait for Struct {
+        async fn method() {
+            let _ = Self { x: 0 };
+        }
+    }
+
+    #[async_trait]
+    impl Trait for std::marker::PhantomData<Struct> {
+        async fn method() {
+            let _ = Self;
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/57
+#[cfg(async_trait_nightly_testing)]
+pub mod issue57 {
+    use crate::executor;
+    use async_trait::async_trait;
+
+    #[async_trait]
+    trait Trait {
+        async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
+    }
+
+    struct Struct;
+
+    #[async_trait]
+    impl Trait for Struct {
+        async fn const_generic<T: Send, const C: usize>(_: [T; C]) {}
+    }
+
+    #[test]
+    fn test() {
+        let fut = Struct::const_generic([0; 10]);
+        executor::block_on_simple(fut);
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/68
+pub mod issue68 {
+    #[rustversion::since(1.40)] // procedural macros cannot expand to macro definitions in 1.39.
+    #[async_trait::async_trait]
+    pub trait Example {
+        async fn method(&self) {
+            macro_rules! t {
+                () => {{
+                    let _: &Self = self;
+                }};
+            }
+            t!();
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/73
+pub mod issue73 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Example {
+        const ASSOCIATED: &'static str;
+
+        async fn associated(&self) {
+            println!("Associated:{}", Self::ASSOCIATED);
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/81
+pub mod issue81 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Trait {
+        async fn handle(&self);
+    }
+
+    pub enum Enum {
+        Variant,
+    }
+
+    #[async_trait]
+    impl Trait for Enum {
+        async fn handle(&self) {
+            let Enum::Variant = self;
+            let Self::Variant = self;
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/83
+pub mod issue83 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Trait {
+        async fn f(&self) {}
+        async fn g(self: &Self) {}
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/85
+pub mod issue85 {
+    #![deny(non_snake_case)]
+
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Trait {
+        #[allow(non_snake_case)]
+        async fn camelCase();
+    }
+
+    pub struct Struct;
+
+    #[async_trait]
+    impl Trait for Struct {
+        async fn camelCase() {}
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/87
+pub mod issue87 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Trait {
+        async fn f(&self);
+    }
+
+    pub enum Tuple {
+        V(),
+    }
+
+    pub enum Struct {
+        V {},
+    }
+
+    #[async_trait]
+    impl Trait for Tuple {
+        async fn f(&self) {
+            let Tuple::V() = self;
+            let Self::V() = self;
+            let _ = Self::V;
+            let _ = Self::V();
+        }
+    }
+
+    #[async_trait]
+    impl Trait for Struct {
+        async fn f(&self) {
+            let Struct::V {} = self;
+            let Self::V {} = self;
+            let _ = Self::V {};
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/89
+pub mod issue89 {
+    #![allow(bare_trait_objects)]
+
+    use async_trait::async_trait;
+
+    #[async_trait]
+    trait Trait {
+        async fn f(&self);
+    }
+
+    #[async_trait]
+    impl Trait for Send + Sync {
+        async fn f(&self) {}
+    }
+
+    #[async_trait]
+    impl Trait for dyn Fn(i8) + Send + Sync {
+        async fn f(&self) {}
+    }
+
+    #[async_trait]
+    impl Trait for (dyn Fn(u8) + Send + Sync) {
+        async fn f(&self) {}
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/92
+pub mod issue92 {
+    use async_trait::async_trait;
+
+    macro_rules! mac {
+        ($($tt:tt)*) => {
+            $($tt)*
+        };
+    }
+
+    pub struct Struct<T> {
+        _x: T,
+    }
+
+    impl<T> Struct<T> {
+        const ASSOCIATED1: &'static str = "1";
+        async fn associated1() {}
+    }
+
+    #[async_trait]
+    pub trait Trait
+    where
+        mac!(Self): Send,
+    {
+        const ASSOCIATED2: &'static str;
+        type Associated2;
+
+        #[allow(path_statements, clippy::no_effect)]
+        async fn associated2(&self) {
+            // trait items
+            mac!(let _: Self::Associated2;);
+            mac!(let _: <Self>::Associated2;);
+            mac!(let _: <Self as Trait>::Associated2;);
+            mac!(Self::ASSOCIATED2;);
+            mac!(<Self>::ASSOCIATED2;);
+            mac!(<Self as Trait>::ASSOCIATED2;);
+            mac!(let _ = Self::associated2(self););
+            mac!(let _ = <Self>::associated2(self););
+            mac!(let _ = <Self as Trait>::associated2(self););
+        }
+    }
+
+    #[async_trait]
+    impl<T: Send + Sync> Trait for Struct<T>
+    where
+        mac!(Self): Send,
+    {
+        const ASSOCIATED2: &'static str = "2";
+        type Associated2 = ();
+
+        #[allow(path_statements, clippy::no_effect)]
+        async fn associated2(&self) {
+            // inherent items
+            mac!(Self::ASSOCIATED1;);
+            mac!(<Self>::ASSOCIATED1;);
+            mac!(let _ = Self::associated1(););
+            mac!(let _ = <Self>::associated1(););
+
+            // trait items
+            mac!(let _: <Self as Trait>::Associated2;);
+            mac!(Self::ASSOCIATED2;);
+            mac!(<Self>::ASSOCIATED2;);
+            mac!(<Self as Trait>::ASSOCIATED2;);
+            mac!(let _ = Self::associated2(self););
+            mac!(let _ = <Self>::associated2(self););
+            mac!(let _ = <Self as Trait>::associated2(self););
+        }
+    }
+
+    pub struct Unit;
+
+    #[async_trait]
+    impl Trait for Unit {
+        const ASSOCIATED2: &'static str = "2";
+        type Associated2 = ();
+
+        async fn associated2(&self) {
+            mac!(let Self: Self = *self;);
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/104
+mod issue104 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    trait T1 {
+        async fn id(&self) -> i32;
+    }
+
+    macro_rules! impl_t1 {
+        ($ty:ty, $id:expr) => {
+            #[async_trait]
+            impl T1 for $ty {
+                async fn id(&self) -> i32 {
+                    $id
+                }
+            }
+        };
+    }
+
+    struct Foo;
+
+    impl_t1!(Foo, 1);
+}
+
+// https://github.com/dtolnay/async-trait/issues/106
+mod issue106 {
+    use async_trait::async_trait;
+    use std::future::Future;
+
+    #[async_trait]
+    pub trait ProcessPool: Send + Sync {
+        type ThreadPool;
+
+        async fn spawn<F, Fut, T>(&self, work: F) -> T
+        where
+            F: FnOnce(&Self::ThreadPool) -> Fut + Send,
+            Fut: Future<Output = T> + 'static;
+    }
+
+    #[async_trait]
+    impl<P: ?Sized> ProcessPool for &P
+    where
+        P: ProcessPool,
+    {
+        type ThreadPool = P::ThreadPool;
+
+        async fn spawn<F, Fut, T>(&self, work: F) -> T
+        where
+            F: FnOnce(&Self::ThreadPool) -> Fut + Send,
+            Fut: Future<Output = T> + 'static,
+        {
+            (**self).spawn(work).await
+        }
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/110
+mod issue110 {
+    #![deny(clippy::all)]
+
+    use async_trait::async_trait;
+    use std::marker::PhantomData;
+
+    #[async_trait]
+    pub trait Loader {
+        async fn load(&self, key: &str);
+    }
+
+    pub struct AwsEc2MetadataLoader<'a> {
+        marker: PhantomData<&'a ()>,
+    }
+
+    #[async_trait]
+    impl Loader for AwsEc2MetadataLoader<'_> {
+        async fn load(&self, _key: &str) {}
+    }
+}
diff --git a/tests/ui/bare-trait-object.rs b/tests/ui/bare-trait-object.rs
new file mode 100644
index 0000000..afcd6b4
--- /dev/null
+++ b/tests/ui/bare-trait-object.rs
@@ -0,0 +1,15 @@
+#![deny(bare_trait_objects)]
+
+use async_trait::async_trait;
+
+#[async_trait]
+trait Trait {
+    async fn f(&self);
+}
+
+#[async_trait]
+impl Trait for Send + Sync {
+    async fn f(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/bare-trait-object.stderr b/tests/ui/bare-trait-object.stderr
new file mode 100644
index 0000000..98cf679
--- /dev/null
+++ b/tests/ui/bare-trait-object.stderr
@@ -0,0 +1,11 @@
+error: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/bare-trait-object.rs:11:16
+   |
+11 | impl Trait for Send + Sync {
+   |                ^^^^^^^^^^^ help: use `dyn`: `dyn Send + Sync`
+   |
+note: the lint level is defined here
+  --> $DIR/bare-trait-object.rs:1:9
+   |
+1  | #![deny(bare_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/delimiter-span.rs b/tests/ui/delimiter-span.rs
new file mode 100644
index 0000000..68456fa
--- /dev/null
+++ b/tests/ui/delimiter-span.rs
@@ -0,0 +1,21 @@
+use async_trait::async_trait;
+
+macro_rules! picky {
+    (ident) => {};
+}
+
+#[async_trait]
+trait Trait {
+    async fn method();
+}
+
+struct Struct;
+
+#[async_trait]
+impl Trait for Struct {
+    async fn method() {
+        picky!({ 123 });
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/delimiter-span.stderr b/tests/ui/delimiter-span.stderr
new file mode 100644
index 0000000..e080445
--- /dev/null
+++ b/tests/ui/delimiter-span.stderr
@@ -0,0 +1,8 @@
+error: no rules expected the token `{`
+  --> $DIR/delimiter-span.rs:17:16
+   |
+3  | macro_rules! picky {
+   | ------------------ when calling this macro
+...
+17 |         picky!({ 123 });
+   |                ^ no rules expected this token in macro call
diff --git a/tests/ui/missing-body.rs b/tests/ui/missing-body.rs
new file mode 100644
index 0000000..f3e1126
--- /dev/null
+++ b/tests/ui/missing-body.rs
@@ -0,0 +1,15 @@
+use async_trait::async_trait;
+
+#[async_trait]
+trait Trait {
+    async fn f(&self);
+}
+
+struct Thing;
+
+#[async_trait]
+impl Trait for Thing {
+    async fn f(&self);
+}
+
+fn main() {}
diff --git a/tests/ui/missing-body.stderr b/tests/ui/missing-body.stderr
new file mode 100644
index 0000000..2d9b09c
--- /dev/null
+++ b/tests/ui/missing-body.stderr
@@ -0,0 +1,7 @@
+error: associated function in `impl` without body
+  --> $DIR/missing-body.rs:12:5
+   |
+12 |     async fn f(&self);
+   |     ^^^^^^^^^^^^^^^^^-
+   |                      |
+   |                      help: provide a definition for the function: `{ <body> }`
diff --git a/tests/ui/must-use.rs b/tests/ui/must-use.rs
new file mode 100644
index 0000000..7ad0d9b
--- /dev/null
+++ b/tests/ui/must-use.rs
@@ -0,0 +1,21 @@
+#![deny(unused_must_use)]
+
+use async_trait::async_trait;
+
+#[async_trait]
+trait Interface {
+    async fn f(&self);
+}
+
+struct Thing;
+
+#[async_trait]
+impl Interface for Thing {
+    async fn f(&self) {}
+}
+
+pub async fn f() {
+    Thing.f();
+}
+
+fn main() {}
diff --git a/tests/ui/must-use.stderr b/tests/ui/must-use.stderr
new file mode 100644
index 0000000..c09a51e
--- /dev/null
+++ b/tests/ui/must-use.stderr
@@ -0,0 +1,11 @@
+error: unused return value of `Interface::f` that must be used
+  --> $DIR/must-use.rs:18:5
+   |
+18 |     Thing.f();
+   |     ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/must-use.rs:1:9
+   |
+1  | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
diff --git a/tests/ui/self-span.rs b/tests/ui/self-span.rs
new file mode 100644
index 0000000..b01f247
--- /dev/null
+++ b/tests/ui/self-span.rs
@@ -0,0 +1,30 @@
+use async_trait::async_trait;
+
+pub struct S {}
+
+pub enum E {
+    V {},
+}
+
+#[async_trait]
+pub trait Trait {
+    async fn method(self);
+}
+
+#[async_trait]
+impl Trait for S {
+    async fn method(self) {
+        let _: () = self;
+        let _: Self = Self;
+    }
+}
+
+#[async_trait]
+impl Trait for E {
+    async fn method(self) {
+        let _: () = self;
+        let _: Self = Self::V;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/self-span.stderr b/tests/ui/self-span.stderr
new file mode 100644
index 0000000..f897c01
--- /dev/null
+++ b/tests/ui/self-span.stderr
@@ -0,0 +1,30 @@
+error[E0423]: expected value, found struct `S`
+  --> $DIR/self-span.rs:18:23
+   |
+3  | pub struct S {}
+   | --------------- `S` defined here
+...
+18 |         let _: Self = Self;
+   |                       ^^^^ did you mean `S { /* fields */ }`?
+
+error[E0308]: mismatched types
+  --> $DIR/self-span.rs:17:21
+   |
+17 |         let _: () = self;
+   |                --   ^^^^ expected `()`, found struct `S`
+   |                |
+   |                expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/self-span.rs:25:21
+   |
+25 |         let _: () = self;
+   |                --   ^^^^ expected `()`, found enum `E`
+   |                |
+   |                expected due to this
+
+error[E0533]: expected unit struct, unit variant or constant, found struct variant `Self::V`
+  --> $DIR/self-span.rs:26:23
+   |
+26 |         let _: Self = Self::V;
+   |                       ^^^^^^^
diff --git a/tests/ui/send-not-implemented.rs b/tests/ui/send-not-implemented.rs
new file mode 100644
index 0000000..a3e3856
--- /dev/null
+++ b/tests/ui/send-not-implemented.rs
@@ -0,0 +1,15 @@
+use async_trait::async_trait;
+use std::sync::Mutex;
+
+async fn f() {}
+
+#[async_trait]
+trait Test {
+    async fn test(&self) {
+        let mutex = Mutex::new(());
+        let _guard = mutex.lock().unwrap();
+        f().await;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/send-not-implemented.stderr b/tests/ui/send-not-implemented.stderr
new file mode 100644
index 0000000..2f288f5
--- /dev/null
+++ b/tests/ui/send-not-implemented.stderr
@@ -0,0 +1,22 @@
+error: future cannot be sent between threads safely
+  --> $DIR/send-not-implemented.rs:8:26
+   |
+8  |       async fn test(&self) {
+   |  __________________________^
+9  | |         let mutex = Mutex::new(());
+10 | |         let _guard = mutex.lock().unwrap();
+11 | |         f().await;
+12 | |     }
+   | |_____^ future returned by `__test` is not `Send`
+   |
+   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, ()>`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/send-not-implemented.rs:11:9
+   |
+10 |         let _guard = mutex.lock().unwrap();
+   |             ------ has type `std::sync::MutexGuard<'_, ()>` which is not `Send`
+11 |         f().await;
+   |         ^^^^^^^^^ await occurs here, with `_guard` maybe used later
+12 |     }
+   |     - `_guard` is later dropped here
+   = note: required for the cast to the object type `dyn std::future::Future<Output = ()> + std::marker::Send`
diff --git a/tests/ui/unsupported-self.rs b/tests/ui/unsupported-self.rs
new file mode 100644
index 0000000..5868c61
--- /dev/null
+++ b/tests/ui/unsupported-self.rs
@@ -0,0 +1,15 @@
+use async_trait::async_trait;
+
+#[async_trait]
+pub trait Trait {
+    async fn method();
+}
+
+#[async_trait]
+impl Trait for &'static str {
+    async fn method() {
+        let _ = Self;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/unsupported-self.stderr b/tests/ui/unsupported-self.stderr
new file mode 100644
index 0000000..c1ea955
--- /dev/null
+++ b/tests/ui/unsupported-self.stderr
@@ -0,0 +1,5 @@
+error: Self type of this impl is unsupported in expression position
+  --> $DIR/unsupported-self.rs:11:17
+   |
+11 |         let _ = Self;
+   |                 ^^^^