chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

36
vendor/async-trait/src/args.rs vendored Normal file
View File

@@ -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)
}

50
vendor/async-trait/src/bound.rs vendored Normal file
View File

@@ -0,0 +1,50 @@
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote, ToTokens};
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",
}
}
}
impl ToTokens for InferredBound {
fn to_tokens(&self, tokens: &mut TokenStream) {
let ident = Ident::new(self.as_str(), Span::call_site());
quote!(::core::marker::#ident).to_tokens(tokens);
}
}
impl PartialEq<InferredBound> for Ident {
fn eq(&self, bound: &InferredBound) -> bool {
self == bound.as_str()
}
}

504
vendor/async-trait/src/expand.rs vendored Normal file
View File

@@ -0,0 +1,504 @@
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 crate::verbatim::VerbatimFn;
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, parse_quote_spanned, Attribute, Block, FnArg, GenericArgument, GenericParam,
Generics, Ident, ImplItem, Lifetime, LifetimeParam, Pat, PatIdent, PathArguments, Receiver,
ReturnType, Signature, Token, TraitItem, Type, TypeInfer, TypePath, 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 {
generics: &'a Generics,
supertraits: &'a Supertraits,
},
Impl {
impl_generics: &'a Generics,
associated_type_impl_traits: &'a Set<Ident>,
},
}
impl Context<'_> {
fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a LifetimeParam> {
let generics = match self {
Context::Trait { generics, .. } => generics,
Context::Impl { impl_generics, .. } => impl_generics,
};
generics.params.iter().filter_map(move |param| {
if let GenericParam::Lifetime(param) = param {
if used.contains(&param.lifetime) {
return Some(param);
}
}
None
})
}
}
pub fn expand(input: &mut Item, is_local: bool) {
match input {
Item::Trait(input) => {
let context = Context::Trait {
generics: &input.generics,
supertraits: &input.supertraits,
};
for inner in &mut input.items {
if let TraitItem::Fn(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);
method.attrs.push(parse_quote!(#[must_use]));
if let Some(block) = block {
has_self |= has_self_in_block(block);
transform_block(context, sig, block);
method.attrs.push(lint_suppress_with_body());
} else {
method.attrs.push(lint_suppress_without_body());
}
let has_default = method.default.is_some();
transform_sig(context, sig, has_self, has_default, is_local);
}
}
}
}
Item::Impl(input) => {
let mut associated_type_impl_traits = Set::new();
for inner in &input.items {
if let ImplItem::Type(assoc) = inner {
if let Type::ImplTrait(_) = assoc.ty {
associated_type_impl_traits.insert(assoc.ident.clone());
}
}
}
let context = Context::Impl {
impl_generics: &input.generics,
associated_type_impl_traits: &associated_type_impl_traits,
};
for inner in &mut input.items {
match inner {
ImplItem::Fn(method) if method.sig.asyncness.is_some() => {
let sig = &mut method.sig;
let block = &mut method.block;
let has_self = has_self_in_sig(sig);
transform_block(context, sig, block);
transform_sig(context, sig, has_self, false, is_local);
method.attrs.push(lint_suppress_with_body());
}
ImplItem::Verbatim(tokens) => {
let mut method = match syn::parse2::<VerbatimFn>(tokens.clone()) {
Ok(method) if method.sig.asyncness.is_some() => method,
_ => continue,
};
let sig = &mut method.sig;
let has_self = has_self_in_sig(sig);
transform_sig(context, sig, has_self, false, is_local);
method.attrs.push(lint_suppress_with_body());
*tokens = quote!(#method);
}
_ => {}
}
}
}
}
}
fn lint_suppress_with_body() -> Attribute {
parse_quote! {
#[allow(
elided_named_lifetimes,
clippy::async_yields_async,
clippy::diverging_sub_expression,
clippy::let_unit_value,
clippy::needless_arbitrary_self_type,
clippy::no_effect_underscore_binding,
clippy::shadow_same,
clippy::type_complexity,
clippy::type_repetition_in_bounds,
clippy::used_underscore_binding
)]
}
}
fn lint_suppress_without_body() -> Attribute {
parse_quote! {
#[allow(
elided_named_lifetimes,
clippy::type_complexity,
clippy::type_repetition_in_bounds
)]
}
}
// 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_arrow, ret) = match &sig.output {
ReturnType::Default => (quote!(->), quote!(())),
ReturnType::Type(arrow, ret) => (quote!(#arrow), quote!(#ret)),
};
let mut lifetimes = CollectLifetimes::new();
for arg in &mut sig.inputs {
match arg {
FnArg::Receiver(arg) => lifetimes.visit_receiver_mut(arg),
FnArg::Typed(arg) => lifetimes.visit_type_mut(&mut arg.ty),
}
}
for param in &mut sig.generics.params {
match param {
GenericParam::Type(param) => {
let param_name = &param.ident;
let span = match param.colon_token.take() {
Some(colon_token) => colon_token.span,
None => param_name.span(),
};
if param.attrs.is_empty() {
let bounds = mem::take(&mut param.bounds);
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned!(span=> #param_name: 'async_trait + #bounds));
} else {
param.bounds.push(parse_quote!('async_trait));
}
}
GenericParam::Lifetime(param) => {
let param_name = &param.lifetime;
let span = match param.colon_token.take() {
Some(colon_token) => colon_token.span,
None => param_name.span(),
};
if param.attrs.is_empty() {
let bounds = mem::take(&mut param.bounds);
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned!(span=> #param: 'async_trait + #bounds));
} else {
param.bounds.push(parse_quote!('async_trait));
}
}
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()));
}
if sig.generics.gt_token.is_none() {
sig.generics.gt_token = Some(Token![>](sig.paren_token.span.join()));
}
for elided in lifetimes.elided {
sig.generics.params.push(parse_quote!(#elided));
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned!(elided.span()=> #elided: 'async_trait));
}
sig.generics.params.push(parse_quote!('async_trait));
if has_self {
let bounds: &[InferredBound] = if is_local {
&[]
} else if let Some(receiver) = sig.receiver() {
match receiver.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],
}
} else {
&[InferredBound::Send]
};
let bounds = bounds.iter().filter(|bound| match context {
Context::Trait { supertraits, .. } => has_default && !has_bound(supertraits, bound),
Context::Impl { .. } => false,
});
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote! {
Self: #(#bounds +)* 'async_trait
});
}
for (i, arg) in sig.inputs.iter_mut().enumerate() {
match arg {
FnArg::Receiver(receiver) => {
if receiver.reference.is_none() {
receiver.mutability = None;
}
}
FnArg::Typed(arg) => {
if match *arg.ty {
Type::Reference(_) => false,
_ => true,
} {
if let Pat::Ident(pat) = &mut *arg.pat {
pat.by_ref = None;
pat.mutability = None;
} else {
let positional = positional_arg(i, &arg.pat);
let m = mut_pat(&mut arg.pat);
arg.pat = parse_quote!(#m #positional);
}
}
AddLifetimeToImplTrait.visit_type_mut(&mut arg.ty);
}
}
}
let bounds = if is_local {
quote!('async_trait)
} else {
quote!(::core::marker::Send + 'async_trait)
};
sig.output = parse_quote! {
#ret_arrow ::core::pin::Pin<Box<
dyn ::core::future::Future<Output = #ret> + #bounds
>>
};
}
// Input:
// async fn f<T>(&self, x: &T, (a, b): (A, B)) -> Ret {
// self + x + a + b
// }
//
// Output:
// Box::pin(async move {
// let ___ret: Ret = {
// let __self = self;
// let x = x;
// let (a, b) = __arg1;
//
// __self + x + a + b
// };
//
// ___ret
// })
fn transform_block(context: Context, sig: &mut Signature, block: &mut Block) {
let mut replace_self = false;
let decls = sig
.inputs
.iter()
.enumerate()
.map(|(i, arg)| match arg {
FnArg::Receiver(Receiver {
self_token,
mutability,
..
}) => {
replace_self = true;
let ident = Ident::new("__self", self_token.span);
quote!(let #mutability #ident = #self_token;)
}
FnArg::Typed(arg) => {
// If there is a #[cfg(...)] attribute that selectively enables
// the parameter, forward it to the variable.
//
// This is currently not applied to the `self` parameter.
let attrs = arg.attrs.iter().filter(|attr| attr.path().is_ident("cfg"));
if let Type::Reference(_) = *arg.ty {
quote!()
} else if let Pat::Ident(PatIdent {
ident, mutability, ..
}) = &*arg.pat
{
quote! {
#(#attrs)*
let #mutability #ident = #ident;
}
} else {
let pat = &arg.pat;
let ident = positional_arg(i, pat);
if let Pat::Wild(_) = **pat {
quote! {
#(#attrs)*
let #ident = #ident;
}
} else {
quote! {
#(#attrs)*
let #pat = {
let #ident = #ident;
#ident
};
}
}
}
}
})
.collect::<Vec<_>>();
if replace_self {
ReplaceSelf.visit_block_mut(block);
}
let let_ret = match &mut sig.output {
ReturnType::Default => quote! {
#(#decls)*
let _: () = #block;
},
ReturnType::Type(_, ret) => {
if contains_associated_type_impl_trait(context, ret) {
if decls.is_empty() {
let stmts = &block.stmts;
quote!(#(#stmts)*)
} else {
quote!(#(#decls)* #block)
}
} else {
let mut ret = ret.clone();
replace_impl_trait_with_infer(&mut ret);
quote! {
if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<#ret> {
#[allow(unreachable_code)]
return __ret;
}
#(#decls)*
let __ret: #ret = #block;
#[allow(unreachable_code)]
__ret
}
}
}
};
let box_pin = quote_spanned!(sig.asyncness.unwrap().span=>
Box::pin(async move { #let_ret })
);
block.stmts = parse_quote!(#box_pin);
}
fn positional_arg(i: usize, pat: &Pat) -> Ident {
let span = syn::spanned::Spanned::span(pat).resolved_at(Span::mixed_site());
format_ident!("__arg{}", i, span = span)
}
fn contains_associated_type_impl_trait(context: Context, ret: &mut Type) -> bool {
struct AssociatedTypeImplTraits<'a> {
set: &'a Set<Ident>,
contains: bool,
}
impl<'a> VisitMut for AssociatedTypeImplTraits<'a> {
fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
if ty.qself.is_none()
&& ty.path.segments.len() == 2
&& ty.path.segments[0].ident == "Self"
&& self.set.contains(&ty.path.segments[1].ident)
{
self.contains = true;
}
visit_mut::visit_type_path_mut(self, ty);
}
}
match context {
Context::Trait { .. } => false,
Context::Impl {
associated_type_impl_traits,
..
} => {
let mut visit = AssociatedTypeImplTraits {
set: associated_type_impl_traits,
contains: false,
};
visit.visit_type_mut(ret);
visit.contains
}
}
}
fn where_clause_or_default(clause: &mut Option<WhereClause>) -> &mut WhereClause {
clause.get_or_insert_with(|| WhereClause {
where_token: Default::default(),
predicates: Punctuated::new(),
})
}
fn replace_impl_trait_with_infer(ty: &mut Type) {
struct ReplaceImplTraitWithInfer;
impl VisitMut for ReplaceImplTraitWithInfer {
fn visit_type_mut(&mut self, ty: &mut Type) {
if let Type::ImplTrait(impl_trait) = ty {
*ty = Type::Infer(TypeInfer {
underscore_token: Token![_](impl_trait.impl_token.span),
});
}
visit_mut::visit_type_mut(self, ty);
}
}
ReplaceImplTraitWithInfer.visit_type_mut(ty);
}

257
vendor/async-trait/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,257 @@
//! [![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&logo=docs.rs
//!
//! <br>
//!
//! <h4>Type erasure for async trait methods</h4>
//!
//! The stabilization of async functions in traits in Rust 1.75 did not include
//! support for using traits containing async functions as `dyn Trait`. Trying
//! to use dyn with an async trait produces the following error:
//!
//! ```compile_fail
//! pub trait Trait {
//! async fn f(&self);
//! }
//!
//! pub fn make() -> Box<dyn Trait> {
//! unimplemented!()
//! }
//! ```
//!
//! ```text
//! error[E0038]: the trait `Trait` is not dyn compatible
//! --> src/main.rs:5:22
//! |
//! 5 | pub fn make() -> Box<dyn Trait> {
//! | ^^^^^^^^^ `Trait` is not dyn compatible
//! |
//! note: for a trait to be dyn compatible it needs to allow building a vtable
//! for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
//! --> src/main.rs:2:14
//! |
//! 1 | pub trait Trait {
//! | ----- this trait is not dyn compatible...
//! 2 | async fn f(&self);
//! | ^ ...because method `f` is `async`
//! = help: consider moving `f` to another trait
//! ```
//!
//! This crate provides an attribute macro to make async fn in traits work with
//! dyn traits.
//!
//! 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 deliver natively.
//!
//! [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. We
//! get to have `Vec<Box<dyn Advertisement + Sync>>` or `&[&dyn Advertisement]`,
//! for example.
//!
//! ```
//! 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>
//!
//! <br>
//!
//! # Explanation
//!
//! Async fns get transformed into methods that return `Pin<Box<dyn Future +
//! Send + 'async_trait>>` and delegate to an async block.
//!
//! For example the `impl Advertisement for AutoplayingVideo` above would be
//! expanded as:
//!
//! ```
//! # const IGNORE: &str = stringify! {
//! impl Advertisement for AutoplayingVideo {
//! fn run<'async_trait>(
//! &'async_trait self,
//! ) -> Pin<Box<dyn core::future::Future<Output = ()> + Send + 'async_trait>>
//! where
//! Self: Sync + 'async_trait,
//! {
//! Box::pin(async move {
//! /* the original method body */
//! })
//! }
//! }
//! # };
//! ```
//!
//! <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<'_>) {}
//! }
//! ```
#![doc(html_root_url = "https://docs.rs/async-trait/0.1.89")]
#![allow(
clippy::default_trait_access,
clippy::doc_markdown,
clippy::elidable_lifetime_names,
clippy::explicit_auto_deref,
clippy::if_not_else,
clippy::items_after_statements,
clippy::match_like_matches_macro,
clippy::module_name_repetitions,
clippy::needless_lifetimes,
clippy::shadow_unrelated,
clippy::similar_names,
clippy::too_many_lines,
clippy::trivially_copy_pass_by_ref
)]
extern crate proc_macro;
mod args;
mod bound;
mod expand;
mod lifetime;
mod parse;
mod receiver;
mod verbatim;
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))
}

112
vendor/async-trait/src/lifetime.rs vendored Normal file
View File

@@ -0,0 +1,112 @@
use proc_macro2::{Span, TokenStream};
use std::mem;
use syn::visit_mut::{self, VisitMut};
use syn::{
parse_quote_spanned, token, Expr, GenericArgument, Lifetime, Receiver, ReturnType, Token, Type,
TypeBareFn, TypeImplTrait, TypeParen, TypePtr, TypeReference,
};
pub struct CollectLifetimes {
pub elided: Vec<Lifetime>,
pub explicit: Vec<Lifetime>,
}
impl CollectLifetimes {
pub fn new() -> Self {
CollectLifetimes {
elided: Vec::new(),
explicit: Vec::new(),
}
}
fn visit_opt_lifetime(&mut self, reference: &Token![&], lifetime: &mut Option<Lifetime>) {
match lifetime {
None => *lifetime = Some(self.next_lifetime(reference.span)),
Some(lifetime) => self.visit_lifetime(lifetime),
}
}
fn visit_lifetime(&mut self, lifetime: &mut Lifetime) {
if lifetime.ident == "_" {
*lifetime = self.next_lifetime(lifetime.span());
} else {
self.explicit.push(lifetime.clone());
}
}
fn next_lifetime(&mut self, span: Span) -> Lifetime {
let name = format!("'life{}", self.elided.len());
let life = Lifetime::new(&name, span);
self.elided.push(life.clone());
life
}
}
impl VisitMut for CollectLifetimes {
fn visit_receiver_mut(&mut self, arg: &mut Receiver) {
if let Some((reference, lifetime)) = &mut arg.reference {
self.visit_opt_lifetime(reference, lifetime);
} else {
visit_mut::visit_type_mut(self, &mut arg.ty);
}
}
fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
self.visit_opt_lifetime(&ty.and_token, &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);
}
}
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)),
});
}
}

34
vendor/async-trait/src/parse.rs vendored Normal file
View File

@@ -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())
}
}
}

169
vendor/async-trait/src/receiver.rs vendored Normal file
View File

@@ -0,0 +1,169 @@
use proc_macro2::{Group, TokenStream, TokenTree};
use syn::visit_mut::{self, VisitMut};
use syn::{
Block, ExprPath, Ident, Item, Macro, Pat, PatIdent, Path, Receiver, Signature, Token, TypePath,
};
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_block(block: &mut Block) -> bool {
let mut visitor = HasSelf(false);
visitor.visit_block_mut(block);
visitor.0
}
fn has_self_in_token_stream(tokens: TokenStream) -> bool {
tokens.into_iter().any(|tt| match tt {
TokenTree::Ident(ident) => ident == "Self",
TokenTree::Group(group) => has_self_in_token_stream(group.stream()),
_ => false,
})
}
pub fn mut_pat(pat: &mut Pat) -> Option<Token![mut]> {
let mut visitor = HasMutPat(None);
visitor.visit_pat_mut(pat);
visitor.0
}
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,
})
}
struct HasMutPat(Option<Token![mut]>);
impl VisitMut for HasMutPat {
fn visit_pat_ident_mut(&mut self, i: &mut PatIdent) {
if let Some(m) = &i.mutability {
self.0 = Some(Token![mut](m.span));
} else {
visit_mut::visit_pat_ident_mut(self, i);
}
}
}
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_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.
}
fn visit_macro_mut(&mut self, mac: &mut Macro) {
if !contains_fn(mac.tokens.clone()) {
self.0 |= has_self_in_token_stream(mac.tokens.clone());
}
}
}
pub struct ReplaceSelf;
fn prepend_underscore_to_self(ident: &mut Ident) -> bool {
let modified = ident == "self";
if modified {
*ident = Ident::new("__self", ident.span());
}
modified
}
impl ReplaceSelf {
fn visit_token_stream(&mut self, tokens: &mut TokenStream) -> bool {
let mut out = Vec::new();
let mut modified = false;
visit_token_stream_impl(self, tokens.clone(), &mut modified, &mut out);
if modified {
*tokens = TokenStream::from_iter(out);
}
return modified;
fn visit_token_stream_impl(
visitor: &mut ReplaceSelf,
tokens: TokenStream,
modified: &mut bool,
out: &mut Vec<TokenTree>,
) {
for tt in tokens {
match tt {
TokenTree::Ident(mut ident) => {
*modified |= prepend_underscore_to_self(&mut ident);
out.push(TokenTree::Ident(ident));
}
TokenTree::Group(group) => {
let mut content = group.stream();
*modified |= visitor.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),
}
}
}
}
}
impl VisitMut for ReplaceSelf {
fn visit_ident_mut(&mut self, i: &mut Ident) {
prepend_underscore_to_self(i);
}
fn visit_path_mut(&mut self, p: &mut Path) {
if p.segments.len() == 1 {
// Replace `self`, but not `self::function`.
self.visit_ident_mut(&mut p.segments[0].ident);
}
for segment in &mut p.segments {
self.visit_path_arguments_mut(&mut segment.arguments);
}
}
fn visit_item_mut(&mut self, i: &mut Item) {
// Visit `macro_rules!` because locally defined macros can refer to
// `self`.
//
// Visit `futures::select` and similar select macros, which commonly
// appear syntactically like an item despite expanding to an expression.
//
// Otherwise, do not recurse into nested items.
if let Item::Macro(i) = i {
if i.mac.path.is_ident("macro_rules")
|| i.mac.path.segments.last().unwrap().ident == "select"
{
self.visit_macro_mut(&mut i.mac);
}
}
}
fn visit_macro_mut(&mut self, mac: &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(mac.tokens.clone()) {
self.visit_token_stream(&mut mac.tokens);
}
}
}

34
vendor/async-trait/src/verbatim.rs vendored Normal file
View File

@@ -0,0 +1,34 @@
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
use syn::parse::{Parse, ParseStream, Result};
use syn::{Attribute, Signature, Token, Visibility};
pub struct VerbatimFn {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub defaultness: Option<Token![default]>,
pub sig: Signature,
pub semi_token: Token![;],
}
impl Parse for VerbatimFn {
fn parse(input: ParseStream) -> Result<Self> {
Ok(VerbatimFn {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
defaultness: input.parse()?,
sig: input.parse()?,
semi_token: input.parse()?,
})
}
}
impl ToTokens for VerbatimFn {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(&self.attrs);
self.vis.to_tokens(tokens);
self.defaultness.to_tokens(tokens);
self.sig.to_tokens(tokens);
self.semi_token.to_tokens(tokens);
}
}