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