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