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