Upgrade async-trait to 0.1.59
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
Test: TreeHugger
Change-Id: Iec93b14088222816e998a72803a206b070bdb009
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(¶m.lifetime)
- } else {
- false
+ if used.contains(¶m.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, 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 = ¶m.ident;
- let span = param.span();
+ let param_name = ¶m.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 = ¶m.lifetime;
- let span = param.span();
+ let param_name = ¶m.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 = ¶m.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));
}
@@ -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)),
+ });
+ }
+}