cxxbridge_macro/
generics.rs

1use crate::syntax::instantiate::NamedImplKey;
2use crate::syntax::resolve::Resolution;
3use crate::syntax::types::ConditionalImpl;
4use crate::syntax::{Impl, Lifetimes};
5use proc_macro2::TokenStream;
6use quote::ToTokens;
7use syn::{Lifetime, Token};
8
9pub(crate) struct ImplGenerics<'a> {
10    explicit_impl: Option<&'a Impl>,
11    resolve: Resolution<'a>,
12}
13
14pub(crate) struct TyGenerics<'a> {
15    key: &'a NamedImplKey<'a>,
16    explicit_impl: Option<&'a Impl>,
17    resolve: Resolution<'a>,
18}
19
20pub(crate) fn split_for_impl<'a>(
21    key: &'a NamedImplKey<'a>,
22    conditional_impl: &ConditionalImpl<'a>,
23    resolve: Resolution<'a>,
24) -> (ImplGenerics<'a>, TyGenerics<'a>) {
25    let impl_generics = ImplGenerics {
26        explicit_impl: conditional_impl.explicit_impl,
27        resolve,
28    };
29    let ty_generics = TyGenerics {
30        key,
31        explicit_impl: conditional_impl.explicit_impl,
32        resolve,
33    };
34    (impl_generics, ty_generics)
35}
36
37impl<'a> ToTokens for ImplGenerics<'a> {
38    fn to_tokens(&self, tokens: &mut TokenStream) {
39        if let Some(imp) = self.explicit_impl {
40            imp.impl_generics.to_tokens(tokens);
41        } else {
42            self.resolve.generics.to_tokens(tokens);
43        }
44    }
45}
46
47impl<'a> ToTokens for TyGenerics<'a> {
48    fn to_tokens(&self, tokens: &mut TokenStream) {
49        if let Some(imp) = self.explicit_impl {
50            imp.ty_generics.to_tokens(tokens);
51        } else if !self.resolve.generics.lifetimes.is_empty() {
52            let span = self.key.rust.span();
53            self.key
54                .lt_token
55                .unwrap_or_else(|| Token![<](span))
56                .to_tokens(tokens);
57            self.resolve.generics.lifetimes.to_tokens(tokens);
58            self.key
59                .gt_token
60                .unwrap_or_else(|| Token![>](span))
61                .to_tokens(tokens);
62        }
63    }
64}
65
66pub(crate) struct UnderscoreLifetimes<'a> {
67    generics: &'a Lifetimes,
68}
69
70impl Lifetimes {
71    pub(crate) fn to_underscore_lifetimes(&self) -> UnderscoreLifetimes {
72        UnderscoreLifetimes { generics: self }
73    }
74}
75
76impl<'a> ToTokens for UnderscoreLifetimes<'a> {
77    fn to_tokens(&self, tokens: &mut TokenStream) {
78        let Lifetimes {
79            lt_token,
80            lifetimes,
81            gt_token,
82        } = self.generics;
83        lt_token.to_tokens(tokens);
84        for pair in lifetimes.pairs() {
85            let (lifetime, punct) = pair.into_tuple();
86            let lifetime = Lifetime::new("'_", lifetime.span());
87            lifetime.to_tokens(tokens);
88            punct.to_tokens(tokens);
89        }
90        gt_token.to_tokens(tokens);
91    }
92}