cxxbridge_macro/
generics.rs1use crate::expand::display_namespaced;
2use crate::syntax::instantiate::NamedImplKey;
3use crate::syntax::types::ConditionalImpl;
4use crate::syntax::{Lifetimes, NamedType, Type, Types};
5use proc_macro2::TokenStream;
6use quote::ToTokens;
7use syn::{Lifetime, Token};
8
9pub(crate) struct ResolvedGenericType<'a> {
10 ty: &'a Type,
11 explicit_impl: bool,
12 types: &'a Types<'a>,
13}
14
15pub(crate) fn split_for_impl<'a>(
22 key: &NamedImplKey<'a>,
23 conditional_impl: &ConditionalImpl<'a>,
24 types: &'a Types<'a>,
25) -> (&'a Lifetimes, ResolvedGenericType<'a>) {
26 let impl_generics = if let Some(explicit_impl) = conditional_impl.explicit_impl {
27 &explicit_impl.impl_generics
28 } else {
29 types.resolve(local_type(key.inner)).generics
30 };
31 let ty_generics = ResolvedGenericType {
32 ty: key.inner,
33 explicit_impl: conditional_impl.explicit_impl.is_some(),
34 types,
35 };
36 (impl_generics, ty_generics)
37}
38
39impl<'a> ToTokens for ResolvedGenericType<'a> {
40 fn to_tokens(&self, tokens: &mut TokenStream) {
41 match self.ty {
42 Type::Ident(named_type) => {
43 named_type.rust.to_tokens(tokens);
44 if self.explicit_impl {
45 named_type.generics.to_tokens(tokens);
46 } else {
47 let resolve = self.types.resolve(named_type);
48 if !resolve.generics.lifetimes.is_empty() {
49 let span = named_type.rust.span();
50 named_type
51 .generics
52 .lt_token
53 .unwrap_or_else(|| ::syn::token::LtToken)
54 .to_tokens(tokens);
55 resolve.generics.lifetimes.to_tokens(tokens);
56 named_type
57 .generics
58 .gt_token
59 .unwrap_or_else(|| ::syn::token::GtToken)
60 .to_tokens(tokens);
61 }
62 }
63 }
64 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("syntax/check.rs should reject other types")));
}unreachable!("syntax/check.rs should reject other types"),
65 }
66 }
67}
68
69pub(crate) fn local_type(ty: &Type) -> &NamedType {
70 match ty {
71 Type::Ident(named_type) => named_type,
72 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("syntax/check.rs should reject other types")));
}unreachable!("syntax/check.rs should reject other types"),
73 }
74}
75
76pub(crate) fn concise_rust_name(ty: &Type) -> String {
77 match ty {
78 Type::Ident(named_type) => named_type.rust.to_string(),
79 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("syntax/check.rs should reject other types")));
}unreachable!("syntax/check.rs should reject other types"),
80 }
81}
82
83pub(crate) fn concise_cxx_name(ty: &Type, types: &Types) -> String {
84 match ty {
85 Type::Ident(named_type) => {
86 let res = types.resolve(&named_type.rust);
87 display_namespaced(res.name).to_string()
88 }
89 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("syntax/check.rs should reject other types")));
}unreachable!("syntax/check.rs should reject other types"),
90 }
91}
92
93pub(crate) struct UnderscoreLifetimes<'a> {
94 generics: &'a Lifetimes,
95}
96
97impl Lifetimes {
98 pub(crate) fn to_underscore_lifetimes(&self) -> UnderscoreLifetimes {
99 UnderscoreLifetimes { generics: self }
100 }
101}
102
103impl<'a> ToTokens for UnderscoreLifetimes<'a> {
104 fn to_tokens(&self, tokens: &mut TokenStream) {
105 let Lifetimes {
106 lt_token,
107 lifetimes,
108 gt_token,
109 } = self.generics;
110 lt_token.to_tokens(tokens);
111 for pair in lifetimes.pairs() {
112 let (lifetime, punct) = pair.into_tuple();
113 let lifetime = Lifetime::new("'_", lifetime.span());
114 lifetime.to_tokens(tokens);
115 punct.to_tokens(tokens);
116 }
117 gt_token.to_tokens(tokens);
118 }
119}