Skip to main content

async_trait/
expand.rs

1use crate::bound::{has_bound, InferredBound, Supertraits};
2use crate::lifetime::{AddLifetimeToImplTrait, CollectLifetimes};
3use crate::parse::Item;
4use crate::receiver::{has_self_in_block, has_self_in_sig, mut_pat, ReplaceSelf};
5use crate::verbatim::VerbatimFn;
6use proc_macro2::{Span, TokenStream};
7use quote::{format_ident, quote, quote_spanned, ToTokens};
8use std::collections::BTreeSet as Set;
9use std::mem;
10use syn::punctuated::Punctuated;
11use syn::visit_mut::{self, VisitMut};
12use syn::{
13    parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericArgument, GenericParam,
14    Generics, Ident, ImplItem, Lifetime, LifetimeParam, Pat, PatIdent, PathArguments, Receiver,
15    ReceiverKind, ReturnType, Signature, Token, TraitItem, Type, TypeInfer, TypePath, WhereClause,
16};
17
18impl ToTokens for Item {
19    fn to_tokens(&self, tokens: &mut TokenStream) {
20        match self {
21            Item::Trait(item) => item.to_tokens(tokens),
22            Item::Impl(item) => item.to_tokens(tokens),
23        }
24    }
25}
26
27#[derive(#[automatically_derived]
impl<'a> ::core::clone::Clone for Context<'a> {
    #[inline]
    fn clone(&self) -> Context<'a> {
        let _: ::core::clone::AssertParamIsClone<&'a Generics>;
        let _: ::core::clone::AssertParamIsClone<&'a Supertraits>;
        let _: ::core::clone::AssertParamIsClone<&'a Generics>;
        let _: ::core::clone::AssertParamIsClone<&'a Set<Ident>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'a> ::core::marker::Copy for Context<'a> { }Copy)]
28enum Context<'a> {
29    Trait {
30        generics: &'a Generics,
31        supertraits: &'a Supertraits,
32    },
33    Impl {
34        impl_generics: &'a Generics,
35        associated_type_impl_traits: &'a Set<Ident>,
36    },
37}
38
39impl Context<'_> {
40    fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a LifetimeParam> {
41        let generics = match self {
42            Context::Trait { generics, .. } => generics,
43            Context::Impl { impl_generics, .. } => impl_generics,
44        };
45        generics.params.iter().filter_map(move |param| {
46            if let GenericParam::Lifetime(param) = param {
47                if used.contains(&param.lifetime) {
48                    return Some(param);
49                }
50            }
51            None
52        })
53    }
54}
55
56pub fn expand(input: &mut Item, is_local: bool) {
57    match input {
58        Item::Trait(input) => {
59            let context = Context::Trait {
60                generics: &input.generics,
61                supertraits: &input.supertraits,
62            };
63            for inner in &mut input.items {
64                if let TraitItem::Fn(method) = inner {
65                    let sig = &mut method.sig;
66                    if sig.asyncness.is_some() {
67                        let block = &mut method.default;
68                        let mut has_self = has_self_in_sig(sig);
69                        method.attrs.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_pound(&mut _s);
        ::quote::__private::push_group(&mut _s,
            ::quote::__private::Delimiter::Bracket,
            {
                let mut _s = ::quote::__private::TokenStream::new();
                ::quote::__private::push_ident(&mut _s, "must_use");
                _s
            });
        _s
    })parse_quote!(#[must_use]));
70                        if let Some(block) = block {
71                            has_self |= has_self_in_block(block);
72                            transform_block(context, sig, block);
73                            method.attrs.push(lint_suppress_with_body());
74                        } else {
75                            method.attrs.push(lint_suppress_without_body());
76                        }
77                        let has_default = method.default.is_some();
78                        transform_sig(context, sig, has_self, has_default, is_local);
79                    }
80                }
81            }
82        }
83        Item::Impl(input) => {
84            let mut associated_type_impl_traits = Set::new();
85            for inner in &input.items {
86                if let ImplItem::Type(assoc) = inner {
87                    if let Type::ImplTrait(_) = assoc.ty {
88                        associated_type_impl_traits.insert(assoc.ident.clone());
89                    }
90                }
91            }
92
93            let context = Context::Impl {
94                impl_generics: &input.generics,
95                associated_type_impl_traits: &associated_type_impl_traits,
96            };
97            for inner in &mut input.items {
98                match inner {
99                    ImplItem::Fn(method) if method.sig.asyncness.is_some() => {
100                        let sig = &mut method.sig;
101                        let block = &mut method.block;
102                        let has_self = has_self_in_sig(sig);
103                        transform_block(context, sig, block);
104                        transform_sig(context, sig, has_self, false, is_local);
105                        method.attrs.push(lint_suppress_with_body());
106                    }
107                    ImplItem::Verbatim(tokens) => {
108                        let mut method = match syn::parse2::<VerbatimFn>(tokens.clone()) {
109                            Ok(method) if method.sig.asyncness.is_some() => method,
110                            _ => continue,
111                        };
112                        let sig = &mut method.sig;
113                        let has_self = has_self_in_sig(sig);
114                        transform_sig(context, sig, has_self, false, is_local);
115                        method.attrs.push(lint_suppress_with_body());
116                        *tokens = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&method, &mut _s);
    _s
}quote!(#method);
117                    }
118                    _ => {}
119                }
120            }
121        }
122    }
123}
124
125fn lint_suppress_with_body() -> Attribute {
126    ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_pound(&mut _s);
        ::quote::__private::push_group(&mut _s,
            ::quote::__private::Delimiter::Bracket,
            {
                let mut _s = ::quote::__private::TokenStream::new();
                ::quote::__private::push_ident(&mut _s, "allow");
                ::quote::__private::push_group(&mut _s,
                    ::quote::__private::Delimiter::Parenthesis,
                    {
                        let mut _s = ::quote::__private::TokenStream::new();
                        ::quote::__private::push_ident(&mut _s,
                            "elided_named_lifetimes");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s,
                            "async_yields_async");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s,
                            "diverging_sub_expression");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "let_unit_value");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s,
                            "needless_arbitrary_self_type");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s,
                            "no_effect_underscore_binding");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "shadow_same");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "type_complexity");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s,
                            "type_repetition_in_bounds");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s,
                            "used_underscore_binding");
                        _s
                    });
                _s
            });
        _s
    });parse_quote! {
127        #[allow(
128            elided_named_lifetimes,
129            clippy::async_yields_async,
130            clippy::diverging_sub_expression,
131            clippy::let_unit_value,
132            clippy::needless_arbitrary_self_type,
133            clippy::no_effect_underscore_binding,
134            clippy::shadow_same,
135            clippy::type_complexity,
136            clippy::type_repetition_in_bounds,
137            clippy::used_underscore_binding
138        )]
139    }
140}
141
142fn lint_suppress_without_body() -> Attribute {
143    ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_pound(&mut _s);
        ::quote::__private::push_group(&mut _s,
            ::quote::__private::Delimiter::Bracket,
            {
                let mut _s = ::quote::__private::TokenStream::new();
                ::quote::__private::push_ident(&mut _s, "allow");
                ::quote::__private::push_group(&mut _s,
                    ::quote::__private::Delimiter::Parenthesis,
                    {
                        let mut _s = ::quote::__private::TokenStream::new();
                        ::quote::__private::push_ident(&mut _s,
                            "elided_named_lifetimes");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "type_complexity");
                        ::quote::__private::push_comma(&mut _s);
                        ::quote::__private::push_ident(&mut _s, "clippy");
                        ::quote::__private::push_colon2(&mut _s);
                        ::quote::__private::push_ident(&mut _s,
                            "type_repetition_in_bounds");
                        _s
                    });
                _s
            });
        _s
    });parse_quote! {
144        #[allow(
145            elided_named_lifetimes,
146            clippy::type_complexity,
147            clippy::type_repetition_in_bounds
148        )]
149    }
150}
151
152// Input:
153//     async fn f<T>(&self, x: &T) -> Ret;
154//
155// Output:
156//     fn f<'life0, 'life1, 'async_trait, T>(
157//         &'life0 self,
158//         x: &'life1 T,
159//     ) -> Pin<Box<dyn Future<Output = Ret> + Send + 'async_trait>>
160//     where
161//         'life0: 'async_trait,
162//         'life1: 'async_trait,
163//         T: 'async_trait,
164//         Self: Sync + 'async_trait;
165fn transform_sig(
166    context: Context,
167    sig: &mut Signature,
168    has_self: bool,
169    has_default: bool,
170    is_local: bool,
171) {
172    sig.fn_token.span = sig.asyncness.take().unwrap().span;
173
174    let (ret_arrow, ret) = match &sig.output {
175        ReturnType::Default => ({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_rarrow(&mut _s);
    _s
}quote!(->), {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    _s
}quote!(())),
176        ReturnType::Type(arrow, ret) => ({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&arrow, &mut _s);
    _s
}quote!(#arrow), {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&ret, &mut _s);
    _s
}quote!(#ret)),
177    };
178
179    let mut lifetimes = CollectLifetimes::new();
180    for arg in &mut sig.inputs {
181        match arg {
182            FnArg::Receiver(arg) => lifetimes.visit_receiver_mut(arg),
183            FnArg::Typed(arg) => lifetimes.visit_type_mut(&mut arg.ty),
184        }
185    }
186
187    for param in &mut sig.generics.params {
188        match param {
189            GenericParam::Type(param) => {
190                let param_name = &param.ident;
191                let span = match param.colon_token.take() {
192                    Some(colon_token) => colon_token.span,
193                    None => param_name.span(),
194                };
195                if param.attrs.is_empty() {
196                    let bounds = mem::take(&mut param.bounds);
197                    where_clause_or_default(&mut sig.generics.where_clause)
198                        .predicates
199                        .push(::syn::__private::parse_quote({
        let _span: ::quote::__private::Span =
            ::quote::__private::get_span(span).__into_span();
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&param_name, &mut _s);
        ::quote::__private::push_colon_spanned(&mut _s, _span);
        ::quote::__private::push_lifetime_spanned(&mut _s, _span,
            "\'async_trait");
        ::quote::__private::push_add_spanned(&mut _s, _span);
        ::quote::ToTokens::to_tokens(&bounds, &mut _s);
        _s
    })parse_quote_spanned!(span=> #param_name: 'async_trait + #bounds));
200                } else {
201                    param.bounds.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_lifetime(&mut _s, "\'async_trait");
        _s
    })parse_quote!('async_trait));
202                }
203            }
204            GenericParam::Lifetime(param) => {
205                let param_name = &param.lifetime;
206                let span = match param.colon_token.take() {
207                    Some(colon_token) => colon_token.span,
208                    None => param_name.span(),
209                };
210                if param.attrs.is_empty() {
211                    let bounds = mem::take(&mut param.bounds);
212                    where_clause_or_default(&mut sig.generics.where_clause)
213                        .predicates
214                        .push(::syn::__private::parse_quote({
        let _span: ::quote::__private::Span =
            ::quote::__private::get_span(span).__into_span();
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&param, &mut _s);
        ::quote::__private::push_colon_spanned(&mut _s, _span);
        ::quote::__private::push_lifetime_spanned(&mut _s, _span,
            "\'async_trait");
        ::quote::__private::push_add_spanned(&mut _s, _span);
        ::quote::ToTokens::to_tokens(&bounds, &mut _s);
        _s
    })parse_quote_spanned!(span=> #param: 'async_trait + #bounds));
215                } else {
216                    param.bounds.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_lifetime(&mut _s, "\'async_trait");
        _s
    })parse_quote!('async_trait));
217                }
218            }
219            GenericParam::Const(_) => {}
220        }
221    }
222
223    for param in context.lifetimes(&lifetimes.explicit) {
224        let param = &param.lifetime;
225        let span = param.span();
226        where_clause_or_default(&mut sig.generics.where_clause)
227            .predicates
228            .push(::syn::__private::parse_quote({
        let _span: ::quote::__private::Span =
            ::quote::__private::get_span(span).__into_span();
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&param, &mut _s);
        ::quote::__private::push_colon_spanned(&mut _s, _span);
        ::quote::__private::push_lifetime_spanned(&mut _s, _span,
            "\'async_trait");
        _s
    })parse_quote_spanned!(span=> #param: 'async_trait));
229    }
230
231    if sig.generics.lt_token.is_none() {
232        sig.generics.lt_token = Some(::syn::token::LtToken![<](sig.ident.span()));
233    }
234    if sig.generics.gt_token.is_none() {
235        sig.generics.gt_token = Some(::syn::token::GtToken![>](sig.paren_token.span.join()));
236    }
237
238    for elided in lifetimes.elided {
239        sig.generics.params.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&elided, &mut _s);
        _s
    })parse_quote!(#elided));
240        where_clause_or_default(&mut sig.generics.where_clause)
241            .predicates
242            .push(::syn::__private::parse_quote({
        let _span: ::quote::__private::Span =
            ::quote::__private::get_span(elided.span()).__into_span();
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&elided, &mut _s);
        ::quote::__private::push_colon_spanned(&mut _s, _span);
        ::quote::__private::push_lifetime_spanned(&mut _s, _span,
            "\'async_trait");
        _s
    })parse_quote_spanned!(elided.span()=> #elided: 'async_trait));
243    }
244
245    sig.generics.params.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_lifetime(&mut _s, "\'async_trait");
        _s
    })parse_quote!('async_trait));
246
247    if has_self {
248        let bounds: &[InferredBound] = if is_local {
249            &[]
250        } else if let Some(receiver) = sig.receiver() {
251            match &receiver.kind {
252                // &self
253                ReceiverKind::Reference(_ampersand, _lifetime, None::<::syn::token::MutToken![mut]>) => {
254                    &[InferredBound::Sync]
255                }
256                ReceiverKind::Typed(_colon, ty) => match ty.as_ref() {
257                    // self: &Self
258                    Type::Reference(ty) if ty.mutability.is_none() => &[InferredBound::Sync],
259                    // self: Arc<Self>
260                    Type::Path(ty)
261                        if {
262                            let segment = ty.path.segments.last().unwrap();
263                            segment.ident == "Arc"
264                                && match &segment.arguments {
265                                    PathArguments::AngleBracketed(arguments) => {
266                                        arguments.args.len() == 1
267                                            && match &arguments.args[0] {
268                                                GenericArgument::Type(Type::Path(arg)) => {
269                                                    arg.path.is_ident("Self")
270                                                }
271                                                _ => false,
272                                            }
273                                    }
274                                    _ => false,
275                                }
276                        } =>
277                    {
278                        &[InferredBound::Sync, InferredBound::Send]
279                    }
280                    _ => &[InferredBound::Send],
281                },
282                _ => &[InferredBound::Send],
283            }
284        } else {
285            &[InferredBound::Send]
286        };
287
288        let bounds = bounds.iter().filter(|bound| match context {
289            Context::Trait { supertraits, .. } => has_default && !has_bound(supertraits, bound),
290            Context::Impl { .. } => false,
291        });
292
293        where_clause_or_default(&mut sig.generics.where_clause)
294            .predicates
295            .push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_ident(&mut _s, "Self");
        ::quote::__private::push_colon(&mut _s);
        {
            use ::quote::__private::ext::*;
            let has_iter = ::quote::__private::HasIterator::<false>;
            #[allow(unused_mut)]
            let (mut bounds, i) = bounds.quote_into_iter();
            let has_iter = has_iter | i;
            <_ as
                    ::quote::__private::CheckHasIterator<true>>::check(has_iter);
            while true {
                let bounds =
                    match bounds.next() {
                        Some(_x) => ::quote::__private::RepInterp(_x),
                        None => break,
                    };
                ::quote::ToTokens::to_tokens(&bounds, &mut _s);
                ::quote::__private::push_add(&mut _s);
            }
        }
        ::quote::__private::push_lifetime(&mut _s, "\'async_trait");
        _s
    })parse_quote! {
296                Self: #(#bounds +)* 'async_trait
297            });
298    }
299
300    for (i, arg) in sig.inputs.iter_mut().enumerate() {
301        match arg {
302            FnArg::Receiver(receiver) => {
303                receiver.mutability = None;
304            }
305            FnArg::Typed(arg) => {
306                if match *arg.ty {
307                    Type::Reference(_) => false,
308                    _ => true,
309                } {
310                    if let Pat::Ident(pat) = &mut *arg.pat {
311                        pat.by_ref = None;
312                        pat.mutability = None;
313                    } else {
314                        let positional = positional_arg(i, &arg.pat);
315                        let m = mut_pat(&mut arg.pat);
316                        arg.pat = ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&m, &mut _s);
        ::quote::ToTokens::to_tokens(&positional, &mut _s);
        _s
    })parse_quote!(#m #positional);
317                    }
318                }
319                AddLifetimeToImplTrait.visit_type_mut(&mut arg.ty);
320            }
321        }
322    }
323
324    let bounds = if is_local {
325        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_lifetime(&mut _s, "\'async_trait");
    _s
}quote!('async_trait)
326    } else {
327        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "marker");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Send");
    ::quote::__private::push_add(&mut _s);
    ::quote::__private::push_lifetime(&mut _s, "\'async_trait");
    _s
}quote!(::core::marker::Send + 'async_trait)
328    };
329    sig.output = ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&ret_arrow, &mut _s);
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "core");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "pin");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "Pin");
        ::quote::__private::push_lt(&mut _s);
        ::quote::__private::push_ident(&mut _s, "Box");
        ::quote::__private::push_lt(&mut _s);
        ::quote::__private::push_ident(&mut _s, "dyn");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "core");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "future");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "Future");
        ::quote::__private::push_lt(&mut _s);
        ::quote::__private::push_ident(&mut _s, "Output");
        ::quote::__private::push_eq(&mut _s);
        ::quote::ToTokens::to_tokens(&ret, &mut _s);
        ::quote::__private::push_gt(&mut _s);
        ::quote::__private::push_add(&mut _s);
        ::quote::ToTokens::to_tokens(&bounds, &mut _s);
        ::quote::__private::push_shr(&mut _s);
        _s
    })parse_quote! {
330        #ret_arrow ::core::pin::Pin<Box<
331            dyn ::core::future::Future<Output = #ret> + #bounds
332        >>
333    };
334}
335
336// Input:
337//     async fn f<T>(&self, x: &T, (a, b): (A, B)) -> Ret {
338//         self + x + a + b
339//     }
340//
341// Output:
342//     Box::pin(async move {
343//         let ___ret: Ret = {
344//             let __self = self;
345//             let x = x;
346//             let (a, b) = __arg1;
347//
348//             __self + x + a + b
349//         };
350//
351//         ___ret
352//     })
353fn transform_block(context: Context, sig: &mut Signature, block: &mut Block) {
354    let mut replace_self = false;
355    let decls = sig
356        .inputs
357        .iter()
358        .enumerate()
359        .map(|(i, arg)| match arg {
360            FnArg::Receiver(Receiver {
361                self_token,
362                mutability,
363                ..
364            }) => {
365                replace_self = true;
366                let ident = Ident::new("__self", self_token.span);
367                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::ToTokens::to_tokens(&mutability, &mut _s);
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&self_token, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    _s
}quote!(let #mutability #ident = #self_token;)
368            }
369            FnArg::Typed(arg) => {
370                // If there is a #[cfg(...)] attribute that selectively enables
371                // the parameter, forward it to the variable.
372                //
373                // This is currently not applied to the `self` parameter.
374                let attrs = arg.attrs.iter().filter(|attr| attr.path().is_ident("cfg"));
375
376                if let Type::Reference(_) = *arg.ty {
377                    ::quote::__private::TokenStream::new()quote!()
378                } else if let Pat::Ident(PatIdent {
379                    ident, mutability, ..
380                }) = &*arg.pat
381                {
382                    {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut attrs, i) = attrs.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let attrs =
                match attrs.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&attrs, &mut _s);
        }
    }
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::ToTokens::to_tokens(&mutability, &mut _s);
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
383                        #(#attrs)*
384                        let #mutability #ident = #ident;
385                    }
386                } else {
387                    let pat = &arg.pat;
388                    let ident = positional_arg(i, pat);
389                    if let Pat::Wild(_) = **pat {
390                        {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut attrs, i) = attrs.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let attrs =
                match attrs.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&attrs, &mut _s);
        }
    }
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
391                            #(#attrs)*
392                            let #ident = #ident;
393                        }
394                    } else {
395                        {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut attrs, i) = attrs.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let attrs =
                match attrs.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&attrs, &mut _s);
        }
    }
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::ToTokens::to_tokens(&pat, &mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "let");
            ::quote::ToTokens::to_tokens(&ident, &mut _s);
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&ident, &mut _s);
            ::quote::__private::push_semi(&mut _s);
            ::quote::ToTokens::to_tokens(&ident, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
396                            #(#attrs)*
397                            let #pat = {
398                                let #ident = #ident;
399                                #ident
400                            };
401                        }
402                    }
403                }
404            }
405        })
406        .collect::<Vec<_>>();
407
408    if replace_self {
409        ReplaceSelf.visit_block_mut(block);
410    }
411
412    let let_ret = match &mut sig.output {
413        ReturnType::Default => {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut decls, i) = decls.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let decls =
                match decls.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&decls, &mut _s);
        }
    }
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_underscore(&mut _s);
    ::quote::__private::push_colon(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&block, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
414            #(#decls)*
415            let _: () = #block;
416        },
417        ReturnType::Type(_, ret) => {
418            if contains_associated_type_impl_trait(context, ret) {
419                if decls.is_empty() {
420                    let stmts = &block.stmts;
421                    {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut stmts, i) = stmts.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let stmts =
                match stmts.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&stmts, &mut _s);
        }
    }
    _s
}quote!(#(#stmts)*)
422                } else {
423                    {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut decls, i) = decls.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let decls =
                match decls.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&decls, &mut _s);
        }
    }
    ::quote::ToTokens::to_tokens(&block, &mut _s);
    _s
}quote!(#(#decls)* #block)
424                }
425            } else {
426                let mut ret = ret.clone();
427                replace_impl_trait_with_infer(&mut ret);
428                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "if");
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Some");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "__ret");
            _s
        });
    ::quote::__private::push_eq(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "None");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&ret, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "allow");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "unreachable_code");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "return");
            ::quote::__private::push_ident(&mut _s, "__ret");
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut decls, i) = decls.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let decls =
                match decls.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&decls, &mut _s);
        }
    }
    ::quote::__private::push_ident(&mut _s, "let");
    ::quote::__private::push_ident(&mut _s, "__ret");
    ::quote::__private::push_colon(&mut _s);
    ::quote::ToTokens::to_tokens(&ret, &mut _s);
    ::quote::__private::push_eq(&mut _s);
    ::quote::ToTokens::to_tokens(&block, &mut _s);
    ::quote::__private::push_semi(&mut _s);
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "allow");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "unreachable_code");
                    _s
                });
            _s
        });
    ::quote::__private::push_ident(&mut _s, "__ret");
    _s
}quote! {
429                    if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<#ret> {
430                        #[allow(unreachable_code)]
431                        return __ret;
432                    }
433                    #(#decls)*
434                    let __ret: #ret = #block;
435                    #[allow(unreachable_code)]
436                    __ret
437                }
438            }
439        }
440    };
441    let box_pin = {
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(sig.asyncness.unwrap().span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident_spanned(&mut _s, _span, "Box");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "pin");
    ::quote::__private::push_group_spanned(&mut _s, _span,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident_spanned(&mut _s, _span, "async");
            ::quote::__private::push_ident_spanned(&mut _s, _span, "move");
            ::quote::__private::push_group_spanned(&mut _s, _span,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&let_ret, &mut _s);
                    _s
                });
            _s
        });
    _s
}quote_spanned!(sig.asyncness.unwrap().span=>
442        Box::pin(async move { #let_ret })
443    );
444    block.stmts = ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&box_pin, &mut _s);
        _s
    })parse_quote!(#box_pin);
445}
446
447fn positional_arg(i: usize, pat: &Pat) -> Ident {
448    let span = syn::spanned::Spanned::span(pat).resolved_at(Span::mixed_site());
449    match ::quote::__private::IdentFragmentAdapter(&i) {
    arg =>
        ::quote::__private::mk_ident(&::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("__arg{0}", arg))
                    }),
            ::quote::__private::Option::Some::<::quote::__private::Span>(span)),
}format_ident!("__arg{}", i, span = span)
450}
451
452fn contains_associated_type_impl_trait(context: Context, ret: &mut Type) -> bool {
453    struct AssociatedTypeImplTraits<'a> {
454        set: &'a Set<Ident>,
455        contains: bool,
456    }
457
458    impl<'a> VisitMut for AssociatedTypeImplTraits<'a> {
459        fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
460            if ty.qself.is_none()
461                && ty.path.segments.len() == 2
462                && ty.path.segments[0].ident == "Self"
463                && self.set.contains(&ty.path.segments[1].ident)
464            {
465                self.contains = true;
466            }
467            visit_mut::visit_type_path_mut(self, ty);
468        }
469    }
470
471    match context {
472        Context::Trait { .. } => false,
473        Context::Impl {
474            associated_type_impl_traits,
475            ..
476        } => {
477            let mut visit = AssociatedTypeImplTraits {
478                set: associated_type_impl_traits,
479                contains: false,
480            };
481            visit.visit_type_mut(ret);
482            visit.contains
483        }
484    }
485}
486
487fn where_clause_or_default(clause: &mut Option<WhereClause>) -> &mut WhereClause {
488    clause.get_or_insert_with(|| WhereClause {
489        where_token: Default::default(),
490        predicates: Punctuated::new(),
491    })
492}
493
494fn replace_impl_trait_with_infer(ty: &mut Type) {
495    struct ReplaceImplTraitWithInfer;
496
497    impl VisitMut for ReplaceImplTraitWithInfer {
498        fn visit_type_mut(&mut self, ty: &mut Type) {
499            if let Type::ImplTrait(impl_trait) = ty {
500                *ty = Type::Infer(TypeInfer {
501                    attrs: Vec::new(),
502                    underscore_token: ::syn::token::UnderscoreToken![_](impl_trait.impl_token.span),
503                });
504            }
505            visit_mut::visit_type_mut(self, ty);
506        }
507    }
508
509    ReplaceImplTraitWithInfer.visit_type_mut(ty);
510}