1 use crate::syntax::atom::Atom::*;
2 use crate::syntax::attrs::{self, OtherAttrs};
3 use crate::syntax::cfg::CfgExpr;
4 use crate::syntax::file::Module;
5 use crate::syntax::instantiate::{ImplKey, NamedImplKey};
6 use crate::syntax::qualified::QualifiedName;
7 use crate::syntax::report::Errors;
8 use crate::syntax::symbol::Symbol;
9 use crate::syntax::{
10     self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature,
11     Struct, Trait, Type, TypeAlias, Types,
12 };
13 use crate::type_id::Crate;
14 use crate::{derive, generics};
15 use proc_macro2::{Ident, Span, TokenStream};
16 use quote::{format_ident, quote, quote_spanned, ToTokens};
17 use std::mem;
18 use syn::{parse_quote, punctuated, Generics, Lifetime, Result, Token};
19 
bridge(mut ffi: Module) -> Result<TokenStream>20 pub(crate) fn bridge(mut ffi: Module) -> Result<TokenStream> {
21     let ref mut errors = Errors::new();
22 
23     let mut cfg = CfgExpr::Unconditional;
24     let mut doc = Doc::new();
25     let attrs = attrs::parse(
26         errors,
27         mem::take(&mut ffi.attrs),
28         attrs::Parser {
29             cfg: Some(&mut cfg),
30             doc: Some(&mut doc),
31             ..Default::default()
32         },
33     );
34 
35     let content = mem::take(&mut ffi.content);
36     let trusted = ffi.unsafety.is_some();
37     let namespace = &ffi.namespace;
38     let ref mut apis = syntax::parse_items(errors, content, trusted, namespace);
39     #[cfg(feature = "experimental-enum-variants-from-header")]
40     crate::load::load(errors, apis);
41     let ref types = Types::collect(errors, apis);
42     errors.propagate()?;
43 
44     let generator = check::Generator::Macro;
45     check::typecheck(errors, apis, types, generator);
46     errors.propagate()?;
47 
48     Ok(expand(ffi, doc, attrs, apis, types))
49 }
50 
expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream51 fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream {
52     let mut expanded = TokenStream::new();
53     let mut hidden = TokenStream::new();
54     let mut forbid = TokenStream::new();
55 
56     for api in apis {
57         if let Api::RustType(ety) = api {
58             expanded.extend(expand_rust_type_import(ety));
59             hidden.extend(expand_rust_type_assert_unpin(ety, types));
60         }
61     }
62 
63     for api in apis {
64         match api {
65             Api::Include(_) | Api::Impl(_) => {}
66             Api::Struct(strct) => {
67                 expanded.extend(expand_struct(strct));
68                 hidden.extend(expand_struct_operators(strct));
69                 forbid.extend(expand_struct_forbid_drop(strct));
70             }
71             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
72             Api::CxxType(ety) => {
73                 let ident = &ety.name.rust;
74                 if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
75                     expanded.extend(expand_cxx_type(ety));
76                     hidden.extend(expand_cxx_type_assert_pinned(ety, types));
77                 }
78             }
79             Api::CxxFunction(efn) => {
80                 expanded.extend(expand_cxx_function_shim(efn, types));
81             }
82             Api::RustType(ety) => {
83                 expanded.extend(expand_rust_type_impl(ety));
84                 hidden.extend(expand_rust_type_layout(ety, types));
85             }
86             Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
87             Api::TypeAlias(alias) => {
88                 expanded.extend(expand_type_alias(alias));
89                 hidden.extend(expand_type_alias_verify(alias, types));
90             }
91         }
92     }
93 
94     for (impl_key, &explicit_impl) in &types.impls {
95         match *impl_key {
96             ImplKey::RustBox(ident) => {
97                 hidden.extend(expand_rust_box(ident, types, explicit_impl));
98             }
99             ImplKey::RustVec(ident) => {
100                 hidden.extend(expand_rust_vec(ident, types, explicit_impl));
101             }
102             ImplKey::UniquePtr(ident) => {
103                 expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
104             }
105             ImplKey::SharedPtr(ident) => {
106                 expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
107             }
108             ImplKey::WeakPtr(ident) => {
109                 expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
110             }
111             ImplKey::CxxVector(ident) => {
112                 expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
113             }
114         }
115     }
116 
117     if !forbid.is_empty() {
118         hidden.extend(expand_forbid(forbid));
119     }
120 
121     // Work around https://github.com/rust-lang/rust/issues/67851.
122     if !hidden.is_empty() {
123         expanded.extend(quote! {
124             #[doc(hidden)]
125             const _: () = {
126                 #hidden
127             };
128         });
129     }
130 
131     let vis = &ffi.vis;
132     let mod_token = &ffi.mod_token;
133     let ident = &ffi.ident;
134     let span = ffi.brace_token.span;
135     let expanded = quote_spanned!(span=> {#expanded});
136 
137     quote! {
138         #doc
139         #attrs
140         #[deny(improper_ctypes, improper_ctypes_definitions)]
141         #[allow(clippy::unknown_clippy_lints)]
142         #[allow(
143             non_camel_case_types,
144             non_snake_case,
145             unused_unsafe, // FIXME: only needed by rustc 1.64 and older
146             clippy::extra_unused_type_parameters,
147             clippy::items_after_statements,
148             clippy::no_effect_underscore_binding,
149             clippy::ptr_as_ptr,
150             clippy::ref_as_ptr,
151             clippy::upper_case_acronyms,
152             clippy::use_self,
153         )]
154         #vis #mod_token #ident #expanded
155     }
156 }
157 
expand_struct(strct: &Struct) -> TokenStream158 fn expand_struct(strct: &Struct) -> TokenStream {
159     let ident = &strct.name.rust;
160     let doc = &strct.doc;
161     let attrs = &strct.attrs;
162     let generics = &strct.generics;
163     let type_id = type_id(&strct.name);
164     let fields = strct.fields.iter().map(|field| {
165         let doc = &field.doc;
166         let attrs = &field.attrs;
167         // This span on the pub makes "private type in public interface" errors
168         // appear in the right place.
169         let vis = field.visibility;
170         quote!(#doc #attrs #vis #field)
171     });
172     let mut derives = None;
173     let derived_traits = derive::expand_struct(strct, &mut derives);
174 
175     let span = ident.span();
176     let visibility = strct.visibility;
177     let struct_token = strct.struct_token;
178     let struct_def = quote_spanned! {span=>
179         #visibility #struct_token #ident #generics {
180             #(#fields,)*
181         }
182     };
183 
184     quote! {
185         #doc
186         #derives
187         #attrs
188         #[repr(C)]
189         #struct_def
190 
191         unsafe impl #generics ::cxx::ExternType for #ident #generics {
192             #[allow(unused_attributes)] // incorrect lint
193             #[doc(hidden)]
194             type Id = #type_id;
195             type Kind = ::cxx::kind::Trivial;
196         }
197 
198         #derived_traits
199     }
200 }
201 
expand_struct_operators(strct: &Struct) -> TokenStream202 fn expand_struct_operators(strct: &Struct) -> TokenStream {
203     let ident = &strct.name.rust;
204     let generics = &strct.generics;
205     let mut operators = TokenStream::new();
206 
207     for derive in &strct.derives {
208         let span = derive.span;
209         match derive.what {
210             Trait::PartialEq => {
211                 let link_name = mangle::operator(&strct.name, "eq");
212                 let local_name = format_ident!("__operator_eq_{}", strct.name.rust);
213                 let prevent_unwind_label = format!("::{} as PartialEq>::eq", strct.name.rust);
214                 operators.extend(quote_spanned! {span=>
215                     #[doc(hidden)]
216                     #[export_name = #link_name]
217                     extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
218                         let __fn = concat!("<", module_path!(), #prevent_unwind_label);
219                         ::cxx::private::prevent_unwind(__fn, || *lhs == *rhs)
220                     }
221                 });
222 
223                 if !derive::contains(&strct.derives, Trait::Eq) {
224                     let link_name = mangle::operator(&strct.name, "ne");
225                     let local_name = format_ident!("__operator_ne_{}", strct.name.rust);
226                     let prevent_unwind_label = format!("::{} as PartialEq>::ne", strct.name.rust);
227                     operators.extend(quote_spanned! {span=>
228                         #[doc(hidden)]
229                         #[export_name = #link_name]
230                         extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
231                             let __fn = concat!("<", module_path!(), #prevent_unwind_label);
232                             ::cxx::private::prevent_unwind(__fn, || *lhs != *rhs)
233                         }
234                     });
235                 }
236             }
237             Trait::PartialOrd => {
238                 let link_name = mangle::operator(&strct.name, "lt");
239                 let local_name = format_ident!("__operator_lt_{}", strct.name.rust);
240                 let prevent_unwind_label = format!("::{} as PartialOrd>::lt", strct.name.rust);
241                 operators.extend(quote_spanned! {span=>
242                     #[doc(hidden)]
243                     #[export_name = #link_name]
244                     extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
245                         let __fn = concat!("<", module_path!(), #prevent_unwind_label);
246                         ::cxx::private::prevent_unwind(__fn, || *lhs < *rhs)
247                     }
248                 });
249 
250                 let link_name = mangle::operator(&strct.name, "le");
251                 let local_name = format_ident!("__operator_le_{}", strct.name.rust);
252                 let prevent_unwind_label = format!("::{} as PartialOrd>::le", strct.name.rust);
253                 operators.extend(quote_spanned! {span=>
254                     #[doc(hidden)]
255                     #[export_name = #link_name]
256                     extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
257                         let __fn = concat!("<", module_path!(), #prevent_unwind_label);
258                         ::cxx::private::prevent_unwind(__fn, || *lhs <= *rhs)
259                     }
260                 });
261 
262                 if !derive::contains(&strct.derives, Trait::Ord) {
263                     let link_name = mangle::operator(&strct.name, "gt");
264                     let local_name = format_ident!("__operator_gt_{}", strct.name.rust);
265                     let prevent_unwind_label = format!("::{} as PartialOrd>::gt", strct.name.rust);
266                     operators.extend(quote_spanned! {span=>
267                         #[doc(hidden)]
268                         #[export_name = #link_name]
269                         extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
270                             let __fn = concat!("<", module_path!(), #prevent_unwind_label);
271                             ::cxx::private::prevent_unwind(__fn, || *lhs > *rhs)
272                         }
273                     });
274 
275                     let link_name = mangle::operator(&strct.name, "ge");
276                     let local_name = format_ident!("__operator_ge_{}", strct.name.rust);
277                     let prevent_unwind_label = format!("::{} as PartialOrd>::ge", strct.name.rust);
278                     operators.extend(quote_spanned! {span=>
279                         #[doc(hidden)]
280                         #[export_name = #link_name]
281                         extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
282                             let __fn = concat!("<", module_path!(), #prevent_unwind_label);
283                             ::cxx::private::prevent_unwind(__fn, || *lhs >= *rhs)
284                         }
285                     });
286                 }
287             }
288             Trait::Hash => {
289                 let link_name = mangle::operator(&strct.name, "hash");
290                 let local_name = format_ident!("__operator_hash_{}", strct.name.rust);
291                 let prevent_unwind_label = format!("::{} as Hash>::hash", strct.name.rust);
292                 operators.extend(quote_spanned! {span=>
293                     #[doc(hidden)]
294                     #[export_name = #link_name]
295                     #[allow(clippy::cast_possible_truncation)]
296                     extern "C" fn #local_name #generics(this: &#ident #generics) -> usize {
297                         let __fn = concat!("<", module_path!(), #prevent_unwind_label);
298                         ::cxx::private::prevent_unwind(__fn, || ::cxx::private::hash(this))
299                     }
300                 });
301             }
302             _ => {}
303         }
304     }
305 
306     operators
307 }
308 
expand_struct_forbid_drop(strct: &Struct) -> TokenStream309 fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
310     let ident = &strct.name.rust;
311     let generics = &strct.generics;
312     let span = ident.span();
313     let impl_token = Token![impl](strct.visibility.span);
314 
315     quote_spanned! {span=>
316         #impl_token #generics self::Drop for super::#ident #generics {}
317     }
318 }
319 
expand_enum(enm: &Enum) -> TokenStream320 fn expand_enum(enm: &Enum) -> TokenStream {
321     let ident = &enm.name.rust;
322     let doc = &enm.doc;
323     let attrs = &enm.attrs;
324     let repr = &enm.repr;
325     let type_id = type_id(&enm.name);
326     let variants = enm.variants.iter().map(|variant| {
327         let doc = &variant.doc;
328         let attrs = &variant.attrs;
329         let variant_ident = &variant.name.rust;
330         let discriminant = &variant.discriminant;
331         let span = variant_ident.span();
332         Some(quote_spanned! {span=>
333             #doc
334             #attrs
335             #[allow(dead_code)]
336             pub const #variant_ident: Self = #ident { repr: #discriminant };
337         })
338     });
339     let mut derives = None;
340     let derived_traits = derive::expand_enum(enm, &mut derives);
341 
342     let span = ident.span();
343     let visibility = enm.visibility;
344     let struct_token = Token![struct](enm.enum_token.span);
345     let enum_repr = quote! {
346         #[allow(missing_docs)]
347         pub repr: #repr,
348     };
349     let enum_def = quote_spanned! {span=>
350         #visibility #struct_token #ident {
351             #enum_repr
352         }
353     };
354 
355     quote! {
356         #doc
357         #derives
358         #attrs
359         #[repr(transparent)]
360         #enum_def
361 
362         #[allow(non_upper_case_globals)]
363         impl #ident {
364             #(#variants)*
365         }
366 
367         unsafe impl ::cxx::ExternType for #ident {
368             #[allow(unused_attributes)] // incorrect lint
369             #[doc(hidden)]
370             type Id = #type_id;
371             type Kind = ::cxx::kind::Trivial;
372         }
373 
374         #derived_traits
375     }
376 }
377 
expand_cxx_type(ety: &ExternType) -> TokenStream378 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
379     let ident = &ety.name.rust;
380     let doc = &ety.doc;
381     let attrs = &ety.attrs;
382     let generics = &ety.generics;
383     let type_id = type_id(&ety.name);
384 
385     let lifetime_fields = ety.generics.lifetimes.iter().map(|lifetime| {
386         let field = format_ident!("_lifetime_{}", lifetime.ident);
387         quote!(#field: ::cxx::core::marker::PhantomData<&#lifetime ()>)
388     });
389     let repr_fields = quote! {
390         _private: ::cxx::private::Opaque,
391         #(#lifetime_fields,)*
392     };
393 
394     let span = ident.span();
395     let visibility = &ety.visibility;
396     let struct_token = Token![struct](ety.type_token.span);
397     let extern_type_def = quote_spanned! {span=>
398         #visibility #struct_token #ident #generics {
399             #repr_fields
400         }
401     };
402 
403     quote! {
404         #doc
405         #attrs
406         #[repr(C)]
407         #extern_type_def
408 
409         unsafe impl #generics ::cxx::ExternType for #ident #generics {
410             #[allow(unused_attributes)] // incorrect lint
411             #[doc(hidden)]
412             type Id = #type_id;
413             type Kind = ::cxx::kind::Opaque;
414         }
415     }
416 }
417 
expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream418 fn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream {
419     let ident = &ety.name.rust;
420     let infer = Token![_](ident.span());
421 
422     let resolve = types.resolve(ident);
423     let lifetimes = resolve.generics.to_underscore_lifetimes();
424 
425     quote! {
426         let _: fn() = {
427             // Derived from https://github.com/nvzqz/static-assertions-rs.
428             trait __AmbiguousIfImpl<A> {
429                 fn infer() {}
430             }
431 
432             impl<T> __AmbiguousIfImpl<()> for T
433             where
434                 T: ?::cxx::core::marker::Sized
435             {}
436 
437             #[allow(dead_code)]
438             struct __Invalid;
439 
440             impl<T> __AmbiguousIfImpl<__Invalid> for T
441             where
442                 T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin,
443             {}
444 
445             // If there is only one specialized trait impl, type inference with
446             // `_` can be resolved and this can compile. Fails to compile if
447             // user has added a manual Unpin impl for their opaque C++ type as
448             // then `__AmbiguousIfImpl<__Invalid>` also exists.
449             <#ident #lifetimes as __AmbiguousIfImpl<#infer>>::infer
450         };
451     }
452 }
453 
expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream454 fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
455     let generics = &efn.generics;
456     let receiver = efn.receiver.iter().map(|receiver| {
457         let receiver_type = receiver.ty();
458         quote!(_: #receiver_type)
459     });
460     let args = efn.args.iter().map(|arg| {
461         let var = &arg.name.rust;
462         let colon = arg.colon_token;
463         let ty = expand_extern_type(&arg.ty, types, true);
464         if arg.ty == RustString {
465             quote!(#var #colon *const #ty)
466         } else if let Type::RustVec(_) = arg.ty {
467             quote!(#var #colon *const #ty)
468         } else if let Type::Fn(_) = arg.ty {
469             quote!(#var #colon ::cxx::private::FatFunction)
470         } else if types.needs_indirect_abi(&arg.ty) {
471             quote!(#var #colon *mut #ty)
472         } else {
473             quote!(#var #colon #ty)
474         }
475     });
476     let all_args = receiver.chain(args);
477     let ret = if efn.throws {
478         quote!(-> ::cxx::private::Result)
479     } else {
480         expand_extern_return_type(&efn.ret, types, true)
481     };
482     let mut outparam = None;
483     if indirect_return(efn, types) {
484         let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
485         outparam = Some(quote!(__return: *mut #ret));
486     }
487     let link_name = mangle::extern_fn(efn, types);
488     let local_name = format_ident!("__{}", efn.name.rust);
489     quote! {
490         #[link_name = #link_name]
491         fn #local_name #generics(#(#all_args,)* #outparam) #ret;
492     }
493 }
494 
expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream495 fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
496     let doc = &efn.doc;
497     let attrs = &efn.attrs;
498     let decl = expand_cxx_function_decl(efn, types);
499     let receiver = efn.receiver.iter().map(|receiver| {
500         let var = receiver.var;
501         if receiver.pinned {
502             let colon = receiver.colon_token;
503             let ty = receiver.ty_self();
504             quote!(#var #colon #ty)
505         } else {
506             let ampersand = receiver.ampersand;
507             let lifetime = &receiver.lifetime;
508             let mutability = receiver.mutability;
509             quote!(#ampersand #lifetime #mutability #var)
510         }
511     });
512     let args = efn.args.iter().map(|arg| quote!(#arg));
513     let all_args = receiver.chain(args);
514     let ret = if efn.throws {
515         let ok = match &efn.ret {
516             Some(ret) => quote!(#ret),
517             None => quote!(()),
518         };
519         quote!(-> ::cxx::core::result::Result<#ok, ::cxx::Exception>)
520     } else {
521         expand_return_type(&efn.ret)
522     };
523     let indirect_return = indirect_return(efn, types);
524     let receiver_var = efn
525         .receiver
526         .iter()
527         .map(|receiver| receiver.var.to_token_stream());
528     let arg_vars = efn.args.iter().map(|arg| {
529         let var = &arg.name.rust;
530         let span = var.span();
531         match &arg.ty {
532             Type::Ident(ident) if ident.rust == RustString => {
533                 quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustString)
534             }
535             Type::RustBox(ty) => {
536                 if types.is_considered_improper_ctype(&ty.inner) {
537                     quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var).cast())
538                 } else {
539                     quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var))
540                 }
541             }
542             Type::UniquePtr(ty) => {
543                 if types.is_considered_improper_ctype(&ty.inner) {
544                     quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var).cast())
545                 } else {
546                     quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var))
547                 }
548             }
549             Type::RustVec(_) => quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
550             Type::Ref(ty) => match &ty.inner {
551                 Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
552                     false => quote_spanned!(span=> ::cxx::private::RustString::from_ref(#var)),
553                     true => quote_spanned!(span=> ::cxx::private::RustString::from_mut(#var)),
554                 },
555                 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
556                     false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string(#var)),
557                     true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string(#var)),
558                 },
559                 Type::RustVec(_) => match ty.mutable {
560                     false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref(#var)),
561                     true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut(#var)),
562                 },
563                 inner if types.is_considered_improper_ctype(inner) => {
564                     let var = match ty.pinned {
565                         false => quote!(#var),
566                         true => quote_spanned!(span=> ::cxx::core::pin::Pin::into_inner_unchecked(#var)),
567                     };
568                     match ty.mutable {
569                         false => {
570                             quote_spanned!(span=> #var as *const #inner as *const ::cxx::core::ffi::c_void)
571                         }
572                         true => quote_spanned!(span=> #var as *mut #inner as *mut ::cxx::core::ffi::c_void),
573                     }
574                 }
575                 _ => quote!(#var),
576             },
577             Type::Ptr(ty) => {
578                 if types.is_considered_improper_ctype(&ty.inner) {
579                     quote_spanned!(span=> #var.cast())
580                 } else {
581                     quote!(#var)
582                 }
583             }
584             Type::Str(_) => quote_spanned!(span=> ::cxx::private::RustStr::from(#var)),
585             Type::SliceRef(ty) => match ty.mutable {
586                 false => quote_spanned!(span=> ::cxx::private::RustSlice::from_ref(#var)),
587                 true => quote_spanned!(span=> ::cxx::private::RustSlice::from_mut(#var)),
588             },
589             ty if types.needs_indirect_abi(ty) => quote_spanned!(span=> #var.as_mut_ptr()),
590             _ => quote!(#var),
591         }
592     });
593     let vars = receiver_var.chain(arg_vars);
594     let trampolines = efn
595         .args
596         .iter()
597         .filter_map(|arg| {
598             if let Type::Fn(f) = &arg.ty {
599                 let var = &arg.name;
600                 Some(expand_function_pointer_trampoline(efn, var, f, types))
601             } else {
602                 None
603             }
604         })
605         .collect::<TokenStream>();
606     let mut setup = efn
607         .args
608         .iter()
609         .filter(|arg| types.needs_indirect_abi(&arg.ty))
610         .map(|arg| {
611             let var = &arg.name.rust;
612             let span = var.span();
613             // These are arguments for which C++ has taken ownership of the data
614             // behind the mut reference it received.
615             quote_spanned! {span=>
616                 let mut #var = ::cxx::core::mem::MaybeUninit::new(#var);
617             }
618         })
619         .collect::<TokenStream>();
620     let local_name = format_ident!("__{}", efn.name.rust);
621     let span = efn.semi_token.span;
622     let call = if indirect_return {
623         let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
624         setup.extend(quote_spanned! {span=>
625             let mut __return = ::cxx::core::mem::MaybeUninit::<#ret>::uninit();
626         });
627         setup.extend(if efn.throws {
628             quote_spanned! {span=>
629                 #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
630             }
631         } else {
632             quote_spanned! {span=>
633                 #local_name(#(#vars,)* __return.as_mut_ptr());
634             }
635         });
636         quote_spanned!(span=> __return.assume_init())
637     } else if efn.throws {
638         quote_spanned! {span=>
639             #local_name(#(#vars),*).exception()
640         }
641     } else {
642         quote_spanned! {span=>
643             #local_name(#(#vars),*)
644         }
645     };
646     let mut expr;
647     if efn.throws && efn.sig.ret.is_none() {
648         expr = call;
649     } else {
650         expr = match &efn.ret {
651             None => call,
652             Some(ret) => match ret {
653                 Type::Ident(ident) if ident.rust == RustString => {
654                     quote_spanned!(span=> #call.into_string())
655                 }
656                 Type::RustBox(ty) => {
657                     if types.is_considered_improper_ctype(&ty.inner) {
658                         quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call.cast()))
659                     } else {
660                         quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call))
661                     }
662                 }
663                 Type::RustVec(vec) => {
664                     if vec.inner == RustString {
665                         quote_spanned!(span=> #call.into_vec_string())
666                     } else {
667                         quote_spanned!(span=> #call.into_vec())
668                     }
669                 }
670                 Type::UniquePtr(ty) => {
671                     if types.is_considered_improper_ctype(&ty.inner) {
672                         quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call.cast()))
673                     } else {
674                         quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call))
675                     }
676                 }
677                 Type::Ref(ty) => match &ty.inner {
678                     Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
679                         false => quote_spanned!(span=> #call.as_string()),
680                         true => quote_spanned!(span=> #call.as_mut_string()),
681                     },
682                     Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
683                         false => quote_spanned!(span=> #call.as_vec_string()),
684                         true => quote_spanned!(span=> #call.as_mut_vec_string()),
685                     },
686                     Type::RustVec(_) => match ty.mutable {
687                         false => quote_spanned!(span=> #call.as_vec()),
688                         true => quote_spanned!(span=> #call.as_mut_vec()),
689                     },
690                     inner if types.is_considered_improper_ctype(inner) => {
691                         let mutability = ty.mutability;
692                         let deref_mut = quote_spanned!(span=> &#mutability *#call.cast());
693                         match ty.pinned {
694                             false => deref_mut,
695                             true => {
696                                 quote_spanned!(span=> ::cxx::core::pin::Pin::new_unchecked(#deref_mut))
697                             }
698                         }
699                     }
700                     _ => call,
701                 },
702                 Type::Ptr(ty) => {
703                     if types.is_considered_improper_ctype(&ty.inner) {
704                         quote_spanned!(span=> #call.cast())
705                     } else {
706                         call
707                     }
708                 }
709                 Type::Str(_) => quote_spanned!(span=> #call.as_str()),
710                 Type::SliceRef(slice) => {
711                     let inner = &slice.inner;
712                     match slice.mutable {
713                         false => quote_spanned!(span=> #call.as_slice::<#inner>()),
714                         true => quote_spanned!(span=> #call.as_mut_slice::<#inner>()),
715                     }
716                 }
717                 _ => call,
718             },
719         };
720         if efn.throws {
721             expr = quote_spanned!(span=> ::cxx::core::result::Result::Ok(#expr));
722         }
723     };
724     let dispatch = quote_spanned!(span=> unsafe { #setup #expr });
725     let visibility = efn.visibility;
726     let unsafety = &efn.sig.unsafety;
727     let fn_token = efn.sig.fn_token;
728     let ident = &efn.name.rust;
729     let generics = &efn.generics;
730     let arg_list = quote_spanned!(efn.sig.paren_token.span=> (#(#all_args,)*));
731     let fn_body = quote_spanned!(span=> {
732         extern "C" {
733             #decl
734         }
735         #trampolines
736         #dispatch
737     });
738     match &efn.receiver {
739         None => {
740             quote! {
741                 #doc
742                 #attrs
743                 #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
744             }
745         }
746         Some(receiver) => {
747             let elided_generics;
748             let receiver_ident = &receiver.ty.rust;
749             let resolve = types.resolve(&receiver.ty);
750             let receiver_generics = if receiver.ty.generics.lt_token.is_some() {
751                 &receiver.ty.generics
752             } else {
753                 elided_generics = Lifetimes {
754                     lt_token: resolve.generics.lt_token,
755                     lifetimes: resolve
756                         .generics
757                         .lifetimes
758                         .pairs()
759                         .map(|pair| {
760                             let lifetime = Lifetime::new("'_", pair.value().apostrophe);
761                             let punct = pair.punct().map(|&&comma| comma);
762                             punctuated::Pair::new(lifetime, punct)
763                         })
764                         .collect(),
765                     gt_token: resolve.generics.gt_token,
766                 };
767                 &elided_generics
768             };
769             quote_spanned! {ident.span()=>
770                 impl #generics #receiver_ident #receiver_generics {
771                     #doc
772                     #attrs
773                     #visibility #unsafety #fn_token #ident #arg_list #ret #fn_body
774                 }
775             }
776         }
777     }
778 }
779 
expand_function_pointer_trampoline( efn: &ExternFn, var: &Pair, sig: &Signature, types: &Types, ) -> TokenStream780 fn expand_function_pointer_trampoline(
781     efn: &ExternFn,
782     var: &Pair,
783     sig: &Signature,
784     types: &Types,
785 ) -> TokenStream {
786     let c_trampoline = mangle::c_trampoline(efn, var, types);
787     let r_trampoline = mangle::r_trampoline(efn, var, types);
788     let local_name = parse_quote!(__);
789     let prevent_unwind_label = format!("::{}::{}", efn.name.rust, var.rust);
790     let body_span = efn.semi_token.span;
791     let shim = expand_rust_function_shim_impl(
792         sig,
793         types,
794         &r_trampoline,
795         local_name,
796         prevent_unwind_label,
797         None,
798         Some(&efn.generics),
799         &efn.attrs,
800         body_span,
801     );
802     let var = &var.rust;
803 
804     quote! {
805         let #var = ::cxx::private::FatFunction {
806             trampoline: {
807                 extern "C" {
808                     #[link_name = #c_trampoline]
809                     fn trampoline();
810                 }
811                 #shim
812                 trampoline as usize as *const ::cxx::core::ffi::c_void
813             },
814             ptr: #var as usize as *const ::cxx::core::ffi::c_void,
815         };
816     }
817 }
818 
expand_rust_type_import(ety: &ExternType) -> TokenStream819 fn expand_rust_type_import(ety: &ExternType) -> TokenStream {
820     let ident = &ety.name.rust;
821     let span = ident.span();
822 
823     quote_spanned! {span=>
824         use super::#ident;
825     }
826 }
827 
expand_rust_type_impl(ety: &ExternType) -> TokenStream828 fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
829     let ident = &ety.name.rust;
830     let generics = &ety.generics;
831     let span = ident.span();
832     let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
833 
834     let mut impls = quote_spanned! {span=>
835         #[doc(hidden)]
836         #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {}
837     };
838 
839     for derive in &ety.derives {
840         if derive.what == Trait::ExternType {
841             let type_id = type_id(&ety.name);
842             let span = derive.span;
843             impls.extend(quote_spanned! {span=>
844                 unsafe impl #generics ::cxx::ExternType for #ident #generics {
845                     #[allow(unused_attributes)] // incorrect lint
846                     #[doc(hidden)]
847                     type Id = #type_id;
848                     type Kind = ::cxx::kind::Opaque;
849                 }
850             });
851         }
852     }
853 
854     impls
855 }
856 
expand_rust_type_assert_unpin(ety: &ExternType, types: &Types) -> TokenStream857 fn expand_rust_type_assert_unpin(ety: &ExternType, types: &Types) -> TokenStream {
858     let ident = &ety.name.rust;
859     let begin_span = Token![::](ety.type_token.span);
860     let unpin = quote_spanned! {ety.semi_token.span=>
861         #begin_span cxx::core::marker::Unpin
862     };
863 
864     let resolve = types.resolve(ident);
865     let lifetimes = resolve.generics.to_underscore_lifetimes();
866 
867     quote_spanned! {ident.span()=>
868         let _ = {
869             fn __AssertUnpin<T: ?::cxx::core::marker::Sized + #unpin>() {}
870             __AssertUnpin::<#ident #lifetimes>
871         };
872     }
873 }
874 
expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStream875 fn expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStream {
876     // Rustc will render as follows if not sized:
877     //
878     //     type TheirType;
879     //     -----^^^^^^^^^-
880     //     |    |
881     //     |    doesn't have a size known at compile-time
882     //     required by this bound in `__AssertSized`
883 
884     let ident = &ety.name.rust;
885     let begin_span = Token![::](ety.type_token.span);
886     let sized = quote_spanned! {ety.semi_token.span=>
887         #begin_span cxx::core::marker::Sized
888     };
889 
890     let link_sizeof = mangle::operator(&ety.name, "sizeof");
891     let link_alignof = mangle::operator(&ety.name, "alignof");
892 
893     let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
894     let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
895 
896     let resolve = types.resolve(ident);
897     let lifetimes = resolve.generics.to_underscore_lifetimes();
898 
899     quote_spanned! {ident.span()=>
900         {
901             #[doc(hidden)]
902             fn __AssertSized<T: ?#sized + #sized>() -> ::cxx::core::alloc::Layout {
903                 ::cxx::core::alloc::Layout::new::<T>()
904             }
905             #[doc(hidden)]
906             #[export_name = #link_sizeof]
907             extern "C" fn #local_sizeof() -> usize {
908                 __AssertSized::<#ident #lifetimes>().size()
909             }
910             #[doc(hidden)]
911             #[export_name = #link_alignof]
912             extern "C" fn #local_alignof() -> usize {
913                 __AssertSized::<#ident #lifetimes>().align()
914             }
915         }
916     }
917 }
918 
expand_forbid(impls: TokenStream) -> TokenStream919 fn expand_forbid(impls: TokenStream) -> TokenStream {
920     quote! {
921         mod forbid {
922             pub trait Drop {}
923             #[allow(drop_bounds)]
924             impl<T: ?::cxx::core::marker::Sized + ::cxx::core::ops::Drop> self::Drop for T {}
925             #impls
926         }
927     }
928 }
929 
expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream930 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
931     let link_name = mangle::extern_fn(efn, types);
932     let local_name = match &efn.receiver {
933         None => format_ident!("__{}", efn.name.rust),
934         Some(receiver) => format_ident!("__{}__{}", receiver.ty.rust, efn.name.rust),
935     };
936     let prevent_unwind_label = match &efn.receiver {
937         None => format!("::{}", efn.name.rust),
938         Some(receiver) => format!("::{}::{}", receiver.ty.rust, efn.name.rust),
939     };
940     let invoke = Some(&efn.name.rust);
941     let body_span = efn.semi_token.span;
942     expand_rust_function_shim_impl(
943         efn,
944         types,
945         &link_name,
946         local_name,
947         prevent_unwind_label,
948         invoke,
949         None,
950         &efn.attrs,
951         body_span,
952     )
953 }
954 
expand_rust_function_shim_impl( sig: &Signature, types: &Types, link_name: &Symbol, local_name: Ident, prevent_unwind_label: String, invoke: Option<&Ident>, outer_generics: Option<&Generics>, attrs: &OtherAttrs, body_span: Span, ) -> TokenStream955 fn expand_rust_function_shim_impl(
956     sig: &Signature,
957     types: &Types,
958     link_name: &Symbol,
959     local_name: Ident,
960     prevent_unwind_label: String,
961     invoke: Option<&Ident>,
962     outer_generics: Option<&Generics>,
963     attrs: &OtherAttrs,
964     body_span: Span,
965 ) -> TokenStream {
966     let generics = outer_generics.unwrap_or(&sig.generics);
967     let receiver_var = sig
968         .receiver
969         .as_ref()
970         .map(|receiver| quote_spanned!(receiver.var.span=> __self));
971     let receiver = sig.receiver.as_ref().map(|receiver| {
972         let colon = receiver.colon_token;
973         let receiver_type = receiver.ty();
974         quote!(#receiver_var #colon #receiver_type)
975     });
976     let args = sig.args.iter().map(|arg| {
977         let var = &arg.name.rust;
978         let colon = arg.colon_token;
979         let ty = expand_extern_type(&arg.ty, types, false);
980         if types.needs_indirect_abi(&arg.ty) {
981             quote!(#var #colon *mut #ty)
982         } else {
983             quote!(#var #colon #ty)
984         }
985     });
986     let all_args = receiver.into_iter().chain(args);
987 
988     let mut requires_unsafe = false;
989     let arg_vars = sig.args.iter().map(|arg| {
990         let var = &arg.name.rust;
991         let span = var.span();
992         match &arg.ty {
993             Type::Ident(i) if i.rust == RustString => {
994                 requires_unsafe = true;
995                 quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_string()))
996             }
997             Type::RustBox(_) => {
998                 requires_unsafe = true;
999                 quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#var))
1000             }
1001             Type::RustVec(vec) => {
1002                 requires_unsafe = true;
1003                 if vec.inner == RustString {
1004                     quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec_string()))
1005                 } else {
1006                     quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec()))
1007                 }
1008             }
1009             Type::UniquePtr(_) => {
1010                 requires_unsafe = true;
1011                 quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#var))
1012             }
1013             Type::Ref(ty) => match &ty.inner {
1014                 Type::Ident(i) if i.rust == RustString => match ty.mutable {
1015                     false => quote_spanned!(span=> #var.as_string()),
1016                     true => quote_spanned!(span=> #var.as_mut_string()),
1017                 },
1018                 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
1019                     false => quote_spanned!(span=> #var.as_vec_string()),
1020                     true => quote_spanned!(span=> #var.as_mut_vec_string()),
1021                 },
1022                 Type::RustVec(_) => match ty.mutable {
1023                     false => quote_spanned!(span=> #var.as_vec()),
1024                     true => quote_spanned!(span=> #var.as_mut_vec()),
1025                 },
1026                 _ => quote!(#var),
1027             },
1028             Type::Str(_) => {
1029                 requires_unsafe = true;
1030                 quote_spanned!(span=> #var.as_str())
1031             }
1032             Type::SliceRef(slice) => {
1033                 requires_unsafe = true;
1034                 let inner = &slice.inner;
1035                 match slice.mutable {
1036                     false => quote_spanned!(span=> #var.as_slice::<#inner>()),
1037                     true => quote_spanned!(span=> #var.as_mut_slice::<#inner>()),
1038                 }
1039             }
1040             ty if types.needs_indirect_abi(ty) => {
1041                 requires_unsafe = true;
1042                 quote_spanned!(span=> ::cxx::core::ptr::read(#var))
1043             }
1044             _ => quote!(#var),
1045         }
1046     });
1047     let vars: Vec<_> = receiver_var.into_iter().chain(arg_vars).collect();
1048 
1049     let wrap_super = invoke.map(|invoke| expand_rust_function_shim_super(sig, &local_name, invoke));
1050 
1051     let mut requires_closure;
1052     let mut call = match invoke {
1053         Some(_) => {
1054             requires_closure = false;
1055             quote!(#local_name)
1056         }
1057         None => {
1058             requires_closure = true;
1059             requires_unsafe = true;
1060             quote!(::cxx::core::mem::transmute::<*const (), #sig>(__extern))
1061         }
1062     };
1063     requires_closure |= !vars.is_empty();
1064     call.extend(quote! { (#(#vars),*) });
1065 
1066     let span = body_span;
1067     let conversion = sig.ret.as_ref().and_then(|ret| match ret {
1068         Type::Ident(ident) if ident.rust == RustString => {
1069             Some(quote_spanned!(span=> ::cxx::private::RustString::from))
1070         }
1071         Type::RustBox(_) => Some(quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw)),
1072         Type::RustVec(vec) => {
1073             if vec.inner == RustString {
1074                 Some(quote_spanned!(span=> ::cxx::private::RustVec::from_vec_string))
1075             } else {
1076                 Some(quote_spanned!(span=> ::cxx::private::RustVec::from))
1077             }
1078         }
1079         Type::UniquePtr(_) => Some(quote_spanned!(span=> ::cxx::UniquePtr::into_raw)),
1080         Type::Ref(ty) => match &ty.inner {
1081             Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
1082                 false => Some(quote_spanned!(span=> ::cxx::private::RustString::from_ref)),
1083                 true => Some(quote_spanned!(span=> ::cxx::private::RustString::from_mut)),
1084             },
1085             Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
1086                 false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string)),
1087                 true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string)),
1088             },
1089             Type::RustVec(_) => match ty.mutable {
1090                 false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref)),
1091                 true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut)),
1092             },
1093             _ => None,
1094         },
1095         Type::Str(_) => Some(quote_spanned!(span=> ::cxx::private::RustStr::from)),
1096         Type::SliceRef(ty) => match ty.mutable {
1097             false => Some(quote_spanned!(span=> ::cxx::private::RustSlice::from_ref)),
1098             true => Some(quote_spanned!(span=> ::cxx::private::RustSlice::from_mut)),
1099         },
1100         _ => None,
1101     });
1102 
1103     let mut expr = match conversion {
1104         None => call,
1105         Some(conversion) if !sig.throws => {
1106             requires_closure = true;
1107             quote_spanned!(span=> #conversion(#call))
1108         }
1109         Some(conversion) => {
1110             requires_closure = true;
1111             quote_spanned!(span=> ::cxx::core::result::Result::map(#call, #conversion))
1112         }
1113     };
1114 
1115     let mut outparam = None;
1116     let indirect_return = indirect_return(sig, types);
1117     if indirect_return {
1118         let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types, false);
1119         outparam = Some(quote_spanned!(span=> __return: *mut #ret,));
1120     }
1121     if sig.throws {
1122         let out = match sig.ret {
1123             Some(_) => quote_spanned!(span=> __return),
1124             None => quote_spanned!(span=> &mut ()),
1125         };
1126         requires_closure = true;
1127         requires_unsafe = true;
1128         expr = quote_spanned!(span=> ::cxx::private::r#try(#out, #expr));
1129     } else if indirect_return {
1130         requires_closure = true;
1131         requires_unsafe = true;
1132         expr = quote_spanned!(span=> ::cxx::core::ptr::write(__return, #expr));
1133     }
1134 
1135     if requires_unsafe {
1136         expr = quote_spanned!(span=> unsafe { #expr });
1137     }
1138 
1139     let closure = if requires_closure {
1140         quote_spanned!(span=> move || #expr)
1141     } else {
1142         quote!(#local_name)
1143     };
1144 
1145     expr = quote_spanned!(span=> ::cxx::private::prevent_unwind(__fn, #closure));
1146 
1147     let ret = if sig.throws {
1148         quote!(-> ::cxx::private::Result)
1149     } else {
1150         expand_extern_return_type(&sig.ret, types, false)
1151     };
1152 
1153     let pointer = match invoke {
1154         None => Some(quote_spanned!(span=> __extern: *const ())),
1155         Some(_) => None,
1156     };
1157 
1158     quote_spanned! {span=>
1159         #attrs
1160         #[doc(hidden)]
1161         #[export_name = #link_name]
1162         unsafe extern "C" fn #local_name #generics(#(#all_args,)* #outparam #pointer) #ret {
1163             let __fn = ::cxx::private::concat!(::cxx::private::module_path!(), #prevent_unwind_label);
1164             #wrap_super
1165             #expr
1166         }
1167     }
1168 }
1169 
1170 // A wrapper like `fn f(x: Arg) { super::f(x) }` just to ensure we have the
1171 // accurate unsafety declaration and no problematic elided lifetimes.
expand_rust_function_shim_super( sig: &Signature, local_name: &Ident, invoke: &Ident, ) -> TokenStream1172 fn expand_rust_function_shim_super(
1173     sig: &Signature,
1174     local_name: &Ident,
1175     invoke: &Ident,
1176 ) -> TokenStream {
1177     let unsafety = sig.unsafety;
1178     let generics = &sig.generics;
1179 
1180     let receiver_var = sig
1181         .receiver
1182         .as_ref()
1183         .map(|receiver| Ident::new("__self", receiver.var.span));
1184     let receiver = sig.receiver.iter().map(|receiver| {
1185         let receiver_type = receiver.ty();
1186         quote!(#receiver_var: #receiver_type)
1187     });
1188     let args = sig.args.iter().map(|arg| quote!(#arg));
1189     let all_args = receiver.chain(args);
1190 
1191     let ret = if let Some((result, _langle, rangle)) = sig.throws_tokens {
1192         let ok = match &sig.ret {
1193             Some(ret) => quote!(#ret),
1194             None => quote!(()),
1195         };
1196         // Set spans that result in the `Result<...>` written by the user being
1197         // highlighted as the cause if their error type has no Display impl.
1198         let result_begin = quote_spanned!(result.span=> ::cxx::core::result::Result<#ok, impl);
1199         let result_end = quote_spanned!(rangle.span=> ::cxx::core::fmt::Display>);
1200         quote!(-> #result_begin #result_end)
1201     } else {
1202         expand_return_type(&sig.ret)
1203     };
1204 
1205     let arg_vars = sig.args.iter().map(|arg| &arg.name.rust);
1206     let vars = receiver_var.iter().chain(arg_vars);
1207 
1208     let span = invoke.span();
1209     let call = match &sig.receiver {
1210         None => quote_spanned!(span=> super::#invoke),
1211         Some(receiver) => {
1212             let receiver_type = &receiver.ty.rust;
1213             quote_spanned!(span=> #receiver_type::#invoke)
1214         }
1215     };
1216 
1217     let mut body = quote_spanned!(span=> #call(#(#vars,)*));
1218     if unsafety.is_some() {
1219         body = quote_spanned!(span=> unsafe { #body });
1220     }
1221 
1222     quote_spanned! {span=>
1223         #unsafety fn #local_name #generics(#(#all_args,)*) #ret {
1224             #body
1225         }
1226     }
1227 }
1228 
expand_type_alias(alias: &TypeAlias) -> TokenStream1229 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
1230     let doc = &alias.doc;
1231     let attrs = &alias.attrs;
1232     let visibility = alias.visibility;
1233     let type_token = alias.type_token;
1234     let ident = &alias.name.rust;
1235     let generics = &alias.generics;
1236     let eq_token = alias.eq_token;
1237     let ty = &alias.ty;
1238     let semi_token = alias.semi_token;
1239 
1240     quote! {
1241         #doc
1242         #attrs
1243         #visibility #type_token #ident #generics #eq_token #ty #semi_token
1244     }
1245 }
1246 
expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream1247 fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
1248     let ident = &alias.name.rust;
1249     let type_id = type_id(&alias.name);
1250     let begin_span = alias.type_token.span;
1251     let end_span = alias.semi_token.span;
1252     let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_type::<);
1253     let end = quote_spanned!(end_span=> >);
1254 
1255     let mut verify = quote! {
1256         const _: fn() = #begin #ident, #type_id #end;
1257     };
1258 
1259     if types.required_trivial.contains_key(&alias.name.rust) {
1260         let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
1261         verify.extend(quote! {
1262             const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
1263         });
1264     }
1265 
1266     verify
1267 }
1268 
type_id(name: &Pair) -> TokenStream1269 fn type_id(name: &Pair) -> TokenStream {
1270     let namespace_segments = name.namespace.iter();
1271     let mut segments = Vec::with_capacity(namespace_segments.len() + 1);
1272     segments.extend(namespace_segments.cloned());
1273     segments.push(Ident::new(&name.cxx.to_string(), Span::call_site()));
1274     let qualified = QualifiedName { segments };
1275     crate::type_id::expand(Crate::Cxx, qualified)
1276 }
1277 
expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream1278 fn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
1279     let ident = key.rust;
1280     let resolve = types.resolve(ident);
1281     let link_prefix = format!("cxxbridge1$box${}$", resolve.name.to_symbol());
1282     let link_alloc = format!("{}alloc", link_prefix);
1283     let link_dealloc = format!("{}dealloc", link_prefix);
1284     let link_drop = format!("{}drop", link_prefix);
1285 
1286     let local_prefix = format_ident!("{}__box_", ident);
1287     let local_alloc = format_ident!("{}alloc", local_prefix);
1288     let local_dealloc = format_ident!("{}dealloc", local_prefix);
1289     let local_drop = format_ident!("{}drop", local_prefix);
1290 
1291     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1292 
1293     let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1294     let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1295     let unsafe_token = format_ident!("unsafe", span = begin_span);
1296     let prevent_unwind_drop_label = format!("::{} as Drop>::drop", ident);
1297 
1298     quote_spanned! {end_span=>
1299         #[doc(hidden)]
1300         #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {}
1301         #[doc(hidden)]
1302         #[export_name = #link_alloc]
1303         unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics> {
1304             // No prevent_unwind: the global allocator is not allowed to panic.
1305             //
1306             // TODO: replace with Box::new_uninit when stable.
1307             // https://doc.rust-lang.org/std/boxed/struct.Box.html#method.new_uninit
1308             // https://github.com/rust-lang/rust/issues/63291
1309             ::cxx::alloc::boxed::Box::into_raw(::cxx::alloc::boxed::Box::new(::cxx::core::mem::MaybeUninit::uninit()))
1310         }
1311         #[doc(hidden)]
1312         #[export_name = #link_dealloc]
1313         unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics>) {
1314             // No prevent_unwind: the global allocator is not allowed to panic.
1315             let _ = unsafe { ::cxx::alloc::boxed::Box::from_raw(ptr) };
1316         }
1317         #[doc(hidden)]
1318         #[export_name = #link_drop]
1319         unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::alloc::boxed::Box<#ident #ty_generics>) {
1320             let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1321             ::cxx::private::prevent_unwind(__fn, || unsafe { ::cxx::core::ptr::drop_in_place(this) });
1322         }
1323     }
1324 }
1325 
expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream1326 fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
1327     let elem = key.rust;
1328     let resolve = types.resolve(elem);
1329     let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.name.to_symbol());
1330     let link_new = format!("{}new", link_prefix);
1331     let link_drop = format!("{}drop", link_prefix);
1332     let link_len = format!("{}len", link_prefix);
1333     let link_capacity = format!("{}capacity", link_prefix);
1334     let link_data = format!("{}data", link_prefix);
1335     let link_reserve_total = format!("{}reserve_total", link_prefix);
1336     let link_set_len = format!("{}set_len", link_prefix);
1337     let link_truncate = format!("{}truncate", link_prefix);
1338 
1339     let local_prefix = format_ident!("{}__vec_", elem);
1340     let local_new = format_ident!("{}new", local_prefix);
1341     let local_drop = format_ident!("{}drop", local_prefix);
1342     let local_len = format_ident!("{}len", local_prefix);
1343     let local_capacity = format_ident!("{}capacity", local_prefix);
1344     let local_data = format_ident!("{}data", local_prefix);
1345     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
1346     let local_set_len = format_ident!("{}set_len", local_prefix);
1347     let local_truncate = format_ident!("{}truncate", local_prefix);
1348 
1349     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1350 
1351     let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1352     let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1353     let unsafe_token = format_ident!("unsafe", span = begin_span);
1354     let prevent_unwind_drop_label = format!("::{} as Drop>::drop", elem);
1355 
1356     quote_spanned! {end_span=>
1357         #[doc(hidden)]
1358         #unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {}
1359         #[doc(hidden)]
1360         #[export_name = #link_new]
1361         unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
1362             // No prevent_unwind: cannot panic.
1363             unsafe {
1364                 ::cxx::core::ptr::write(this, ::cxx::private::RustVec::new());
1365             }
1366         }
1367         #[doc(hidden)]
1368         #[export_name = #link_drop]
1369         unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
1370             let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1371             ::cxx::private::prevent_unwind(
1372                 __fn,
1373                 || unsafe { ::cxx::core::ptr::drop_in_place(this) },
1374             );
1375         }
1376         #[doc(hidden)]
1377         #[export_name = #link_len]
1378         unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
1379             // No prevent_unwind: cannot panic.
1380             unsafe { (*this).len() }
1381         }
1382         #[doc(hidden)]
1383         #[export_name = #link_capacity]
1384         unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
1385             // No prevent_unwind: cannot panic.
1386             unsafe { (*this).capacity() }
1387         }
1388         #[doc(hidden)]
1389         #[export_name = #link_data]
1390         unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics {
1391             // No prevent_unwind: cannot panic.
1392             unsafe { (*this).as_ptr() }
1393         }
1394         #[doc(hidden)]
1395         #[export_name = #link_reserve_total]
1396         unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, new_cap: usize) {
1397             // No prevent_unwind: the global allocator is not allowed to panic.
1398             unsafe {
1399                 (*this).reserve_total(new_cap);
1400             }
1401         }
1402         #[doc(hidden)]
1403         #[export_name = #link_set_len]
1404         unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
1405             // No prevent_unwind: cannot panic.
1406             unsafe {
1407                 (*this).set_len(len);
1408             }
1409         }
1410         #[doc(hidden)]
1411         #[export_name = #link_truncate]
1412         unsafe extern "C" fn #local_truncate #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
1413             let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1414             ::cxx::private::prevent_unwind(
1415                 __fn,
1416                 || unsafe { (*this).truncate(len) },
1417             );
1418         }
1419     }
1420 }
1421 
expand_unique_ptr( key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>, ) -> TokenStream1422 fn expand_unique_ptr(
1423     key: NamedImplKey,
1424     types: &Types,
1425     explicit_impl: Option<&Impl>,
1426 ) -> TokenStream {
1427     let ident = key.rust;
1428     let name = ident.to_string();
1429     let resolve = types.resolve(ident);
1430     let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.name.to_symbol());
1431     let link_null = format!("{}null", prefix);
1432     let link_uninit = format!("{}uninit", prefix);
1433     let link_raw = format!("{}raw", prefix);
1434     let link_get = format!("{}get", prefix);
1435     let link_release = format!("{}release", prefix);
1436     let link_drop = format!("{}drop", prefix);
1437 
1438     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1439 
1440     let can_construct_from_value = types.is_maybe_trivial(ident);
1441     let new_method = if can_construct_from_value {
1442         Some(quote! {
1443             fn __new(value: Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1444                 extern "C" {
1445                     #[link_name = #link_uninit]
1446                     fn __uninit(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void;
1447                 }
1448                 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1449                 unsafe {
1450                     __uninit(&mut repr).cast::<#ident #ty_generics>().write(value);
1451                 }
1452                 repr
1453             }
1454         })
1455     } else {
1456         None
1457     };
1458 
1459     let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1460     let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1461     let unsafe_token = format_ident!("unsafe", span = begin_span);
1462 
1463     quote_spanned! {end_span=>
1464         #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
1465             fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1466                 f.write_str(#name)
1467             }
1468             fn __null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1469                 extern "C" {
1470                     #[link_name = #link_null]
1471                     fn __null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1472                 }
1473                 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1474                 unsafe {
1475                     __null(&mut repr);
1476                 }
1477                 repr
1478             }
1479             #new_method
1480             unsafe fn __raw(raw: *mut Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1481                 extern "C" {
1482                     #[link_name = #link_raw]
1483                     fn __raw(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::core::ffi::c_void);
1484                 }
1485                 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1486                 unsafe {
1487                     __raw(&mut repr, raw.cast());
1488                 }
1489                 repr
1490             }
1491             unsafe fn __get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const Self {
1492                 extern "C" {
1493                     #[link_name = #link_get]
1494                     fn __get(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::core::ffi::c_void;
1495                 }
1496                 unsafe { __get(&repr).cast() }
1497             }
1498             unsafe fn __release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut Self {
1499                 extern "C" {
1500                     #[link_name = #link_release]
1501                     fn __release(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void;
1502                 }
1503                 unsafe { __release(&mut repr).cast() }
1504             }
1505             unsafe fn __drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) {
1506                 extern "C" {
1507                     #[link_name = #link_drop]
1508                     fn __drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1509                 }
1510                 unsafe {
1511                     __drop(&mut repr);
1512                 }
1513             }
1514         }
1515     }
1516 }
1517 
expand_shared_ptr( key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>, ) -> TokenStream1518 fn expand_shared_ptr(
1519     key: NamedImplKey,
1520     types: &Types,
1521     explicit_impl: Option<&Impl>,
1522 ) -> TokenStream {
1523     let ident = key.rust;
1524     let name = ident.to_string();
1525     let resolve = types.resolve(ident);
1526     let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol());
1527     let link_null = format!("{}null", prefix);
1528     let link_uninit = format!("{}uninit", prefix);
1529     let link_clone = format!("{}clone", prefix);
1530     let link_get = format!("{}get", prefix);
1531     let link_drop = format!("{}drop", prefix);
1532 
1533     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1534 
1535     let can_construct_from_value = types.is_maybe_trivial(ident);
1536     let new_method = if can_construct_from_value {
1537         Some(quote! {
1538             unsafe fn __new(value: Self, new: *mut ::cxx::core::ffi::c_void) {
1539                 extern "C" {
1540                     #[link_name = #link_uninit]
1541                     fn __uninit(new: *mut ::cxx::core::ffi::c_void) -> *mut ::cxx::core::ffi::c_void;
1542                 }
1543                 unsafe {
1544                     __uninit(new).cast::<#ident #ty_generics>().write(value);
1545                 }
1546             }
1547         })
1548     } else {
1549         None
1550     };
1551 
1552     let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1553     let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1554     let unsafe_token = format_ident!("unsafe", span = begin_span);
1555 
1556     quote_spanned! {end_span=>
1557         #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
1558             fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1559                 f.write_str(#name)
1560             }
1561             unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) {
1562                 extern "C" {
1563                     #[link_name = #link_null]
1564                     fn __null(new: *mut ::cxx::core::ffi::c_void);
1565                 }
1566                 unsafe {
1567                     __null(new);
1568                 }
1569             }
1570             #new_method
1571             unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
1572                 extern "C" {
1573                     #[link_name = #link_clone]
1574                     fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void);
1575                 }
1576                 unsafe {
1577                     __clone(this, new);
1578                 }
1579             }
1580             unsafe fn __get(this: *const ::cxx::core::ffi::c_void) -> *const Self {
1581                 extern "C" {
1582                     #[link_name = #link_get]
1583                     fn __get(this: *const ::cxx::core::ffi::c_void) -> *const ::cxx::core::ffi::c_void;
1584                 }
1585                 unsafe { __get(this).cast() }
1586             }
1587             unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) {
1588                 extern "C" {
1589                     #[link_name = #link_drop]
1590                     fn __drop(this: *mut ::cxx::core::ffi::c_void);
1591                 }
1592                 unsafe {
1593                     __drop(this);
1594                 }
1595             }
1596         }
1597     }
1598 }
1599 
expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream1600 fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
1601     let ident = key.rust;
1602     let name = ident.to_string();
1603     let resolve = types.resolve(ident);
1604     let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.name.to_symbol());
1605     let link_null = format!("{}null", prefix);
1606     let link_clone = format!("{}clone", prefix);
1607     let link_downgrade = format!("{}downgrade", prefix);
1608     let link_upgrade = format!("{}upgrade", prefix);
1609     let link_drop = format!("{}drop", prefix);
1610 
1611     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1612 
1613     let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1614     let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1615     let unsafe_token = format_ident!("unsafe", span = begin_span);
1616 
1617     quote_spanned! {end_span=>
1618         #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
1619             fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1620                 f.write_str(#name)
1621             }
1622             unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) {
1623                 extern "C" {
1624                     #[link_name = #link_null]
1625                     fn __null(new: *mut ::cxx::core::ffi::c_void);
1626                 }
1627                 unsafe {
1628                     __null(new);
1629                 }
1630             }
1631             unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
1632                 extern "C" {
1633                     #[link_name = #link_clone]
1634                     fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void);
1635                 }
1636                 unsafe {
1637                     __clone(this, new);
1638                 }
1639             }
1640             unsafe fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void) {
1641                 extern "C" {
1642                     #[link_name = #link_downgrade]
1643                     fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void);
1644                 }
1645                 unsafe {
1646                     __downgrade(shared, weak);
1647                 }
1648             }
1649             unsafe fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void) {
1650                 extern "C" {
1651                     #[link_name = #link_upgrade]
1652                     fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void);
1653                 }
1654                 unsafe {
1655                     __upgrade(weak, shared);
1656                 }
1657             }
1658             unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) {
1659                 extern "C" {
1660                     #[link_name = #link_drop]
1661                     fn __drop(this: *mut ::cxx::core::ffi::c_void);
1662                 }
1663                 unsafe {
1664                     __drop(this);
1665                 }
1666             }
1667         }
1668     }
1669 }
1670 
expand_cxx_vector( key: NamedImplKey, explicit_impl: Option<&Impl>, types: &Types, ) -> TokenStream1671 fn expand_cxx_vector(
1672     key: NamedImplKey,
1673     explicit_impl: Option<&Impl>,
1674     types: &Types,
1675 ) -> TokenStream {
1676     let elem = key.rust;
1677     let name = elem.to_string();
1678     let resolve = types.resolve(elem);
1679     let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
1680     let link_new = format!("{}new", prefix);
1681     let link_size = format!("{}size", prefix);
1682     let link_get_unchecked = format!("{}get_unchecked", prefix);
1683     let link_push_back = format!("{}push_back", prefix);
1684     let link_pop_back = format!("{}pop_back", prefix);
1685     let unique_ptr_prefix = format!(
1686         "cxxbridge1$unique_ptr$std$vector${}$",
1687         resolve.name.to_symbol(),
1688     );
1689     let link_unique_ptr_null = format!("{}null", unique_ptr_prefix);
1690     let link_unique_ptr_raw = format!("{}raw", unique_ptr_prefix);
1691     let link_unique_ptr_get = format!("{}get", unique_ptr_prefix);
1692     let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
1693     let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
1694 
1695     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1696 
1697     let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1698     let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1699     let unsafe_token = format_ident!("unsafe", span = begin_span);
1700 
1701     let can_pass_element_by_value = types.is_maybe_trivial(elem);
1702     let by_value_methods = if can_pass_element_by_value {
1703         Some(quote_spanned! {end_span=>
1704             unsafe fn __push_back(
1705                 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
1706                 value: &mut ::cxx::core::mem::ManuallyDrop<Self>,
1707             ) {
1708                 extern "C" {
1709                     #[link_name = #link_push_back]
1710                     fn __push_back #impl_generics(
1711                         this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
1712                         value: *mut ::cxx::core::ffi::c_void,
1713                     );
1714                 }
1715                 unsafe {
1716                     __push_back(
1717                         this,
1718                         value as *mut ::cxx::core::mem::ManuallyDrop<Self> as *mut ::cxx::core::ffi::c_void,
1719                     );
1720                 }
1721             }
1722             unsafe fn __pop_back(
1723                 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
1724                 out: &mut ::cxx::core::mem::MaybeUninit<Self>,
1725             ) {
1726                 extern "C" {
1727                     #[link_name = #link_pop_back]
1728                     fn __pop_back #impl_generics(
1729                         this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
1730                         out: *mut ::cxx::core::ffi::c_void,
1731                     );
1732                 }
1733                 unsafe {
1734                     __pop_back(
1735                         this,
1736                         out as *mut ::cxx::core::mem::MaybeUninit<Self> as *mut ::cxx::core::ffi::c_void,
1737                     );
1738                 }
1739             }
1740         })
1741     } else {
1742         None
1743     };
1744 
1745     quote_spanned! {end_span=>
1746         #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
1747             fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1748                 f.write_str(#name)
1749             }
1750             fn __vector_new() -> *mut ::cxx::CxxVector<Self> {
1751                 extern "C" {
1752                     #[link_name = #link_new]
1753                     fn __vector_new #impl_generics() -> *mut ::cxx::CxxVector<#elem #ty_generics>;
1754                 }
1755                 unsafe { __vector_new() }
1756             }
1757             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
1758                 extern "C" {
1759                     #[link_name = #link_size]
1760                     fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
1761                 }
1762                 unsafe { __vector_size(v) }
1763             }
1764             unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
1765                 extern "C" {
1766                     #[link_name = #link_get_unchecked]
1767                     fn __get_unchecked #impl_generics(
1768                         v: *mut ::cxx::CxxVector<#elem #ty_generics>,
1769                         pos: usize,
1770                     ) -> *mut ::cxx::core::ffi::c_void;
1771                 }
1772                 unsafe { __get_unchecked(v, pos) as *mut Self }
1773             }
1774             #by_value_methods
1775             fn __unique_ptr_null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1776                 extern "C" {
1777                     #[link_name = #link_unique_ptr_null]
1778                     fn __unique_ptr_null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1779                 }
1780                 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1781                 unsafe {
1782                     __unique_ptr_null(&mut repr);
1783                 }
1784                 repr
1785             }
1786             unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1787                 extern "C" {
1788                     #[link_name = #link_unique_ptr_raw]
1789                     fn __unique_ptr_raw #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::CxxVector<#elem #ty_generics>);
1790                 }
1791                 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1792                 unsafe {
1793                     __unique_ptr_raw(&mut repr, raw);
1794                 }
1795                 repr
1796             }
1797             unsafe fn __unique_ptr_get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<Self> {
1798                 extern "C" {
1799                     #[link_name = #link_unique_ptr_get]
1800                     fn __unique_ptr_get #impl_generics(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<#elem #ty_generics>;
1801                 }
1802                 unsafe { __unique_ptr_get(&repr) }
1803             }
1804             unsafe fn __unique_ptr_release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<Self> {
1805                 extern "C" {
1806                     #[link_name = #link_unique_ptr_release]
1807                     fn __unique_ptr_release #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
1808                 }
1809                 unsafe { __unique_ptr_release(&mut repr) }
1810             }
1811             unsafe fn __unique_ptr_drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) {
1812                 extern "C" {
1813                     #[link_name = #link_unique_ptr_drop]
1814                     fn __unique_ptr_drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1815                 }
1816                 unsafe {
1817                     __unique_ptr_drop(&mut repr);
1818                 }
1819             }
1820         }
1821     }
1822 }
1823 
expand_return_type(ret: &Option<Type>) -> TokenStream1824 fn expand_return_type(ret: &Option<Type>) -> TokenStream {
1825     match ret {
1826         Some(ret) => quote!(-> #ret),
1827         None => TokenStream::new(),
1828     }
1829 }
1830 
indirect_return(sig: &Signature, types: &Types) -> bool1831 fn indirect_return(sig: &Signature, types: &Types) -> bool {
1832     sig.ret
1833         .as_ref()
1834         .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
1835 }
1836 
expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream1837 fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
1838     match ty {
1839         Type::Ident(ident) if ident.rust == RustString => {
1840             let span = ident.rust.span();
1841             quote_spanned!(span=> ::cxx::private::RustString)
1842         }
1843         Type::RustBox(ty) | Type::UniquePtr(ty) => {
1844             let span = ty.name.span();
1845             if proper && types.is_considered_improper_ctype(&ty.inner) {
1846                 quote_spanned!(span=> *mut ::cxx::core::ffi::c_void)
1847             } else {
1848                 let inner = expand_extern_type(&ty.inner, types, proper);
1849                 quote_spanned!(span=> *mut #inner)
1850             }
1851         }
1852         Type::RustVec(ty) => {
1853             let span = ty.name.span();
1854             let langle = ty.langle;
1855             let elem = expand_extern_type(&ty.inner, types, proper);
1856             let rangle = ty.rangle;
1857             quote_spanned!(span=> ::cxx::private::RustVec #langle #elem #rangle)
1858         }
1859         Type::Ref(ty) => {
1860             let ampersand = ty.ampersand;
1861             let lifetime = &ty.lifetime;
1862             let mutability = ty.mutability;
1863             match &ty.inner {
1864                 Type::Ident(ident) if ident.rust == RustString => {
1865                     let span = ident.rust.span();
1866                     quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustString)
1867                 }
1868                 Type::RustVec(ty) => {
1869                     let span = ty.name.span();
1870                     let langle = ty.langle;
1871                     let inner = expand_extern_type(&ty.inner, types, proper);
1872                     let rangle = ty.rangle;
1873                     quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustVec #langle #inner #rangle)
1874                 }
1875                 inner if proper && types.is_considered_improper_ctype(inner) => {
1876                     let star = Token![*](ampersand.span);
1877                     match ty.mutable {
1878                         false => quote!(#star const ::cxx::core::ffi::c_void),
1879                         true => quote!(#star #mutability ::cxx::core::ffi::c_void),
1880                     }
1881                 }
1882                 _ => quote!(#ty),
1883             }
1884         }
1885         Type::Ptr(ty) => {
1886             if proper && types.is_considered_improper_ctype(&ty.inner) {
1887                 let star = ty.star;
1888                 let mutability = ty.mutability;
1889                 let constness = ty.constness;
1890                 quote!(#star #mutability #constness ::cxx::core::ffi::c_void)
1891             } else {
1892                 quote!(#ty)
1893             }
1894         }
1895         Type::Str(ty) => {
1896             let span = ty.ampersand.span;
1897             let rust_str = Ident::new("RustStr", syn::spanned::Spanned::span(&ty.inner));
1898             quote_spanned!(span=> ::cxx::private::#rust_str)
1899         }
1900         Type::SliceRef(ty) => {
1901             let span = ty.ampersand.span;
1902             let rust_slice = Ident::new("RustSlice", ty.bracket.span.join());
1903             quote_spanned!(span=> ::cxx::private::#rust_slice)
1904         }
1905         _ => quote!(#ty),
1906     }
1907 }
1908 
expand_extern_return_type(ret: &Option<Type>, types: &Types, proper: bool) -> TokenStream1909 fn expand_extern_return_type(ret: &Option<Type>, types: &Types, proper: bool) -> TokenStream {
1910     let ret = match ret {
1911         Some(ret) if !types.needs_indirect_abi(ret) => ret,
1912         _ => return TokenStream::new(),
1913     };
1914     let ty = expand_extern_type(ret, types, proper);
1915     quote!(-> #ty)
1916 }
1917