cxxbridge_macro/
generics.rs1use crate::expand::display_namespaced;
2use crate::syntax::instantiate::NamedImplKey;
3use crate::syntax::types::ConditionalImpl;
4use crate::syntax::{Lifetimes, Type, Types};
5use proc_macro2::TokenStream;
6use quote::{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 get_impl_generics(key.inner, types)
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 Type::RustBox(ty1) => {
65 let inner = ResolvedGenericType {
66 ty: &ty1.inner,
67 explicit_impl: self.explicit_impl,
68 types: self.types,
69 };
70 tokens.extend({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "cxx");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "alloc");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "boxed");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Box");
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&inner, &mut _s);
::quote::__private::push_gt(&mut _s);
_s
}quote! {
71 ::cxx::alloc::boxed::Box<#inner>
72 });
73 }
74 _ => {
::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"),
75 }
76 }
77}
78
79fn get_impl_generics<'a>(ty: &Type, types: &Types<'a>) -> &'a Lifetimes {
80 match ty {
81 Type::Ident(named_type) => types.resolve(named_type).generics,
82 Type::RustBox(ty1) => get_impl_generics(&ty1.inner, types),
83 _ => {
::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"),
84 }
85}
86
87pub(crate) fn format_for_prevent_unwind_label(ty: &Type) -> TokenStream {
88 match ty {
89 Type::Ident(named_type) => {
90 let rust_name = named_type.rust.to_string();
91 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "cxx");
::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, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "cxx");
::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, "module_path");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\"::\"");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&rust_name, &mut _s);
_s
});
_s
}quote! {
92 ::cxx::core::concat!(::cxx::core::module_path!(), "::", #rust_name)
93 }
94 }
95 Type::RustBox(ty1) => {
96 let inner = format_for_prevent_unwind_label(&ty1.inner);
97 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "cxx");
::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, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s, "\"Box<\"");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&inner, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\">\"");
_s
});
_s
}quote! {
98 ::cxx::core::concat!("Box<", #inner, ">")
99 }
100 }
101 _ => {
::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"),
102 }
103}
104
105pub(crate) fn concise_rust_name(ty: &Type) -> String {
106 match ty {
107 Type::Ident(named_type) => named_type.rust.to_string(),
108 Type::RustBox(ty1) => {
109 let inner = concise_rust_name(&ty1.inner);
110 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Box<{0}>", inner))
})format!("Box<{inner}>")
111 }
112 _ => {
::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"),
113 }
114}
115
116pub(crate) fn concise_cxx_name(ty: &Type, types: &Types) -> String {
117 match ty {
118 Type::Ident(named_type) => {
119 let res = types.resolve(&named_type.rust);
120 display_namespaced(res.name).to_string()
121 }
122 Type::RustBox(ty1) => {
123 let inner = concise_cxx_name(&ty1.inner, types);
124 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("rust::Box<{0}>", inner))
})format!("rust::Box<{inner}>")
125 }
126 _ => {
::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"),
127 }
128}
129
130pub(crate) struct UnderscoreLifetimes<'a> {
131 generics: &'a Lifetimes,
132}
133
134impl Lifetimes {
135 pub(crate) fn to_underscore_lifetimes(&self) -> UnderscoreLifetimes {
136 UnderscoreLifetimes { generics: self }
137 }
138}
139
140impl<'a> ToTokens for UnderscoreLifetimes<'a> {
141 fn to_tokens(&self, tokens: &mut TokenStream) {
142 let Lifetimes {
143 lt_token,
144 lifetimes,
145 gt_token,
146 } = self.generics;
147 lt_token.to_tokens(tokens);
148 for pair in lifetimes.pairs() {
149 let (lifetime, punct) = pair.into_tuple();
150 let lifetime = Lifetime::new("'_", lifetime.span());
151 lifetime.to_tokens(tokens);
152 punct.to_tokens(tokens);
153 }
154 gt_token.to_tokens(tokens);
155 }
156}