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