Merge "Upgrade async-trait to 0.1.59" am: d4ef99c6cc am: feb5d8538f

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/async-trait/+/2327956

Change-Id: Ia94200c364497f643d20efdbd96de93854d991e4
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 71c36c5..ed1a319 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "20bd296e0d646e2b14626b7078e045254bed26ee"
+    "sha1": "c1fba00e2ec717d22272d0922c6062e25181bff8"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7c80abc..531e97e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,6 +5,12 @@
   pull_request:
   schedule: [cron: "40 1 * * *"]
 
+permissions:
+  contents: read
+
+env:
+  RUSTFLAGS: -Dwarnings
+
 jobs:
   test:
     name: Rust ${{matrix.rust}}
@@ -12,24 +18,26 @@
     strategy:
       fail-fast: false
       matrix:
-        rust: [beta, stable, 1.45.0]
+        rust: [beta, stable, 1.56.0]
         include:
           - rust: nightly
             rustflags: --cfg async_trait_nightly_testing
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: dtolnay/rust-toolchain@master
         with:
           toolchain: ${{matrix.rust}}
       - run: cargo test
         env:
-          RUSTFLAGS: ${{matrix.rustflags}}
+          RUSTFLAGS: ${{matrix.rustflags}} ${{env.RUSTFLAGS}}
 
   msrv:
     name: Rust 1.39.0
     runs-on: ubuntu-latest
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: dtolnay/[email protected]
       - run: cargo check
 
@@ -37,16 +45,29 @@
     name: Clippy
     runs-on: ubuntu-latest
     if: github.event_name != 'pull_request'
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: dtolnay/rust-toolchain@clippy
       - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic
 
+  miri:
+    name: Miri
+    runs-on: ubuntu-latest
+    timeout-minutes: 45
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dtolnay/rust-toolchain@miri
+      - run: cargo miri test
+        env:
+          MIRIFLAGS: -Zmiri-strict-provenance
+
   outdated:
     name: Outdated
     runs-on: ubuntu-latest
     if: github.event_name != 'pull_request'
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: dtolnay/install@cargo-outdated
-      - run: cargo outdated --exit-code 1
+      - run: cargo outdated --workspace --exit-code 1
diff --git a/Android.bp b/Android.bp
index 09676ac..4fcaa58 100644
--- a/Android.bp
+++ b/Android.bp
@@ -41,7 +41,7 @@
     name: "libasync_trait",
     crate_name: "async_trait",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.1.52",
+    cargo_pkg_version: "0.1.59",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
diff --git a/Cargo.toml b/Cargo.toml
index d09788d..9af1d7a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,19 +13,25 @@
 edition = "2018"
 rust-version = "1.39"
 name = "async-trait"
-version = "0.1.52"
+version = "0.1.59"
 authors = ["David Tolnay <[email protected]>"]
 description = "Type erasure for async trait methods"
 documentation = "https://docs.rs/async-trait"
 readme = "README.md"
 keywords = ["async"]
+categories = [
+    "asynchronous",
+    "no-std",
+]
 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"
 
@@ -33,8 +39,12 @@
 version = "1.0"
 
 [dependencies.syn]
-version = "1.0.61"
-features = ["full", "visit-mut"]
+version = "1.0.96"
+features = [
+    "full",
+    "visit-mut",
+]
+
 [dev-dependencies.futures]
 version = "0.3"
 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index c340ced..090eef9 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,15 +1,15 @@
 [package]
 name = "async-trait"
-version = "0.1.52"
+version = "0.1.59"
 authors = ["David Tolnay <[email protected]>"]
-edition = "2018"
-rust-version = "1.39"
-license = "MIT OR Apache-2.0"
+categories = ["asynchronous", "no-std"]
 description = "Type erasure for async trait methods"
-repository = "https://github.com/dtolnay/async-trait"
 documentation = "https://docs.rs/async-trait"
-readme = "README.md"
+edition = "2018"
 keywords = ["async"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/async-trait"
+rust-version = "1.39"
 
 [lib]
 proc-macro = true
@@ -17,7 +17,7 @@
 [dependencies]
 proc-macro2 = "1.0"
 quote = "1.0"
-syn = { version = "1.0.61", features = ["full", "visit-mut"] }
+syn = { version = "1.0.96", features = ["full", "visit-mut"] }
 
 [dev-dependencies]
 futures = "0.3"
diff --git a/METADATA b/METADATA
index 5da1fec..d8eed72 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/async-trait
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "async-trait"
 description: "Type erasure for async trait methods"
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/async-trait/async-trait-0.1.52.crate"
+    value: "https://static.crates.io/crates/async-trait/async-trait-0.1.59.crate"
   }
-  version: "0.1.52"
+  version: "0.1.59"
   license_type: NOTICE
   last_upgrade_date {
     year: 2022
-    month: 3
-    day: 1
+    month: 12
+    day: 6
   }
 }
diff --git a/README.md b/README.md
index 4753f50..6ff8989 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 
 [<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="docs.rs" src="https://img.shields.io/badge/docs.rs-async--trait-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" 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
diff --git a/build.rs b/build.rs
index a2b0833..fa2fe1c 100644
--- a/build.rs
+++ b/build.rs
@@ -8,6 +8,10 @@
         None => return,
     };
 
+    if compiler < 45 {
+        println!("cargo:rustc-cfg=no_span_mixed_site");
+    }
+
     if compiler < 47 {
         println!("cargo:rustc-cfg=self_span_hack");
     }
diff --git a/src/bound.rs b/src/bound.rs
new file mode 100644
index 0000000..50182f6
--- /dev/null
+++ b/src/bound.rs
@@ -0,0 +1,48 @@
+use proc_macro2::{Ident, Span, TokenStream};
+use quote::quote_spanned;
+use syn::punctuated::Punctuated;
+use syn::{Token, TypeParamBound};
+
+pub type Supertraits = Punctuated<TypeParamBound, Token![+]>;
+
+pub enum InferredBound {
+    Send,
+    Sync,
+}
+
+pub fn has_bound(supertraits: &Supertraits, bound: &InferredBound) -> bool {
+    for supertrait in supertraits {
+        if let TypeParamBound::Trait(supertrait) = supertrait {
+            if supertrait.path.is_ident(bound)
+                || supertrait.path.segments.len() == 3
+                    && (supertrait.path.segments[0].ident == "std"
+                        || supertrait.path.segments[0].ident == "core")
+                    && supertrait.path.segments[1].ident == "marker"
+                    && supertrait.path.segments[2].ident == *bound
+            {
+                return true;
+            }
+        }
+    }
+    false
+}
+
+impl InferredBound {
+    fn as_str(&self) -> &str {
+        match self {
+            InferredBound::Send => "Send",
+            InferredBound::Sync => "Sync",
+        }
+    }
+
+    pub fn spanned_path(&self, span: Span) -> TokenStream {
+        let ident = Ident::new(self.as_str(), span);
+        quote_spanned!(span=> ::core::marker::#ident)
+    }
+}
+
+impl PartialEq<InferredBound> for Ident {
+    fn eq(&self, bound: &InferredBound) -> bool {
+        self == bound.as_str()
+    }
+}
diff --git a/src/expand.rs b/src/expand.rs
index 2f4697a..53918cb 100644
--- a/src/expand.rs
+++ b/src/expand.rs
@@ -1,23 +1,19 @@
-use crate::lifetime::CollectLifetimes;
+use crate::bound::{has_bound, InferredBound, Supertraits};
+use crate::lifetime::{AddLifetimeToImplTrait, CollectLifetimes};
 use crate::parse::Item;
 use crate::receiver::{has_self_in_block, has_self_in_sig, mut_pat, ReplaceSelf};
-use proc_macro2::TokenStream;
+use proc_macro2::{Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::collections::BTreeSet as Set;
+use std::mem;
 use syn::punctuated::Punctuated;
 use syn::visit_mut::{self, VisitMut};
 use syn::{
-    parse_quote, Attribute, Block, FnArg, GenericParam, Generics, Ident, ImplItem, Lifetime, Pat,
-    PatIdent, Receiver, ReturnType, Signature, Stmt, Token, TraitItem, Type, TypeParamBound,
-    TypePath, WhereClause,
+    parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericArgument, GenericParam,
+    Generics, Ident, ImplItem, Lifetime, LifetimeDef, Pat, PatIdent, PathArguments, Receiver,
+    ReturnType, Signature, Stmt, Token, TraitItem, Type, TypePath, WhereClause,
 };
 
-macro_rules! parse_quote_spanned {
-    ($span:expr=> $($t:tt)*) => {
-        syn::parse2(quote_spanned!($span=> $($t)*)).unwrap()
-    };
-}
-
 impl ToTokens for Item {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
@@ -40,23 +36,22 @@
 }
 
 impl Context<'_> {
-    fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a GenericParam> {
+    fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a LifetimeDef> {
         let generics = match self {
             Context::Trait { generics, .. } => generics,
             Context::Impl { impl_generics, .. } => impl_generics,
         };
-        generics.params.iter().filter(move |param| {
+        generics.params.iter().filter_map(move |param| {
             if let GenericParam::Lifetime(param) = param {
-                used.contains(&param.lifetime)
-            } else {
-                false
+                if used.contains(&param.lifetime) {
+                    return Some(param);
+                }
             }
+            None
         })
     }
 }
 
-type Supertraits = Punctuated<TypeParamBound, Token![+]>;
-
 pub fn expand(input: &mut Item, is_local: bool) {
     match input {
         Item::Trait(input) => {
@@ -163,19 +158,14 @@
     has_default: bool,
     is_local: bool,
 ) {
-    sig.fn_token.span = sig.asyncness.take().unwrap().span;
+    let default_span = sig.asyncness.take().unwrap().span;
+    sig.fn_token.span = default_span;
 
-    let ret = match &sig.output {
-        ReturnType::Default => quote!(()),
-        ReturnType::Type(_, ret) => quote!(#ret),
+    let (ret_arrow, ret) = match &sig.output {
+        ReturnType::Default => (Token![->](default_span), quote_spanned!(default_span=> ())),
+        ReturnType::Type(arrow, ret) => (*arrow, quote!(#ret)),
     };
 
-    let default_span = sig
-        .ident
-        .span()
-        .join(sig.paren_token.span)
-        .unwrap_or_else(|| sig.ident.span());
-
     let mut lifetimes = CollectLifetimes::new("'life", default_span);
     for arg in sig.inputs.iter_mut() {
         match arg {
@@ -184,31 +174,42 @@
         }
     }
 
-    for param in sig
-        .generics
-        .params
-        .iter()
-        .chain(context.lifetimes(&lifetimes.explicit))
-    {
+    for param in &mut sig.generics.params {
         match param {
             GenericParam::Type(param) => {
-                let param = &param.ident;
-                let span = param.span();
+                let param_name = &param.ident;
+                let span = match param.colon_token.take() {
+                    Some(colon_token) => colon_token.span,
+                    None => param_name.span(),
+                };
+                let bounds = mem::replace(&mut param.bounds, Punctuated::new());
                 where_clause_or_default(&mut sig.generics.where_clause)
                     .predicates
-                    .push(parse_quote_spanned!(span=> #param: 'async_trait));
+                    .push(parse_quote_spanned!(span=> #param_name: 'async_trait + #bounds));
             }
             GenericParam::Lifetime(param) => {
-                let param = &param.lifetime;
-                let span = param.span();
+                let param_name = &param.lifetime;
+                let span = match param.colon_token.take() {
+                    Some(colon_token) => colon_token.span,
+                    None => param_name.span(),
+                };
+                let bounds = mem::replace(&mut param.bounds, Punctuated::new());
                 where_clause_or_default(&mut sig.generics.where_clause)
                     .predicates
-                    .push(parse_quote_spanned!(span=> #param: 'async_trait));
+                    .push(parse_quote_spanned!(span=> #param: 'async_trait + #bounds));
             }
             GenericParam::Const(_) => {}
         }
     }
 
+    for param in context.lifetimes(&lifetimes.explicit) {
+        let param = &param.lifetime;
+        let span = param.span();
+        where_clause_or_default(&mut sig.generics.where_clause)
+            .predicates
+            .push(parse_quote_spanned!(span=> #param: 'async_trait));
+    }
+
     if sig.generics.lt_token.is_none() {
         sig.generics.lt_token = Some(Token![<](sig.ident.span()));
     }
@@ -228,37 +229,65 @@
         .push(parse_quote_spanned!(default_span=> 'async_trait));
 
     if has_self {
-        let bound_span = sig.ident.span();
-        let bound = match sig.inputs.iter().next() {
+        let bounds: &[InferredBound] = match sig.inputs.iter().next() {
             Some(FnArg::Receiver(Receiver {
                 reference: Some(_),
                 mutability: None,
                 ..
-            })) => Ident::new("Sync", bound_span),
+            })) => &[InferredBound::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()
-                    }
+                if match arg.pat.as_ref() {
+                    Pat::Ident(pat) => pat.ident == "self",
                     _ => false,
                 } =>
             {
-                Ident::new("Sync", bound_span)
+                match arg.ty.as_ref() {
+                    // self: &Self
+                    Type::Reference(ty) if ty.mutability.is_none() => &[InferredBound::Sync],
+                    // self: Arc<Self>
+                    Type::Path(ty)
+                        if {
+                            let segment = ty.path.segments.last().unwrap();
+                            segment.ident == "Arc"
+                                && match &segment.arguments {
+                                    PathArguments::AngleBracketed(arguments) => {
+                                        arguments.args.len() == 1
+                                            && match &arguments.args[0] {
+                                                GenericArgument::Type(Type::Path(arg)) => {
+                                                    arg.path.is_ident("Self")
+                                                }
+                                                _ => false,
+                                            }
+                                    }
+                                    _ => false,
+                                }
+                        } =>
+                    {
+                        &[InferredBound::Sync, InferredBound::Send]
+                    }
+                    _ => &[InferredBound::Send],
+                }
             }
-            _ => Ident::new("Send", bound_span),
+            _ => &[InferredBound::Send],
         };
 
-        let assume_bound = match context {
-            Context::Trait { supertraits, .. } => !has_default || has_bound(supertraits, &bound),
-            Context::Impl { .. } => true,
-        };
-
-        let where_clause = where_clause_or_default(&mut sig.generics.where_clause);
-        where_clause.predicates.push(if assume_bound || is_local {
-            parse_quote_spanned!(bound_span=> Self: 'async_trait)
-        } else {
-            parse_quote_spanned!(bound_span=> Self: ::core::marker::#bound + 'async_trait)
+        let bounds = bounds.iter().filter_map(|bound| {
+            let assume_bound = match context {
+                Context::Trait { supertraits, .. } => !has_default || has_bound(supertraits, bound),
+                Context::Impl { .. } => true,
+            };
+            if assume_bound || is_local {
+                None
+            } else {
+                Some(bound.spanned_path(default_span))
+            }
         });
+
+        where_clause_or_default(&mut sig.generics.where_clause)
+            .predicates
+            .push(parse_quote_spanned! {default_span=>
+                Self: #(#bounds +)* 'async_trait
+            });
     }
 
     for (i, arg) in sig.inputs.iter_mut().enumerate() {
@@ -276,18 +305,18 @@
                     let m = mut_pat(&mut arg.pat);
                     arg.pat = parse_quote!(#m #positional);
                 }
+                AddLifetimeToImplTrait.visit_type_mut(&mut arg.ty);
             }
         }
     }
 
-    let ret_span = sig.ident.span();
     let bounds = if is_local {
-        quote_spanned!(ret_span=> 'async_trait)
+        quote_spanned!(default_span=> 'async_trait)
     } else {
-        quote_spanned!(ret_span=> ::core::marker::Send + 'async_trait)
+        quote_spanned!(default_span=> ::core::marker::Send + 'async_trait)
     };
-    sig.output = parse_quote_spanned! {ret_span=>
-        -> ::core::pin::Pin<Box<
+    sig.output = parse_quote_spanned! {default_span=>
+        #ret_arrow ::core::pin::Pin<Box<
             dyn ::core::future::Future<Output = #ret> + #bounds
         >>
     };
@@ -347,7 +376,11 @@
                 } else {
                     let pat = &arg.pat;
                     let ident = positional_arg(i, pat);
-                    quote!(let #pat = #ident;)
+                    if let Pat::Wild(_) = **pat {
+                        quote!(let #ident = #ident;)
+                    } else {
+                        quote!(let #pat = #ident;)
+                    }
                 }
             }
         })
@@ -391,25 +424,10 @@
 }
 
 fn positional_arg(i: usize, pat: &Pat) -> Ident {
-    use syn::spanned::Spanned;
-    format_ident!("__arg{}", i, span = pat.span())
-}
-
-fn has_bound(supertraits: &Supertraits, marker: &Ident) -> bool {
-    for bound in supertraits {
-        if let TypeParamBound::Trait(bound) = bound {
-            if bound.path.is_ident(marker)
-                || bound.path.segments.len() == 3
-                    && (bound.path.segments[0].ident == "std"
-                        || bound.path.segments[0].ident == "core")
-                    && bound.path.segments[1].ident == "marker"
-                    && bound.path.segments[2].ident == *marker
-            {
-                return true;
-            }
-        }
-    }
-    false
+    let span: Span = syn::spanned::Spanned::span(pat);
+    #[cfg(not(no_span_mixed_site))]
+    let span = span.resolved_at(Span::mixed_site());
+    format_ident!("__arg{}", i, span = span)
 }
 
 fn contains_associated_type_impl_trait(context: Context, ret: &mut Type) -> bool {
diff --git a/src/lib.rs b/src/lib.rs
index 3ae002a..8ca5032 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,7 +2,7 @@
 //!
 //! [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
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
 //!
 //! <br>
 //!
@@ -306,6 +306,7 @@
 #![allow(
     clippy::default_trait_access,
     clippy::doc_markdown,
+    clippy::explicit_auto_deref,
     clippy::if_not_else,
     clippy::items_after_statements,
     clippy::module_name_repetitions,
@@ -317,6 +318,7 @@
 extern crate proc_macro;
 
 mod args;
+mod bound;
 mod expand;
 mod lifetime;
 mod parse;
diff --git a/src/lifetime.rs b/src/lifetime.rs
index ff25d32..8e4ec38 100644
--- a/src/lifetime.rs
+++ b/src/lifetime.rs
@@ -1,6 +1,10 @@
-use proc_macro2::Span;
+use proc_macro2::{Span, TokenStream};
+use std::mem;
 use syn::visit_mut::{self, VisitMut};
-use syn::{GenericArgument, Lifetime, Receiver, TypeReference};
+use syn::{
+    parse_quote_spanned, token, Expr, GenericArgument, Lifetime, Receiver, ReturnType, Type,
+    TypeBareFn, TypeImplTrait, TypeParen, TypePtr, TypeReference,
+};
 
 pub struct CollectLifetimes {
     pub elided: Vec<Lifetime>,
@@ -62,3 +66,50 @@
         visit_mut::visit_generic_argument_mut(self, gen);
     }
 }
+
+pub struct AddLifetimeToImplTrait;
+
+impl VisitMut for AddLifetimeToImplTrait {
+    fn visit_type_impl_trait_mut(&mut self, ty: &mut TypeImplTrait) {
+        let span = ty.impl_token.span;
+        let lifetime = parse_quote_spanned!(span=> 'async_trait);
+        ty.bounds.insert(0, lifetime);
+        if let Some(punct) = ty.bounds.pairs_mut().next().unwrap().punct_mut() {
+            punct.span = span;
+        }
+        visit_mut::visit_type_impl_trait_mut(self, ty);
+    }
+
+    fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
+        parenthesize_impl_trait(&mut ty.elem, ty.and_token.span);
+        visit_mut::visit_type_reference_mut(self, ty);
+    }
+
+    fn visit_type_ptr_mut(&mut self, ty: &mut TypePtr) {
+        parenthesize_impl_trait(&mut ty.elem, ty.star_token.span);
+        visit_mut::visit_type_ptr_mut(self, ty);
+    }
+
+    fn visit_type_bare_fn_mut(&mut self, ty: &mut TypeBareFn) {
+        if let ReturnType::Type(arrow, return_type) = &mut ty.output {
+            parenthesize_impl_trait(return_type, arrow.spans[0]);
+        }
+        visit_mut::visit_type_bare_fn_mut(self, ty);
+    }
+
+    fn visit_expr_mut(&mut self, _e: &mut Expr) {
+        // Do not recurse into impl Traits inside of an array length expression.
+        //
+        //    fn outer(arg: [u8; { fn inner(_: impl Trait) {}; 0 }]);
+    }
+}
+
+fn parenthesize_impl_trait(elem: &mut Type, paren_span: Span) {
+    if let Type::ImplTrait(_) = *elem {
+        let placeholder = Type::Verbatim(TokenStream::new());
+        *elem = Type::Paren(TypeParen {
+            paren_token: token::Paren(paren_span),
+            elem: Box::new(mem::replace(elem, placeholder)),
+        });
+    }
+}
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
index f9aea23..7974a62 100644
--- a/tests/compiletest.rs
+++ b/tests/compiletest.rs
@@ -1,4 +1,5 @@
 #[rustversion::attr(not(nightly), ignore)]
+#[cfg_attr(miri, ignore)]
 #[test]
 fn ui() {
     let t = trybuild::TestCases::new();
diff --git a/tests/test.rs b/tests/test.rs
index 2bca1fc..23d8f80 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -3,7 +3,6 @@
     feature(min_specialization, type_alias_impl_trait)
 )]
 #![allow(
-    clippy::let_underscore_drop,
     clippy::let_unit_value,
     clippy::missing_panics_doc,
     clippy::missing_safety_doc,
@@ -618,6 +617,7 @@
     }
 
     #[test]
+    #[cfg_attr(miri, ignore)] // https://github.com/matklad/once_cell/pull/185
     fn tracing() {
         // Create the future outside of the subscriber, as no call to tracing
         // should be made until the future is polled.
@@ -913,7 +913,7 @@
         const ASSOCIATED2: &'static str;
         type Associated2;
 
-        #[allow(path_statements, clippy::no_effect)]
+        #[allow(path_statements, clippy::let_underscore_future, clippy::no_effect)]
         async fn associated2(&self) {
             // trait items
             mac!(let _: Self::Associated2;);
@@ -936,7 +936,7 @@
         const ASSOCIATED2: &'static str = "2";
         type Associated2 = ();
 
-        #[allow(path_statements, clippy::no_effect)]
+        #[allow(path_statements, clippy::let_underscore_future, clippy::no_effect)]
         async fn associated2(&self) {
             // inherent items
             mac!(Self::ASSOCIATED1;);
@@ -1038,9 +1038,9 @@
     }
 
     #[async_trait]
-    impl<P: ?Sized> ProcessPool for &P
+    impl<P> ProcessPool for &P
     where
-        P: ProcessPool,
+        P: ?Sized + ProcessPool,
     {
         type ThreadPool = P::ThreadPool;
 
@@ -1056,8 +1056,6 @@
 
 // https://github.com/dtolnay/async-trait/issues/110
 pub mod issue110 {
-    #![deny(clippy::all)]
-
     use async_trait::async_trait;
     use std::marker::PhantomData;
 
@@ -1113,8 +1111,6 @@
 
 // https://github.com/dtolnay/async-trait/issues/129
 pub mod issue129 {
-    #![deny(clippy::pedantic)]
-
     use async_trait::async_trait;
 
     #[async_trait]
@@ -1378,6 +1374,23 @@
     pub fn test(_t: &dyn Trait) {}
 }
 
+// https://github.com/dtolnay/async-trait/issues/177
+pub mod issue177 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Trait {
+        async fn foo(&self, _callback: impl FnMut(&str) + Send) {}
+    }
+
+    pub struct Struct;
+
+    #[async_trait]
+    impl Trait for Struct {
+        async fn foo(&self, _callback: impl FnMut(&str) + Send) {}
+    }
+}
+
 // https://github.com/dtolnay/async-trait/issues/183
 pub mod issue183 {
     #![deny(clippy::shadow_same)]
@@ -1389,3 +1402,62 @@
         async fn foo(_n: i32) {}
     }
 }
+
+// https://github.com/dtolnay/async-trait/issues/199
+pub mod issue199 {
+    use async_trait::async_trait;
+    use std::cell::Cell;
+
+    struct IncrementOnDrop<'a>(&'a Cell<usize>);
+
+    impl<'a> Drop for IncrementOnDrop<'a> {
+        fn drop(&mut self) {
+            self.0.set(self.0.get() + 1);
+        }
+    }
+
+    #[async_trait(?Send)]
+    trait Trait {
+        async fn f(counter: &Cell<usize>, arg: IncrementOnDrop<'_>);
+    }
+
+    struct Struct;
+
+    #[async_trait(?Send)]
+    impl Trait for Struct {
+        async fn f(counter: &Cell<usize>, _: IncrementOnDrop<'_>) {
+            assert_eq!(counter.get(), 0); // second arg not dropped yet
+        }
+    }
+
+    #[test]
+    fn test() {
+        let counter = Cell::new(0);
+        let future = Struct::f(&counter, IncrementOnDrop(&counter));
+        assert_eq!(counter.get(), 0);
+        drop(future);
+        assert_eq!(counter.get(), 1);
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/204
+pub mod issue204 {
+    use async_trait::async_trait;
+
+    #[async_trait]
+    pub trait Trait {
+        async fn f(arg: &impl Trait);
+        async fn g(arg: *const impl Trait);
+    }
+}
+
+// https://github.com/dtolnay/async-trait/issues/210
+pub mod issue210 {
+    use async_trait::async_trait;
+    use std::sync::Arc;
+
+    #[async_trait]
+    pub trait Trait {
+        async fn f(self: Arc<Self>) {}
+    }
+}
diff --git a/tests/ui/arg-implementation-detail.rs b/tests/ui/arg-implementation-detail.rs
new file mode 100644
index 0000000..b83aa72
--- /dev/null
+++ b/tests/ui/arg-implementation-detail.rs
@@ -0,0 +1,22 @@
+use async_trait::async_trait;
+
+pub struct Struct;
+
+#[async_trait]
+pub trait Trait {
+    async fn f((_a, _b): (Struct, Struct)) {
+        // Expands to something like:
+        //
+        //    fn f(__arg0: (Struct, Struct)) -> … {
+        //        Box::pin(async move {
+        //            let (_a, _b) = __arg0;
+        //            …
+        //        })
+        //    }
+        //
+        // but user's code must not be allowed to name that temporary argument:
+        let _ = __arg0;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/arg-implementation-detail.stderr b/tests/ui/arg-implementation-detail.stderr
new file mode 100644
index 0000000..e742688
--- /dev/null
+++ b/tests/ui/arg-implementation-detail.stderr
@@ -0,0 +1,5 @@
+error[E0425]: cannot find value `__arg0` in this scope
+  --> tests/ui/arg-implementation-detail.rs:18:17
+   |
+18 |         let _ = __arg0;
+   |                 ^^^^^^ not found in this scope
diff --git a/tests/ui/bare-trait-object.stderr b/tests/ui/bare-trait-object.stderr
index 6670c48..50b2048 100644
--- a/tests/ui/bare-trait-object.stderr
+++ b/tests/ui/bare-trait-object.stderr
@@ -2,12 +2,20 @@
   --> tests/ui/bare-trait-object.rs:11:16
    |
 11 | impl Trait for Send + Sync {
-   |                ^^^^^^^^^^^ help: use `dyn`: `dyn Send + Sync`
+   |                ^^^^^^^^^^^
    |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 note: the lint level is defined here
   --> tests/ui/bare-trait-object.rs:1:9
    |
 1  | #![deny(bare_trait_objects)]
    |         ^^^^^^^^^^^^^^^^^^
-   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: use `dyn`
+   |
+11 | impl Trait for dyn Send + Sync {
+   |                +++
+help: alternatively use a blanket implementation to implement `Trait` for all types that also implement `Send + Sync`
+   |
+11 | impl<T: Send + Sync> Trait for T {
+   |     ++++++++++++++++           ~
diff --git a/tests/ui/consider-restricting.rs b/tests/ui/consider-restricting.rs
new file mode 100644
index 0000000..e23c8b1
--- /dev/null
+++ b/tests/ui/consider-restricting.rs
@@ -0,0 +1,26 @@
+// https://github.com/rust-lang/rust/issues/93828
+
+use async_trait::async_trait;
+
+pub trait IntoUrl {}
+
+#[async_trait]
+pub trait ClientExt {
+    async fn publish<T: IntoUrl>(&self, url: T);
+}
+
+struct Client;
+
+#[async_trait]
+impl ClientExt for Client {
+    async fn publish<T: IntoUrl>(&self, url: T) {}
+}
+
+struct Client2;
+
+#[async_trait]
+impl ClientExt for Client2 {
+    async fn publish<T>(&self, url: T) {}
+}
+
+fn main() {}
diff --git a/tests/ui/consider-restricting.stderr b/tests/ui/consider-restricting.stderr
new file mode 100644
index 0000000..62ff894
--- /dev/null
+++ b/tests/ui/consider-restricting.stderr
@@ -0,0 +1,33 @@
+error: future cannot be sent between threads safely
+  --> tests/ui/consider-restricting.rs:16:49
+   |
+16 |     async fn publish<T: IntoUrl>(&self, url: T) {}
+   |                                                 ^^ future created by async block is not `Send`
+   |
+note: captured value is not `Send`
+  --> tests/ui/consider-restricting.rs:16:41
+   |
+16 |     async fn publish<T: IntoUrl>(&self, url: T) {}
+   |                                         ^^^ has type `T` which is not `Send`
+   = note: required for the cast from `[async block@$DIR/tests/ui/consider-restricting.rs:16:49: 16:51]` to the object type `dyn Future<Output = ()> + Send`
+help: consider further restricting this bound
+   |
+16 |     async fn publish<T: IntoUrl + std::marker::Send>(&self, url: T) {}
+   |                                 +++++++++++++++++++
+
+error: future cannot be sent between threads safely
+  --> tests/ui/consider-restricting.rs:23:40
+   |
+23 |     async fn publish<T>(&self, url: T) {}
+   |                                        ^^ future created by async block is not `Send`
+   |
+note: captured value is not `Send`
+  --> tests/ui/consider-restricting.rs:23:32
+   |
+23 |     async fn publish<T>(&self, url: T) {}
+   |                                ^^^ has type `T` which is not `Send`
+   = note: required for the cast from `[async block@$DIR/tests/ui/consider-restricting.rs:23:40: 23:42]` to the object type `dyn Future<Output = ()> + Send`
+help: consider further restricting this bound
+   |
+23 |     async fn publish<T + std::marker::Send>(&self, url: T) {}
+   |                        +++++++++++++++++++
diff --git a/tests/ui/delimiter-span.rs b/tests/ui/delimiter-span.rs
index d3f67a1..51a44a2 100644
--- a/tests/ui/delimiter-span.rs
+++ b/tests/ui/delimiter-span.rs
@@ -1,3 +1,5 @@
+#![allow(unused_macro_rules)]
+
 use async_trait::async_trait;
 
 macro_rules! picky {
diff --git a/tests/ui/delimiter-span.stderr b/tests/ui/delimiter-span.stderr
index a13985d..f03da4c 100644
--- a/tests/ui/delimiter-span.stderr
+++ b/tests/ui/delimiter-span.stderr
@@ -1,17 +1,21 @@
 error: no rules expected the token `{`
-  --> tests/ui/delimiter-span.rs:17:16
+  --> tests/ui/delimiter-span.rs:19:16
    |
-3  | macro_rules! picky {
+5  | macro_rules! picky {
    | ------------------ when calling this macro
 ...
-17 |         picky!({ 123, self });
+19 |         picky!({ 123, self });
    |                ^ no rules expected this token in macro call
+   |
+   = note: while trying to match sequence start
 
 error: no rules expected the token `{`
-  --> tests/ui/delimiter-span.rs:18:16
+  --> tests/ui/delimiter-span.rs:20:16
    |
-3  | macro_rules! picky {
+5  | macro_rules! picky {
    | ------------------ when calling this macro
 ...
-18 |         picky!({ 123 });
+20 |         picky!({ 123 });
    |                ^ no rules expected this token in macro call
+   |
+   = note: while trying to match sequence start
diff --git a/tests/ui/lifetime-span.rs b/tests/ui/lifetime-span.rs
index 4e9e5d9..01981e6 100644
--- a/tests/ui/lifetime-span.rs
+++ b/tests/ui/lifetime-span.rs
@@ -10,12 +10,12 @@
 
 #[async_trait]
 impl Trait for A {
-    async fn method(&self) { }
+    async fn method(&self) {}
 }
 
 #[async_trait]
 impl<'r> Trait<'r> for B {
-    async fn method(&self) { }
+    async fn method(&self) {}
 }
 
 #[async_trait]
@@ -25,12 +25,12 @@
 
 #[async_trait]
 impl Trait2 for A {
-    async fn method(&self) { }
+    async fn method(&self) {}
 }
 
 #[async_trait]
 impl<'r> Trait2<'r> for B {
-    async fn method(&'r self) { }
+    async fn method(&'r self) {}
 }
 
 fn main() {}
diff --git a/tests/ui/lifetime-span.stderr b/tests/ui/lifetime-span.stderr
index aad25a7..999da04 100644
--- a/tests/ui/lifetime-span.stderr
+++ b/tests/ui/lifetime-span.stderr
@@ -2,9 +2,13 @@
   --> tests/ui/lifetime-span.rs:12:6
    |
 12 | impl Trait for A {
-   |      ^^^^^- help: indicate the anonymous lifetime: `<'_>`
+   |      ^^^^^ expected lifetime parameter
    |
    = note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+   |
+12 | impl Trait<'_> for A {
+   |           ++++
 
 error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
   --> tests/ui/lifetime-span.rs:32:10
@@ -19,30 +23,3 @@
    |
 22 | pub trait Trait2 {
    |           ^^^^^^
-
-error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration
-  --> tests/ui/lifetime-span.rs:13:14
-   |
-8  |     async fn method(&'r self);
-   |              ---------------- lifetimes in impl do not match this method in trait
-...
-13 |     async fn method(&self) { }
-   |              ^^^^^^^^^^^^^ lifetimes do not match method in trait
-
-error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration
-  --> tests/ui/lifetime-span.rs:18:14
-   |
-8  |     async fn method(&'r self);
-   |              ---------------- lifetimes in impl do not match this method in trait
-...
-18 |     async fn method(&self) { }
-   |              ^^^^^^^^^^^^^ lifetimes do not match method in trait
-
-error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration
-  --> tests/ui/lifetime-span.rs:33:14
-   |
-23 |     async fn method<'r>(&'r self);
-   |                    ---- lifetimes in impl do not match this method in trait
-...
-33 |     async fn method(&'r self) { }
-   |              ^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
diff --git a/tests/ui/must-use.stderr b/tests/ui/must-use.stderr
index 1b97055..fd6fc31 100644
--- a/tests/ui/must-use.stderr
+++ b/tests/ui/must-use.stderr
@@ -2,7 +2,7 @@
   --> tests/ui/must-use.rs:18:5
    |
 18 |     Thing.f();
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^
    |
 note: the lint level is defined here
   --> tests/ui/must-use.rs:1:9
diff --git a/tests/ui/self-span.stderr b/tests/ui/self-span.stderr
index 2690791..8743e57 100644
--- a/tests/ui/self-span.stderr
+++ b/tests/ui/self-span.stderr
@@ -20,8 +20,8 @@
    |                |
    |                expected due to this
 
-error[E0533]: expected unit struct, unit variant or constant, found struct variant `Self::V`
+error[E0533]: expected value, found struct variant `Self::V`
   --> tests/ui/self-span.rs:26:23
    |
 26 |         let _: Self = Self::V;
-   |                       ^^^^^^^
+   |                       ^^^^^^^ not a value
diff --git a/tests/ui/send-not-implemented.stderr b/tests/ui/send-not-implemented.stderr
index 8004de6..d68fc43 100644
--- a/tests/ui/send-not-implemented.stderr
+++ b/tests/ui/send-not-implemented.stderr
@@ -9,17 +9,17 @@
 12 | |     }
    | |_____^ future created by async block is not `Send`
    |
-   = help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
+   = help: within `[async block@$DIR/tests/ui/send-not-implemented.rs:8:26: 12:6]`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
 note: future is not `Send` as this value is used across an await
-  --> tests/ui/send-not-implemented.rs:11:9
+  --> tests/ui/send-not-implemented.rs:11:12
    |
 10 |         let _guard = mutex.lock().unwrap();
    |             ------ has type `MutexGuard<'_, ()>` which is not `Send`
 11 |         f().await;
-   |         ^^^^^^^^^ await occurs here, with `_guard` maybe used later
+   |            ^^^^^^ await occurs here, with `_guard` maybe used later
 12 |     }
    |     - `_guard` is later dropped here
-   = note: required for the cast to the object type `dyn Future<Output = ()> + Send`
+   = note: required for the cast from `[async block@$DIR/tests/ui/send-not-implemented.rs:8:26: 12:6]` to the object type `dyn Future<Output = ()> + Send`
 
 error: future cannot be sent between threads safely
   --> tests/ui/send-not-implemented.rs:14:38
@@ -33,15 +33,15 @@
 19 | |     }
    | |_____^ future created by async block is not `Send`
    |
-   = help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
+   = help: within `[async block@$DIR/tests/ui/send-not-implemented.rs:14:38: 19:6]`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
 note: future is not `Send` as this value is used across an await
-  --> tests/ui/send-not-implemented.rs:17:9
+  --> tests/ui/send-not-implemented.rs:17:12
    |
 16 |         let _guard = mutex.lock().unwrap();
    |             ------ has type `MutexGuard<'_, ()>` which is not `Send`
 17 |         f().await;
-   |         ^^^^^^^^^ await occurs here, with `_guard` maybe used later
+   |            ^^^^^^ await occurs here, with `_guard` maybe used later
 18 |         true
 19 |     }
    |     - `_guard` is later dropped here
-   = note: required for the cast to the object type `dyn Future<Output = bool> + Send`
+   = note: required for the cast from `[async block@$DIR/tests/ui/send-not-implemented.rs:14:38: 19:6]` to the object type `dyn Future<Output = bool> + Send`