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