Skip to main content

async_trait/
lifetime.rs

1use proc_macro2::{Span, TokenStream};
2use std::mem;
3use syn::visit_mut::{self, VisitMut};
4use syn::{
5    parse_quote_spanned, token, Expr, GenericArgument, Lifetime, ReceiverKind, ReturnType, Token,
6    Type, TypeFnPtr, TypeImplTrait, TypeParen, TypePtr, TypeReference,
7};
8
9pub struct CollectLifetimes {
10    pub elided: Vec<Lifetime>,
11    pub explicit: Vec<Lifetime>,
12}
13
14impl CollectLifetimes {
15    pub fn new() -> Self {
16        CollectLifetimes {
17            elided: Vec::new(),
18            explicit: Vec::new(),
19        }
20    }
21
22    fn visit_opt_lifetime(&mut self, reference: &::syn::token::AndToken![&], lifetime: &mut Option<Lifetime>) {
23        match lifetime {
24            None => *lifetime = Some(self.next_lifetime(reference.span)),
25            Some(lifetime) => self.visit_lifetime(lifetime),
26        }
27    }
28
29    fn visit_lifetime(&mut self, lifetime: &mut Lifetime) {
30        if lifetime.ident == "_" {
31            *lifetime = self.next_lifetime(lifetime.span());
32        } else {
33            self.explicit.push(lifetime.clone());
34        }
35    }
36
37    fn next_lifetime(&mut self, span: Span) -> Lifetime {
38        let name = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\'life{0}", self.elided.len()))
    })format!("'life{}", self.elided.len());
39        let life = Lifetime::new(&name, span);
40        self.elided.push(life.clone());
41        life
42    }
43}
44
45impl VisitMut for CollectLifetimes {
46    fn visit_receiver_kind_mut(&mut self, receiver: &mut ReceiverKind) {
47        match receiver {
48            ReceiverKind::Value => {}
49            ReceiverKind::Reference(reference, lifetime, _mutability) => {
50                self.visit_opt_lifetime(reference, lifetime);
51            }
52            ReceiverKind::Typed(_colon, ty) => {
53                visit_mut::visit_type_mut(self, ty);
54            }
55            _ => {}
56        }
57    }
58
59    fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
60        self.visit_opt_lifetime(&ty.and_token, &mut ty.lifetime);
61        visit_mut::visit_type_reference_mut(self, ty);
62    }
63
64    fn visit_generic_argument_mut(&mut self, gen: &mut GenericArgument) {
65        if let GenericArgument::Lifetime(lifetime) = gen {
66            self.visit_lifetime(lifetime);
67        }
68        visit_mut::visit_generic_argument_mut(self, gen);
69    }
70}
71
72pub struct AddLifetimeToImplTrait;
73
74impl VisitMut for AddLifetimeToImplTrait {
75    fn visit_type_impl_trait_mut(&mut self, ty: &mut TypeImplTrait) {
76        let span = ty.impl_token.span;
77        let lifetime = ::syn::__private::parse_quote({
        let _span: ::quote::__private::Span =
            ::quote::__private::get_span(span).__into_span();
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_lifetime_spanned(&mut _s, _span,
            "\'async_trait");
        _s
    })parse_quote_spanned!(span=> 'async_trait);
78        ty.bounds.insert(0, lifetime);
79        if let Some(punct) = ty.bounds.pairs_mut().next().unwrap().punct_mut() {
80            punct.span = span;
81        }
82        visit_mut::visit_type_impl_trait_mut(self, ty);
83    }
84
85    fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
86        parenthesize_impl_trait(&mut ty.elem, ty.and_token.span);
87        visit_mut::visit_type_reference_mut(self, ty);
88    }
89
90    fn visit_type_ptr_mut(&mut self, ty: &mut TypePtr) {
91        parenthesize_impl_trait(&mut ty.elem, ty.star_token.span);
92        visit_mut::visit_type_ptr_mut(self, ty);
93    }
94
95    fn visit_type_fn_ptr_mut(&mut self, ty: &mut TypeFnPtr) {
96        if let ReturnType::Type(arrow, return_type) = &mut ty.output {
97            parenthesize_impl_trait(return_type, arrow.spans[0]);
98        }
99        visit_mut::visit_type_fn_ptr_mut(self, ty);
100    }
101
102    fn visit_expr_mut(&mut self, _e: &mut Expr) {
103        // Do not recurse into impl Traits inside of an array length expression.
104        //
105        //    fn outer(arg: [u8; { fn inner(_: impl Trait) {}; 0 }]);
106    }
107}
108
109fn parenthesize_impl_trait(elem: &mut Type, paren_span: Span) {
110    if let Type::ImplTrait(_) = *elem {
111        let placeholder = Type::Verbatim(TokenStream::new());
112        *elem = Type::Paren(TypeParen {
113            attrs: Vec::new(),
114            paren_token: token::Paren(paren_span),
115            elem: Box::new(mem::replace(elem, placeholder)),
116        });
117    }
118}