1use crate::syntax::atom::Atom::*;
2use crate::syntax::attrs::{self, OtherAttrs};
3use crate::syntax::cfg::{CfgExpr, ComputedCfg};
4use crate::syntax::file::Module;
5use crate::syntax::instantiate::{ImplKey, NamedImplKey};
6use crate::syntax::message::Message;
7use crate::syntax::namespace::Namespace;
8use crate::syntax::qualified::QualifiedName;
9use crate::syntax::report::Errors;
10use crate::syntax::symbol::Symbol;
11use crate::syntax::trivial::TrivialReason;
12use crate::syntax::types::ConditionalImpl;
13use crate::syntax::unpin::UnpinReason;
14use crate::syntax::{
15 self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, FnKind, Lang, Lifetimes, Pair,
16 Signature, Struct, Trait, Type, TypeAlias, Types,
17};
18use crate::type_id::Crate;
19use crate::{derive, generics};
20use proc_macro2::{Ident, Span, TokenStream};
21use quote::{format_ident, quote, quote_spanned, ToTokens};
22use std::fmt::{self, Display};
23use std::mem;
24use syn::{parse_quote, punctuated, Generics, Lifetime, Result, Token, Visibility};
25
26pub(crate) fn bridge(mut ffi: Module) -> Result<TokenStream> {
27 let ref mut errors = Errors::new();
28
29 let mut cfg = CfgExpr::Unconditional;
30 let mut doc = Doc::new();
31 let attrs = attrs::parse(
32 errors,
33 mem::take(&mut ffi.attrs),
34 attrs::Parser {
35 cfg: Some(&mut cfg),
36 doc: Some(&mut doc),
37 ..Default::default()
38 },
39 );
40
41 let content = mem::take(&mut ffi.content);
42 let trusted = ffi.unsafety.is_some();
43 let namespace = &ffi.namespace;
44 let ref mut apis = syntax::parse_items(errors, content, trusted, namespace);
45 let ref types = Types::collect(errors, apis);
46 errors.propagate()?;
47
48 let generator = check::Generator::Macro;
49 check::typecheck(errors, apis, types, generator);
50 errors.propagate()?;
51
52 Ok(expand(ffi, doc, attrs, apis, types))
53}
54
55fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream {
56 let mut expanded = TokenStream::new();
57 let mut hidden = TokenStream::new();
58 let mut forbid = TokenStream::new();
59
60 for api in apis {
61 if let Api::RustType(ety) = api {
62 expanded.extend(expand_rust_type_import(ety));
63 hidden.extend(expand_rust_type_assert_unpin(ety, types));
64 }
65 }
66
67 for api in apis {
68 match api {
69 Api::Include(_) | Api::Impl(_) => {}
70 Api::Struct(strct) => {
71 expanded.extend(expand_struct(strct));
72 hidden.extend(expand_struct_nonempty(strct));
73 hidden.extend(expand_struct_operators(strct));
74 forbid.extend(expand_struct_forbid_drop(strct));
75 }
76 Api::Enum(enm) => expanded.extend(expand_enum(enm)),
77 Api::CxxType(ety) => {
78 let ident = &ety.name.rust;
79 if types.structs.contains_key(ident) {
80 hidden.extend(expand_extern_shared_struct(ety, &ffi));
81 } else if !types.enums.contains_key(ident) {
82 expanded.extend(expand_cxx_type(ety));
83 hidden.extend(expand_cxx_type_assert_pinned(ety, types));
84 }
85 }
86 Api::CxxFunction(efn) => {
87 expanded.extend(expand_cxx_function_shim(efn, types));
88 }
89 Api::RustType(ety) => {
90 expanded.extend(expand_rust_type_impl(ety));
91 hidden.extend(expand_rust_type_layout(ety, types));
92 }
93 Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
94 Api::TypeAlias(alias) => {
95 expanded.extend(expand_type_alias(alias));
96 hidden.extend(expand_type_alias_verify(alias, types));
97 }
98 }
99 }
100
101 for (impl_key, conditional_impl) in &types.impls {
102 match impl_key {
103 ImplKey::RustBox(ident) => {
104 hidden.extend(expand_rust_box(ident, types, conditional_impl));
105 }
106 ImplKey::RustVec(ident) => {
107 hidden.extend(expand_rust_vec(ident, types, conditional_impl));
108 }
109 ImplKey::UniquePtr(ident) => {
110 expanded.extend(expand_unique_ptr(ident, types, conditional_impl));
111 }
112 ImplKey::SharedPtr(ident) => {
113 expanded.extend(expand_shared_ptr(ident, types, conditional_impl));
114 }
115 ImplKey::WeakPtr(ident) => {
116 expanded.extend(expand_weak_ptr(ident, types, conditional_impl));
117 }
118 ImplKey::CxxVector(ident) => {
119 expanded.extend(expand_cxx_vector(ident, conditional_impl, types));
120 }
121 }
122 }
123
124 if !forbid.is_empty() {
125 hidden.extend(expand_forbid(forbid));
126 }
127
128 if !hidden.is_empty() {
130 expanded.extend(quote! {
131 #[doc(hidden)]
132 const _: () = {
133 #hidden
134 };
135 });
136 }
137
138 let vis = &ffi.vis;
139 let mod_token = &ffi.mod_token;
140 let ident = &ffi.ident;
141 let span = ffi.brace_token.span;
142 let expanded = quote_spanned!(span=> {#expanded});
143
144 quote! {
145 #doc
146 #attrs
147 #[deny(improper_ctypes, improper_ctypes_definitions)]
148 #[allow(clippy::unknown_lints)]
149 #[allow(
150 non_camel_case_types,
151 non_snake_case,
152 clippy::extra_unused_type_parameters,
153 clippy::items_after_statements,
154 clippy::no_effect_underscore_binding,
155 clippy::ptr_as_ptr,
156 clippy::ref_as_ptr,
157 clippy::upper_case_acronyms,
158 clippy::use_self,
159 )]
160 #vis #mod_token #ident #expanded
161 }
162}
163
164fn expand_struct(strct: &Struct) -> TokenStream {
165 let ident = &strct.name.rust;
166 let doc = &strct.doc;
167 let attrs = &strct.attrs;
168 let generics = &strct.generics;
169 let type_id = type_id(&strct.name);
170 let fields = strct.fields.iter().map(|field| {
171 let doc = &field.doc;
172 let attrs = &field.attrs;
173 let vis = field.visibility;
176 quote!(#doc #attrs #vis #field)
177 });
178 let mut derives = None;
179 let derived_traits = derive::expand_struct(strct, &mut derives);
180
181 let span = ident.span();
182 let visibility = strct.visibility;
183 let struct_token = strct.struct_token;
184 let struct_def = quote_spanned! {span=>
185 #visibility #struct_token #ident #generics {
186 #(#fields,)*
187 }
188 };
189
190 let align = strct.align.as_ref().map(|align| quote!(, align(#align)));
191
192 quote! {
193 #doc
194 #derives
195 #attrs
196 #[repr(C #align)]
197 #struct_def
198
199 #attrs
200 #[automatically_derived]
201 unsafe impl #generics ::cxx::ExternType for #ident #generics {
202 #[allow(unused_attributes)] #[doc(hidden)]
204 type Id = #type_id;
205 type Kind = ::cxx::kind::Trivial;
206 }
207
208 #derived_traits
209 }
210}
211
212fn expand_struct_nonempty(strct: &Struct) -> TokenStream {
213 let has_unconditional_field = strct
214 .fields
215 .iter()
216 .any(|field| matches!(field.cfg, CfgExpr::Unconditional));
217 if has_unconditional_field {
218 return TokenStream::new();
219 }
220
221 let mut fields = strct.fields.iter();
222 let mut cfg = ComputedCfg::from(&fields.next().unwrap().cfg);
223 fields.for_each(|field| cfg.merge_or(&field.cfg));
224
225 if let ComputedCfg::Leaf(CfgExpr::Unconditional) = cfg {
226 TokenStream::new()
228 } else {
229 let meta = cfg.as_meta();
230 let msg = "structs without any fields are not supported";
231 let error = syn::Error::new_spanned(strct, msg).into_compile_error();
232 quote! {
233 #[cfg(not(#meta))]
234 #error
235 }
236 }
237}
238
239fn expand_struct_operators(strct: &Struct) -> TokenStream {
240 let ident = &strct.name.rust;
241 let generics = &strct.generics;
242 let attrs = &strct.attrs;
243 let mut operators = TokenStream::new();
244
245 for derive in &strct.derives {
246 let span = derive.span;
247 match derive.what {
248 Trait::PartialEq => {
249 let link_name = mangle::operator(&strct.name, "eq");
250 let local_name = format_ident!("__operator_eq_{}", strct.name.rust);
251 let prevent_unwind_label = format!("::{} as PartialEq>::eq", strct.name.rust);
252 operators.extend(quote_spanned! {span=>
253 #attrs
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::Eq) {
263 let link_name = mangle::operator(&strct.name, "ne");
264 let local_name = format_ident!("__operator_ne_{}", strct.name.rust);
265 let prevent_unwind_label = format!("::{} as PartialEq>::ne", strct.name.rust);
266 operators.extend(quote_spanned! {span=>
267 #attrs
268 #[doc(hidden)]
269 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
270 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
271 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
272 ::cxx::private::prevent_unwind(__fn, || *lhs != *rhs)
273 }
274 });
275 }
276 }
277 Trait::PartialOrd => {
278 let link_name = mangle::operator(&strct.name, "lt");
279 let local_name = format_ident!("__operator_lt_{}", strct.name.rust);
280 let prevent_unwind_label = format!("::{} as PartialOrd>::lt", strct.name.rust);
281 operators.extend(quote_spanned! {span=>
282 #attrs
283 #[doc(hidden)]
284 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
285 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
286 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
287 ::cxx::private::prevent_unwind(__fn, || *lhs < *rhs)
288 }
289 });
290
291 let link_name = mangle::operator(&strct.name, "le");
292 let local_name = format_ident!("__operator_le_{}", strct.name.rust);
293 let prevent_unwind_label = format!("::{} as PartialOrd>::le", strct.name.rust);
294 operators.extend(quote_spanned! {span=>
295 #attrs
296 #[doc(hidden)]
297 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
298 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
299 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
300 ::cxx::private::prevent_unwind(__fn, || *lhs <= *rhs)
301 }
302 });
303
304 if !derive::contains(&strct.derives, Trait::Ord) {
305 let link_name = mangle::operator(&strct.name, "gt");
306 let local_name = format_ident!("__operator_gt_{}", strct.name.rust);
307 let prevent_unwind_label = format!("::{} as PartialOrd>::gt", strct.name.rust);
308 operators.extend(quote_spanned! {span=>
309 #attrs
310 #[doc(hidden)]
311 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
312 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
313 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
314 ::cxx::private::prevent_unwind(__fn, || *lhs > *rhs)
315 }
316 });
317
318 let link_name = mangle::operator(&strct.name, "ge");
319 let local_name = format_ident!("__operator_ge_{}", strct.name.rust);
320 let prevent_unwind_label = format!("::{} as PartialOrd>::ge", strct.name.rust);
321 operators.extend(quote_spanned! {span=>
322 #attrs
323 #[doc(hidden)]
324 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
325 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
326 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
327 ::cxx::private::prevent_unwind(__fn, || *lhs >= *rhs)
328 }
329 });
330 }
331 }
332 Trait::Hash => {
333 let link_name = mangle::operator(&strct.name, "hash");
334 let local_name = format_ident!("__operator_hash_{}", strct.name.rust);
335 let prevent_unwind_label = format!("::{} as Hash>::hash", strct.name.rust);
336 operators.extend(quote_spanned! {span=>
337 #attrs
338 #[doc(hidden)]
339 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
340 #[allow(clippy::cast_possible_truncation)]
341 extern "C" fn #local_name #generics(this: &#ident #generics) -> usize {
342 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
343 ::cxx::private::prevent_unwind(__fn, || ::cxx::private::hash(this))
344 }
345 });
346 }
347 _ => {}
348 }
349 }
350
351 operators
352}
353
354fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
355 let ident = &strct.name.rust;
356 let generics = &strct.generics;
357 let attrs = &strct.attrs;
358 let span = ident.span();
359 let impl_token = Token;
360
361 quote_spanned! {span=>
362 #attrs
363 #[automatically_derived]
364 #impl_token #generics self::Drop for super::#ident #generics {}
365 }
366}
367
368fn expand_enum(enm: &Enum) -> TokenStream {
369 let ident = &enm.name.rust;
370 let doc = &enm.doc;
371 let attrs = &enm.attrs;
372 let repr = &enm.repr;
373 let type_id = type_id(&enm.name);
374 let variants = enm.variants.iter().map(|variant| {
375 let doc = &variant.doc;
376 let attrs = &variant.attrs;
377 let variant_ident = &variant.name.rust;
378 let discriminant = &variant.discriminant;
379 let span = variant_ident.span();
380 Some(quote_spanned! {span=>
381 #doc
382 #attrs
383 #[allow(dead_code)]
384 pub const #variant_ident: Self = #ident { repr: #discriminant };
385 })
386 });
387 let mut derives = None;
388 let derived_traits = derive::expand_enum(enm, &mut derives);
389
390 let span = ident.span();
391 let visibility = enm.visibility;
392 let struct_token = Token;
393 let enum_repr = quote! {
394 #[allow(missing_docs)]
395 pub repr: #repr,
396 };
397 let enum_def = quote_spanned! {span=>
398 #visibility #struct_token #ident {
399 #enum_repr
400 }
401 };
402
403 quote! {
404 #doc
405 #derives
406 #attrs
407 #[repr(transparent)]
408 #enum_def
409
410 #attrs
411 #[allow(non_upper_case_globals)]
412 impl #ident {
413 #(#variants)*
414 }
415
416 #attrs
417 #[automatically_derived]
418 unsafe impl ::cxx::ExternType for #ident {
419 #[allow(unused_attributes)] #[doc(hidden)]
421 type Id = #type_id;
422 type Kind = ::cxx::kind::Trivial;
423 }
424
425 #derived_traits
426 }
427}
428
429fn expand_cxx_type(ety: &ExternType) -> TokenStream {
430 let ident = &ety.name.rust;
431 let doc = &ety.doc;
432 let attrs = &ety.attrs;
433 let generics = &ety.generics;
434 let type_id = type_id(&ety.name);
435
436 let lifetime_fields = ety.generics.lifetimes.iter().map(|lifetime| {
437 let field = format_ident!("_lifetime_{}", lifetime.ident);
438 quote!(#field: ::cxx::core::marker::PhantomData<&#lifetime ()>)
439 });
440 let repr_fields = quote! {
441 _private: ::cxx::private::Opaque,
442 #(#lifetime_fields,)*
443 };
444
445 let span = ident.span();
446 let visibility = &ety.visibility;
447 let struct_token = Token;
448 let extern_type_def = quote_spanned! {span=>
449 #visibility #struct_token #ident #generics {
450 #repr_fields
451 }
452 };
453
454 quote! {
455 #doc
456 #attrs
457 #[repr(C)]
458 #extern_type_def
459
460 #attrs
461 #[automatically_derived]
462 unsafe impl #generics ::cxx::ExternType for #ident #generics {
463 #[allow(unused_attributes)] #[doc(hidden)]
465 type Id = #type_id;
466 type Kind = ::cxx::kind::Opaque;
467 }
468 }
469}
470
471fn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream {
472 let ident = &ety.name.rust;
473 let attrs = &ety.attrs;
474 let infer = Token);
475
476 let resolve = types.resolve(ident);
477 let lifetimes = resolve.generics.to_underscore_lifetimes();
478
479 quote! {
480 #attrs
481 let _: fn() = {
482 trait __AmbiguousIfImpl<A> {
484 fn infer() {}
485 }
486
487 #[automatically_derived]
488 impl<T> __AmbiguousIfImpl<()> for T
489 where
490 T: ?::cxx::core::marker::Sized
491 {}
492
493 #[allow(dead_code)]
494 struct __Invalid;
495
496 #[automatically_derived]
497 impl<T> __AmbiguousIfImpl<__Invalid> for T
498 where
499 T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin,
500 {}
501
502 <#ident #lifetimes as __AmbiguousIfImpl<#infer>>::infer
507 };
508 }
509}
510
511fn expand_extern_shared_struct(ety: &ExternType, ffi: &Module) -> TokenStream {
512 let module = &ffi.ident;
513 let name = &ety.name.rust;
514 let namespaced_name = display_namespaced(&ety.name);
515 let attrs = &ety.attrs;
516
517 let visibility = match &ffi.vis {
518 Visibility::Public(_) => "pub ".to_owned(),
519 Visibility::Restricted(vis) => {
520 format!(
521 "pub(in {}) ",
522 vis.path
523 .segments
524 .iter()
525 .map(|segment| segment.ident.to_string())
526 .collect::<Vec<_>>()
527 .join("::"),
528 )
529 }
530 Visibility::Inherited => String::new(),
531 };
532
533 let namespace_attr = if ety.name.namespace == Namespace::ROOT {
534 String::new()
535 } else {
536 format!(
537 "#[namespace = \"{}\"]\n ",
538 ety.name
539 .namespace
540 .iter()
541 .map(Ident::to_string)
542 .collect::<Vec<_>>()
543 .join("::"),
544 )
545 };
546
547 let message = format!(
548 "\
549 \nShared struct redeclared as an unsafe extern C++ type is deprecated.\
550 \nIf this is intended to be a shared struct, remove this `type {name}`.\
551 \nIf this is intended to be an extern type, change it to:\
552 \n\
553 \n use cxx::ExternType;\
554 \n \
555 \n #[repr(C)]\
556 \n {visibility}struct {name} {{\
557 \n ...\
558 \n }}\
559 \n \
560 \n unsafe impl ExternType for {name} {{\
561 \n type Id = cxx::type_id!(\"{namespaced_name}\");\
562 \n type Kind = cxx::kind::Trivial;\
563 \n }}\
564 \n \
565 \n {visibility}mod {module} {{\
566 \n {namespace_attr}extern \"C++\" {{\
567 \n type {name} = crate::{name};\
568 \n }}\
569 \n ...\
570 \n }}",
571 );
572
573 quote! {
574 #attrs
575 #[deprecated = #message]
576 struct #name {}
577
578 #attrs
579 let _ = #name {};
580 }
581}
582
583fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
584 let generics = &efn.generics;
585 let receiver = efn.receiver().into_iter().map(|receiver| {
586 if types.is_considered_improper_ctype(&receiver.ty) {
587 if receiver.mutable {
588 quote!(_: *mut ::cxx::core::ffi::c_void)
589 } else {
590 quote!(_: *const ::cxx::core::ffi::c_void)
591 }
592 } else {
593 let receiver_type = receiver.ty();
594 quote!(_: #receiver_type)
595 }
596 });
597 let args = efn.args.iter().map(|arg| {
598 let var = &arg.name.rust;
599 let colon = arg.colon_token;
600 let ty = expand_extern_type(&arg.ty, types, true);
601 if arg.ty == RustString {
602 quote!(#var #colon *const #ty)
603 } else if let Type::RustVec(_) = arg.ty {
604 quote!(#var #colon *const #ty)
605 } else if let Type::Fn(_) = arg.ty {
606 quote!(#var #colon ::cxx::private::FatFunction)
607 } else if types.needs_indirect_abi(&arg.ty) {
608 quote!(#var #colon *mut #ty)
609 } else {
610 quote!(#var #colon #ty)
611 }
612 });
613 let all_args = receiver.chain(args);
614 let ret = if efn.throws {
615 quote!(-> ::cxx::private::Result)
616 } else {
617 expand_extern_return_type(efn, types, true, efn.lang)
618 };
619 let mut outparam = None;
620 if indirect_return(efn, types, efn.lang) {
621 let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
622 outparam = Some(quote!(__return: *mut #ret));
623 }
624 let link_name = mangle::extern_fn(efn, types);
625 let local_name = format_ident!("__{}", efn.name.rust);
626 quote! {
627 #[link_name = #link_name]
628 fn #local_name #generics(#(#all_args,)* #outparam) #ret;
629 }
630}
631
632fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
633 let doc = &efn.doc;
634 let attrs = &efn.attrs;
635 let decl = expand_cxx_function_decl(efn, types);
636 let receiver = efn.receiver().into_iter().map(|receiver| {
637 let var = receiver.var;
638 if receiver.pinned {
639 let colon = receiver.colon_token;
640 let ty = receiver.ty_self();
641 quote!(#var #colon #ty)
642 } else {
643 let ampersand = receiver.ampersand;
644 let lifetime = &receiver.lifetime;
645 let mutability = receiver.mutability;
646 quote!(#ampersand #lifetime #mutability #var)
647 }
648 });
649 let args = efn.args.iter().map(|arg| quote!(#arg));
650 let all_args = receiver.chain(args);
651 let ret = if efn.throws {
652 let ok = match &efn.ret {
653 Some(ret) => quote!(#ret),
654 None => quote!(()),
655 };
656 quote!(-> ::cxx::core::result::Result<#ok, ::cxx::Exception>)
657 } else {
658 expand_return_type(&efn.ret)
659 };
660 let indirect_return = indirect_return(efn, types, efn.lang);
661 let receiver_var = efn.receiver().into_iter().map(|receiver| {
662 if types.is_considered_improper_ctype(&receiver.ty) {
663 let var = receiver.var;
664 let ty = &receiver.ty.rust;
665 let resolve = types.resolve(ty);
666 let lifetimes = resolve.generics.to_underscore_lifetimes();
667 if receiver.pinned {
668 quote!(::cxx::core::pin::Pin::into_inner_unchecked(#var) as *mut #ty #lifetimes as *mut ::cxx::core::ffi::c_void)
669 } else if receiver.mutable {
670 quote!(#var as *mut #ty #lifetimes as *mut ::cxx::core::ffi::c_void)
671 } else {
672 quote!(#var as *const #ty #lifetimes as *const ::cxx::core::ffi::c_void)
673 }
674 } else {
675 receiver.var.to_token_stream()
676 }
677 });
678 let arg_vars = efn.args.iter().map(|arg| {
679 let var = &arg.name.rust;
680 let span = var.span();
681 match &arg.ty {
682 Type::Ident(ident) if ident.rust == RustString => {
683 quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustString)
684 }
685 Type::RustBox(ty) => {
686 if types.is_considered_improper_ctype(&ty.inner) {
687 quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var).cast())
688 } else {
689 quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var))
690 }
691 }
692 Type::UniquePtr(ty) => {
693 if types.is_considered_improper_ctype(&ty.inner) {
694 quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var).cast())
695 } else {
696 quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var))
697 }
698 }
699 Type::RustVec(_) => quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
700 Type::Ref(ty) => match &ty.inner {
701 Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
702 false => quote_spanned!(span=> ::cxx::private::RustString::from_ref(#var)),
703 true => quote_spanned!(span=> ::cxx::private::RustString::from_mut(#var)),
704 },
705 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
706 false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string(#var)),
707 true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string(#var)),
708 },
709 Type::RustVec(_) => match ty.mutable {
710 false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref(#var)),
711 true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut(#var)),
712 },
713 inner if types.is_considered_improper_ctype(inner) => {
714 let var = match ty.pinned {
715 false => quote!(#var),
716 true => quote_spanned!(span=> ::cxx::core::pin::Pin::into_inner_unchecked(#var)),
717 };
718 match ty.mutable {
719 false => {
720 quote_spanned!(span=> #var as *const #inner as *const ::cxx::core::ffi::c_void)
721 }
722 true => quote_spanned!(span=> #var as *mut #inner as *mut ::cxx::core::ffi::c_void),
723 }
724 }
725 _ => quote!(#var),
726 },
727 Type::Ptr(ty) => {
728 if types.is_considered_improper_ctype(&ty.inner) {
729 quote_spanned!(span=> #var.cast())
730 } else {
731 quote!(#var)
732 }
733 }
734 Type::Str(_) => quote_spanned!(span=> ::cxx::private::RustStr::from(#var)),
735 Type::SliceRef(ty) => match ty.mutable {
736 false => quote_spanned!(span=> ::cxx::private::RustSlice::from_ref(#var)),
737 true => quote_spanned!(span=> ::cxx::private::RustSlice::from_mut(#var)),
738 },
739 ty if types.needs_indirect_abi(ty) => quote_spanned!(span=> #var.as_mut_ptr()),
740 _ => quote!(#var),
741 }
742 });
743 let vars = receiver_var.chain(arg_vars);
744 let trampolines = efn
745 .args
746 .iter()
747 .filter_map(|arg| {
748 if let Type::Fn(f) = &arg.ty {
749 let var = &arg.name;
750 Some(expand_function_pointer_trampoline(efn, var, f, types))
751 } else {
752 None
753 }
754 })
755 .collect::<TokenStream>();
756 let mut setup = efn
757 .args
758 .iter()
759 .filter(|arg| types.needs_indirect_abi(&arg.ty))
760 .map(|arg| {
761 let var = &arg.name.rust;
762 let span = var.span();
763 quote_spanned! {span=>
766 let mut #var = ::cxx::core::mem::MaybeUninit::new(#var);
767 }
768 })
769 .collect::<TokenStream>();
770 let local_name = format_ident!("__{}", efn.name.rust);
771 let span = efn.semi_token.span;
772 let call = if indirect_return {
773 let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
774 setup.extend(quote_spanned! {span=>
775 let mut __return = ::cxx::core::mem::MaybeUninit::<#ret>::uninit();
776 });
777 setup.extend(if efn.throws {
778 quote_spanned! {span=>
779 #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
780 }
781 } else {
782 quote_spanned! {span=>
783 #local_name(#(#vars,)* __return.as_mut_ptr());
784 }
785 });
786 quote_spanned!(span=> __return.assume_init())
787 } else if efn.throws {
788 quote_spanned! {span=>
789 #local_name(#(#vars),*).exception()
790 }
791 } else {
792 quote_spanned! {span=>
793 #local_name(#(#vars),*)
794 }
795 };
796 let mut expr;
797 if let Some(ret) = &efn.ret {
798 expr = match ret {
799 Type::Ident(ident) if ident.rust == RustString => {
800 quote_spanned!(span=> #call.into_string())
801 }
802 Type::RustBox(ty) => {
803 if types.is_considered_improper_ctype(&ty.inner) {
804 quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call.cast()))
805 } else {
806 quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call))
807 }
808 }
809 Type::RustVec(vec) => {
810 if vec.inner == RustString {
811 quote_spanned!(span=> #call.into_vec_string())
812 } else {
813 quote_spanned!(span=> #call.into_vec())
814 }
815 }
816 Type::UniquePtr(ty) => {
817 if types.is_considered_improper_ctype(&ty.inner) {
818 quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call.cast()))
819 } else {
820 quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call))
821 }
822 }
823 Type::Ref(ty) => match &ty.inner {
824 Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
825 false => quote_spanned!(span=> #call.as_string()),
826 true => quote_spanned!(span=> #call.as_mut_string()),
827 },
828 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
829 false => quote_spanned!(span=> #call.as_vec_string()),
830 true => quote_spanned!(span=> #call.as_mut_vec_string()),
831 },
832 Type::RustVec(_) => match ty.mutable {
833 false => quote_spanned!(span=> #call.as_vec()),
834 true => quote_spanned!(span=> #call.as_mut_vec()),
835 },
836 inner if types.is_considered_improper_ctype(inner) => {
837 let mutability = ty.mutability;
838 let deref_mut = quote_spanned!(span=> &#mutability *#call.cast());
839 match ty.pinned {
840 false => deref_mut,
841 true => {
842 quote_spanned!(span=> ::cxx::core::pin::Pin::new_unchecked(#deref_mut))
843 }
844 }
845 }
846 _ => call,
847 },
848 Type::Ptr(ty) => {
849 if types.is_considered_improper_ctype(&ty.inner) {
850 quote_spanned!(span=> #call.cast())
851 } else {
852 call
853 }
854 }
855 Type::Str(_) => quote_spanned!(span=> #call.as_str()),
856 Type::SliceRef(slice) => {
857 let inner = &slice.inner;
858 match slice.mutable {
859 false => quote_spanned!(span=> #call.as_slice::<#inner>()),
860 true => quote_spanned!(span=> #call.as_mut_slice::<#inner>()),
861 }
862 }
863 _ => call,
864 };
865 if efn.throws {
866 expr = quote_spanned!(span=> ::cxx::core::result::Result::Ok(#expr));
867 }
868 } else if efn.throws {
869 expr = call;
870 } else {
871 expr = quote! { #call; };
872 }
873 let dispatch = quote_spanned!(span=> unsafe { #setup #expr });
874 let visibility = efn.visibility;
875 let unsafety = &efn.unsafety;
876 let fn_token = efn.fn_token;
877 let ident = &efn.name.rust;
878 let generics = &efn.generics;
879 let arg_list = quote_spanned!(efn.paren_token.span=> (#(#all_args,)*));
880 let calling_conv = match efn.lang {
881 Lang::Cxx => quote_spanned!(span=> "C"),
882 Lang::CxxUnwind => quote_spanned!(span=> "C-unwind"),
883 Lang::Rust => unreachable!(),
884 };
885 let fn_body = quote_spanned!(span=> {
886 #UnsafeExtern extern #calling_conv {
887 #decl
888 }
889 #trampolines
890 #dispatch
891 });
892 match efn.self_type() {
893 None => {
894 quote! {
895 #doc
896 #attrs
897 #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
898 }
899 }
900 Some(self_type) => {
901 let elided_generics;
902 let resolve = types.resolve(self_type);
903 let self_type_attrs = resolve.attrs;
904 let self_type_generics = match &efn.kind {
905 FnKind::Method(receiver) if receiver.ty.generics.lt_token.is_some() => {
906 &receiver.ty.generics
907 }
908 _ => {
909 elided_generics = Lifetimes {
910 lt_token: resolve.generics.lt_token,
911 lifetimes: resolve
912 .generics
913 .lifetimes
914 .pairs()
915 .map(|pair| {
916 let lifetime = Lifetime::new("'_", pair.value().apostrophe);
917 let punct = pair.punct().map(|&&comma| comma);
918 punctuated::Pair::new(lifetime, punct)
919 })
920 .collect(),
921 gt_token: resolve.generics.gt_token,
922 };
923 &elided_generics
924 }
925 };
926 quote_spanned! {ident.span()=>
927 #self_type_attrs
928 impl #generics #self_type #self_type_generics {
929 #doc
930 #attrs
931 #visibility #unsafety #fn_token #ident #arg_list #ret #fn_body
932 }
933 }
934 }
935 }
936}
937
938fn expand_function_pointer_trampoline(
939 efn: &ExternFn,
940 var: &Pair,
941 sig: &Signature,
942 types: &Types,
943) -> TokenStream {
944 let c_trampoline = mangle::c_trampoline(efn, var, types);
945 let r_trampoline = mangle::r_trampoline(efn, var, types);
946 let local_name = parse_quote!(__);
947 let prevent_unwind_label = format!("::{}::{}", efn.name.rust, var.rust);
948 let body_span = efn.semi_token.span;
949 let shim = expand_rust_function_shim_impl(
950 sig,
951 types,
952 &r_trampoline,
953 local_name,
954 prevent_unwind_label,
955 None,
956 Some(&efn.generics),
957 &efn.attrs,
958 body_span,
959 );
960 let calling_conv = match efn.lang {
961 Lang::Cxx => "C",
962 Lang::CxxUnwind => "C-unwind",
963 Lang::Rust => unreachable!(),
964 };
965 let var = &var.rust;
966
967 quote! {
968 let #var = ::cxx::private::FatFunction {
969 trampoline: {
970 #UnsafeExtern extern #calling_conv {
971 #[link_name = #c_trampoline]
972 fn trampoline();
973 }
974 #shim
975 trampoline as usize as *const ::cxx::core::ffi::c_void
976 },
977 ptr: #var as usize as *const ::cxx::core::ffi::c_void,
978 };
979 }
980}
981
982fn expand_rust_type_import(ety: &ExternType) -> TokenStream {
983 let ident = &ety.name.rust;
984 let attrs = &ety.attrs;
985 let span = ident.span();
986
987 quote_spanned! {span=>
988 #attrs
989 use super::#ident;
990 }
991}
992
993fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
994 let ident = &ety.name.rust;
995 let generics = &ety.generics;
996 let attrs = &ety.attrs;
997 let span = ident.span();
998 let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
999
1000 let mut impls = quote_spanned! {span=>
1001 #attrs
1002 #[automatically_derived]
1003 #[doc(hidden)]
1004 #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {}
1005 };
1006
1007 for derive in &ety.derives {
1008 if derive.what == Trait::ExternType {
1009 let type_id = type_id(&ety.name);
1010 let span = derive.span;
1011 impls.extend(quote_spanned! {span=>
1012 #attrs
1013 #[automatically_derived]
1014 unsafe impl #generics ::cxx::ExternType for #ident #generics {
1015 #[allow(unused_attributes)] #[doc(hidden)]
1017 type Id = #type_id;
1018 type Kind = ::cxx::kind::Opaque;
1019 }
1020 });
1021 }
1022 }
1023
1024 impls
1025}
1026
1027fn expand_rust_type_assert_unpin(ety: &ExternType, types: &Types) -> TokenStream {
1028 let ident = &ety.name.rust;
1029 let attrs = &ety.attrs;
1030
1031 let resolve = types.resolve(ident);
1032 let lifetimes = resolve.generics.to_underscore_lifetimes();
1033
1034 quote_spanned! {ident.span()=>
1035 #attrs
1036 const _: fn() = ::cxx::private::require_unpin::<#ident #lifetimes>;
1037 }
1038}
1039
1040fn expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStream {
1041 let ident = &ety.name.rust;
1050 let attrs = &ety.attrs;
1051 let begin_span = Token;
1052 let sized = quote_spanned! {ety.semi_token.span=>
1053 #begin_span cxx::core::marker::Sized
1054 };
1055
1056 let link_sizeof = mangle::operator(&ety.name, "sizeof");
1057 let link_alignof = mangle::operator(&ety.name, "alignof");
1058
1059 let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
1060 let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
1061
1062 let resolve = types.resolve(ident);
1063 let lifetimes = resolve.generics.to_underscore_lifetimes();
1064
1065 quote_spanned! {ident.span()=>
1066 #attrs
1067 {
1068 #[doc(hidden)]
1069 #[allow(clippy::needless_maybe_sized)]
1070 fn __AssertSized<T: ?#sized + #sized>() -> ::cxx::core::alloc::Layout {
1071 ::cxx::core::alloc::Layout::new::<T>()
1072 }
1073 #[doc(hidden)]
1074 #[#UnsafeAttr(#ExportNameAttr = #link_sizeof)]
1075 extern "C" fn #local_sizeof() -> usize {
1076 __AssertSized::<#ident #lifetimes>().size()
1077 }
1078 #[doc(hidden)]
1079 #[#UnsafeAttr(#ExportNameAttr = #link_alignof)]
1080 extern "C" fn #local_alignof() -> usize {
1081 __AssertSized::<#ident #lifetimes>().align()
1082 }
1083 }
1084 }
1085}
1086
1087fn expand_forbid(impls: TokenStream) -> TokenStream {
1088 quote! {
1089 mod forbid {
1090 pub trait Drop {}
1091 #[automatically_derived]
1092 #[allow(drop_bounds)]
1093 impl<T: ?::cxx::core::marker::Sized + ::cxx::core::ops::Drop> self::Drop for T {}
1094 #impls
1095 }
1096 }
1097}
1098
1099fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
1100 let link_name = mangle::extern_fn(efn, types);
1101 let local_name = match efn.self_type() {
1102 None => format_ident!("__{}", efn.name.rust),
1103 Some(self_type) => format_ident!("__{}__{}", self_type, efn.name.rust),
1104 };
1105 let prevent_unwind_label = match efn.self_type() {
1106 None => format!("::{}", efn.name.rust),
1107 Some(self_type) => format!("::{}::{}", self_type, efn.name.rust),
1108 };
1109 let invoke = Some(&efn.name.rust);
1110 let body_span = efn.semi_token.span;
1111 expand_rust_function_shim_impl(
1112 efn,
1113 types,
1114 &link_name,
1115 local_name,
1116 prevent_unwind_label,
1117 invoke,
1118 None,
1119 &efn.attrs,
1120 body_span,
1121 )
1122}
1123
1124fn expand_rust_function_shim_impl(
1125 sig: &Signature,
1126 types: &Types,
1127 link_name: &Symbol,
1128 local_name: Ident,
1129 prevent_unwind_label: String,
1130 invoke: Option<&Ident>,
1131 outer_generics: Option<&Generics>,
1132 attrs: &OtherAttrs,
1133 body_span: Span,
1134) -> TokenStream {
1135 let generics = outer_generics.unwrap_or(&sig.generics);
1136 let receiver_var = sig
1137 .receiver()
1138 .map(|receiver| quote_spanned!(receiver.var.span=> __self));
1139 let receiver = sig.receiver().map(|receiver| {
1140 let colon = receiver.colon_token;
1141 let receiver_type = receiver.ty();
1142 quote!(#receiver_var #colon #receiver_type)
1143 });
1144 let args = sig.args.iter().map(|arg| {
1145 let var = &arg.name.rust;
1146 let colon = arg.colon_token;
1147 let ty = expand_extern_type(&arg.ty, types, false);
1148 if types.needs_indirect_abi(&arg.ty) {
1149 quote!(#var #colon *mut #ty)
1150 } else {
1151 quote!(#var #colon #ty)
1152 }
1153 });
1154 let all_args = receiver.into_iter().chain(args);
1155
1156 let mut requires_unsafe = false;
1157 let arg_vars = sig.args.iter().map(|arg| {
1158 let var = &arg.name.rust;
1159 let span = var.span();
1160 match &arg.ty {
1161 Type::Ident(i) if i.rust == RustString => {
1162 requires_unsafe = true;
1163 quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_string()))
1164 }
1165 Type::RustBox(_) => {
1166 requires_unsafe = true;
1167 quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#var))
1168 }
1169 Type::RustVec(vec) => {
1170 requires_unsafe = true;
1171 if vec.inner == RustString {
1172 quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec_string()))
1173 } else {
1174 quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec()))
1175 }
1176 }
1177 Type::UniquePtr(_) => {
1178 requires_unsafe = true;
1179 quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#var))
1180 }
1181 Type::Ref(ty) => match &ty.inner {
1182 Type::Ident(i) if i.rust == RustString => match ty.mutable {
1183 false => quote_spanned!(span=> #var.as_string()),
1184 true => quote_spanned!(span=> #var.as_mut_string()),
1185 },
1186 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
1187 false => quote_spanned!(span=> #var.as_vec_string()),
1188 true => quote_spanned!(span=> #var.as_mut_vec_string()),
1189 },
1190 Type::RustVec(_) => match ty.mutable {
1191 false => quote_spanned!(span=> #var.as_vec()),
1192 true => quote_spanned!(span=> #var.as_mut_vec()),
1193 },
1194 _ => quote!(#var),
1195 },
1196 Type::Str(_) => {
1197 requires_unsafe = true;
1198 quote_spanned!(span=> #var.as_str())
1199 }
1200 Type::SliceRef(slice) => {
1201 requires_unsafe = true;
1202 let inner = &slice.inner;
1203 match slice.mutable {
1204 false => quote_spanned!(span=> #var.as_slice::<#inner>()),
1205 true => quote_spanned!(span=> #var.as_mut_slice::<#inner>()),
1206 }
1207 }
1208 ty if types.needs_indirect_abi(ty) => {
1209 requires_unsafe = true;
1210 quote_spanned!(span=> ::cxx::core::ptr::read(#var))
1211 }
1212 _ => quote!(#var),
1213 }
1214 });
1215 let vars: Vec<_> = receiver_var.into_iter().chain(arg_vars).collect();
1216
1217 let wrap_super = invoke.map(|invoke| expand_rust_function_shim_super(sig, &local_name, invoke));
1218
1219 let mut requires_closure;
1220 let mut call = match invoke {
1221 Some(_) => {
1222 requires_closure = false;
1223 quote!(#local_name)
1224 }
1225 None => {
1226 requires_closure = true;
1227 requires_unsafe = true;
1228 quote!(::cxx::core::mem::transmute::<*const (), #sig>(__extern))
1229 }
1230 };
1231 requires_closure |= !vars.is_empty();
1232 call.extend(quote! { (#(#vars),*) });
1233
1234 let span = body_span;
1235 let conversion = sig.ret.as_ref().and_then(|ret| match ret {
1236 Type::Ident(ident) if ident.rust == RustString => {
1237 Some(quote_spanned!(span=> ::cxx::private::RustString::from))
1238 }
1239 Type::RustBox(_) => Some(quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw)),
1240 Type::RustVec(vec) => {
1241 if vec.inner == RustString {
1242 Some(quote_spanned!(span=> ::cxx::private::RustVec::from_vec_string))
1243 } else {
1244 Some(quote_spanned!(span=> ::cxx::private::RustVec::from))
1245 }
1246 }
1247 Type::UniquePtr(_) => Some(quote_spanned!(span=> ::cxx::UniquePtr::into_raw)),
1248 Type::Ref(ty) => match &ty.inner {
1249 Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
1250 false => Some(quote_spanned!(span=> ::cxx::private::RustString::from_ref)),
1251 true => Some(quote_spanned!(span=> ::cxx::private::RustString::from_mut)),
1252 },
1253 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
1254 false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string)),
1255 true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string)),
1256 },
1257 Type::RustVec(_) => match ty.mutable {
1258 false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref)),
1259 true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut)),
1260 },
1261 _ => None,
1262 },
1263 Type::Str(_) => Some(quote_spanned!(span=> ::cxx::private::RustStr::from)),
1264 Type::SliceRef(ty) => match ty.mutable {
1265 false => Some(quote_spanned!(span=> ::cxx::private::RustSlice::from_ref)),
1266 true => Some(quote_spanned!(span=> ::cxx::private::RustSlice::from_mut)),
1267 },
1268 _ => None,
1269 });
1270
1271 let mut expr = match conversion {
1272 None => call,
1273 Some(conversion) if !sig.throws => {
1274 requires_closure = true;
1275 quote_spanned!(span=> #conversion(#call))
1276 }
1277 Some(conversion) => {
1278 requires_closure = true;
1279 quote_spanned!(span=> ::cxx::core::result::Result::map(#call, #conversion))
1280 }
1281 };
1282
1283 let mut outparam = None;
1284 let indirect_return = indirect_return(sig, types, Lang::Rust);
1285 if indirect_return {
1286 let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types, false);
1287 outparam = Some(quote_spanned!(span=> __return: *mut #ret,));
1288 }
1289 if sig.throws {
1290 let out = match sig.ret {
1291 Some(_) => quote_spanned!(span=> __return),
1292 None => quote_spanned!(span=> &mut ()),
1293 };
1294 requires_closure = true;
1295 requires_unsafe = true;
1296 expr = quote_spanned!(span=> ::cxx::private::r#try(#out, #expr));
1297 } else if indirect_return {
1298 requires_closure = true;
1299 requires_unsafe = true;
1300 expr = quote_spanned!(span=> ::cxx::core::ptr::write(__return, #expr));
1301 }
1302
1303 if requires_unsafe {
1304 expr = quote_spanned!(span=> unsafe { #expr });
1305 }
1306
1307 let closure = if requires_closure {
1308 quote_spanned!(span=> move || #expr)
1309 } else {
1310 quote!(#local_name)
1311 };
1312
1313 expr = quote_spanned!(span=> ::cxx::private::prevent_unwind(__fn, #closure));
1314
1315 let ret = if sig.throws {
1316 quote!(-> ::cxx::private::Result)
1317 } else {
1318 expand_extern_return_type(sig, types, false, Lang::Rust)
1319 };
1320
1321 let pointer = match invoke {
1322 None => Some(quote_spanned!(span=> __extern: *const ())),
1323 Some(_) => None,
1324 };
1325
1326 quote_spanned! {span=>
1327 #attrs
1328 #[doc(hidden)]
1329 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
1330 unsafe extern "C" fn #local_name #generics(#(#all_args,)* #outparam #pointer) #ret {
1331 let __fn = ::cxx::private::concat!(::cxx::private::module_path!(), #prevent_unwind_label);
1332 #wrap_super
1333 #expr
1334 }
1335 }
1336}
1337
1338fn expand_rust_function_shim_super(
1341 sig: &Signature,
1342 local_name: &Ident,
1343 invoke: &Ident,
1344) -> TokenStream {
1345 let unsafety = sig.unsafety;
1346 let generics = &sig.generics;
1347
1348 let receiver_var = sig
1349 .receiver()
1350 .map(|receiver| Ident::new("__self", receiver.var.span));
1351 let receiver = sig.receiver().into_iter().map(|receiver| {
1352 let receiver_type = receiver.ty();
1353 quote!(#receiver_var: #receiver_type)
1354 });
1355 let args = sig.args.iter().map(|arg| quote!(#arg));
1356 let all_args = receiver.chain(args);
1357
1358 let ret = if let Some((result, _langle, rangle)) = sig.throws_tokens {
1359 let ok = match &sig.ret {
1360 Some(ret) => quote!(#ret),
1361 None => quote!(()),
1362 };
1363 let result_begin = quote_spanned!(result.span=> ::cxx::core::result::Result<#ok, impl);
1366 let result_end = if rustversion::cfg!(since(1.82)) {
1367 quote_spanned!(rangle.span=> ::cxx::core::fmt::Display + use<>>)
1369 } else {
1370 quote_spanned!(rangle.span=> ::cxx::core::fmt::Display>)
1371 };
1372 quote!(-> #result_begin #result_end)
1373 } else {
1374 expand_return_type(&sig.ret)
1375 };
1376
1377 let arg_vars = sig.args.iter().map(|arg| &arg.name.rust);
1378 let vars = receiver_var.iter().chain(arg_vars);
1379
1380 let span = invoke.span();
1381 let call = match sig.self_type() {
1382 None => quote_spanned!(span=> super::#invoke),
1383 Some(self_type) => quote_spanned!(span=> #self_type::#invoke),
1384 };
1385
1386 let mut body = quote_spanned!(span=> #call(#(#vars,)*));
1387 let mut allow_unused_unsafe = None;
1388 if unsafety.is_some() {
1389 body = quote_spanned!(span=> unsafe { #body });
1390 allow_unused_unsafe = Some(quote_spanned!(span=> #[allow(unused_unsafe)]));
1391 }
1392
1393 quote_spanned! {span=>
1394 #allow_unused_unsafe
1395 #unsafety fn #local_name #generics(#(#all_args,)*) #ret {
1396 #body
1397 }
1398 }
1399}
1400
1401fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
1402 let doc = &alias.doc;
1403 let attrs = &alias.attrs;
1404 let visibility = alias.visibility;
1405 let type_token = alias.type_token;
1406 let ident = &alias.name.rust;
1407 let generics = &alias.generics;
1408 let eq_token = alias.eq_token;
1409 let ty = &alias.ty;
1410 let semi_token = alias.semi_token;
1411
1412 quote! {
1413 #doc
1414 #attrs
1415 #visibility #type_token #ident #generics #eq_token #ty #semi_token
1416 }
1417}
1418
1419fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
1420 let attrs = &alias.attrs;
1421 let ident = &alias.name.rust;
1422 let type_id = type_id(&alias.name);
1423 let begin_span = alias.type_token.span;
1424 let end_span = alias.semi_token.span;
1425 let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_type::<);
1426 let end = quote_spanned!(end_span=> >);
1427
1428 let resolve = types.resolve(ident);
1429 let lifetimes = resolve.generics.to_underscore_lifetimes();
1430
1431 let mut verify = quote! {
1432 #attrs
1433 const _: fn() = #begin #ident #lifetimes, #type_id #end;
1434 };
1435
1436 let mut require_unpin = false;
1437 let mut require_box = false;
1438 let mut require_vec = false;
1439 let mut require_extern_type_trivial = false;
1440 let mut require_rust_type_or_trivial = None;
1441 if let Some(reasons) = types.required_trivial.get(&alias.name.rust) {
1442 for reason in reasons {
1443 match reason {
1444 TrivialReason::BoxTarget { local: true }
1445 | TrivialReason::VecElement { local: true } => require_unpin = true,
1446 TrivialReason::BoxTarget { local: false } => require_box = true,
1447 TrivialReason::VecElement { local: false } => require_vec = true,
1448 TrivialReason::StructField(_)
1449 | TrivialReason::FunctionArgument(_)
1450 | TrivialReason::FunctionReturn(_) => require_extern_type_trivial = true,
1451 TrivialReason::SliceElement(slice) => require_rust_type_or_trivial = Some(slice),
1452 }
1453 }
1454 }
1455
1456 'unpin: {
1457 if let Some(reason) = types.required_unpin.get(ident) {
1458 let ampersand;
1459 let reference_lifetime;
1460 let mutability;
1461 let mut inner;
1462 let generics;
1463 let shorthand;
1464 match reason {
1465 UnpinReason::Receiver(receiver) => {
1466 ampersand = &receiver.ampersand;
1467 reference_lifetime = &receiver.lifetime;
1468 mutability = &receiver.mutability;
1469 inner = receiver.ty.rust.clone();
1470 generics = &receiver.ty.generics;
1471 shorthand = receiver.shorthand;
1472 if receiver.shorthand {
1473 inner.set_span(receiver.var.span);
1474 }
1475 }
1476 UnpinReason::Ref(mutable_reference) => {
1477 ampersand = &mutable_reference.ampersand;
1478 reference_lifetime = &mutable_reference.lifetime;
1479 mutability = &mutable_reference.mutability;
1480 let Type::Ident(inner_type) = &mutable_reference.inner else {
1481 unreachable!();
1482 };
1483 inner = inner_type.rust.clone();
1484 generics = &inner_type.generics;
1485 shorthand = false;
1486 }
1487 UnpinReason::Slice(mutable_slice) => {
1488 ampersand = &mutable_slice.ampersand;
1489 mutability = &mutable_slice.mutability;
1490 let inner = quote_spanned!(mutable_slice.bracket.span=> [#ident #lifetimes]);
1491 let trait_name = format_ident!("SliceOfUnpin_{ident}");
1492 let label = format!("requires `{ident}: Unpin`");
1493 verify.extend(quote! {
1494 #attrs
1495 let _ = {
1496 #[diagnostic::on_unimplemented(
1497 message = "mutable slice of pinned type is not supported",
1498 label = #label,
1499 )]
1500 trait #trait_name {
1501 fn check_unpin() {}
1502 }
1503 #[diagnostic::do_not_recommend]
1504 impl<'a, T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin> #trait_name for &'a #mutability T {}
1505 <#ampersand #mutability #inner as #trait_name>::check_unpin
1506 };
1507 });
1508 require_unpin = false;
1509 break 'unpin;
1510 }
1511 }
1512 let trait_name = format_ident!("ReferenceToUnpin_{ident}");
1513 let message =
1514 format!("mutable reference to C++ type requires a pin -- use Pin<&mut {ident}>");
1515 let label = {
1516 let mut label = Message::new();
1517 write!(label, "use `");
1518 if shorthand {
1519 write!(label, "self: ");
1520 }
1521 write!(label, "Pin<&");
1522 if let Some(reference_lifetime) = reference_lifetime {
1523 write!(label, "{reference_lifetime} ");
1524 }
1525 write!(label, "mut {ident}");
1526 if !generics.lifetimes.is_empty() {
1527 write!(label, "<");
1528 for (i, lifetime) in generics.lifetimes.iter().enumerate() {
1529 if i > 0 {
1530 write!(label, ", ");
1531 }
1532 write!(label, "{lifetime}");
1533 }
1534 write!(label, ">");
1535 } else if shorthand && !alias.generics.lifetimes.is_empty() {
1536 write!(label, "<");
1537 for i in 0..alias.generics.lifetimes.len() {
1538 if i > 0 {
1539 write!(label, ", ");
1540 }
1541 write!(label, "'_");
1542 }
1543 write!(label, ">");
1544 }
1545 write!(label, ">`");
1546 label
1547 };
1548 let lifetimes = generics.to_underscore_lifetimes();
1549 verify.extend(quote! {
1550 #attrs
1551 let _ = {
1552 #[diagnostic::on_unimplemented(message = #message, label = #label)]
1553 trait #trait_name {
1554 fn check_unpin() {}
1555 }
1556 #[diagnostic::do_not_recommend]
1557 impl<'a, T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin> #trait_name for &'a mut T {}
1558 <#ampersand #mutability #inner #lifetimes as #trait_name>::check_unpin
1559 };
1560 });
1561 require_unpin = false;
1562 }
1563 }
1564
1565 if require_unpin {
1566 verify.extend(quote! {
1567 #attrs
1568 const _: fn() = ::cxx::private::require_unpin::<#ident #lifetimes>;
1569 });
1570 }
1571
1572 if require_box {
1573 verify.extend(quote! {
1574 #attrs
1575 const _: fn() = ::cxx::private::require_box::<#ident #lifetimes>;
1576 });
1577 }
1578
1579 if require_vec {
1580 verify.extend(quote! {
1581 #attrs
1582 const _: fn() = ::cxx::private::require_vec::<#ident #lifetimes>;
1583 });
1584 }
1585
1586 if require_extern_type_trivial {
1587 let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
1588 verify.extend(quote! {
1589 #attrs
1590 const _: fn() = #begin #ident #lifetimes, ::cxx::kind::Trivial #end;
1591 });
1592 } else if let Some(slice_type) = require_rust_type_or_trivial {
1593 let ampersand = &slice_type.ampersand;
1594 let mutability = &slice_type.mutability;
1595 let inner = quote_spanned!(slice_type.bracket.span.join()=> [#ident #lifetimes]);
1596 verify.extend(quote! {
1597 #attrs
1598 let _ = || ::cxx::private::with::<#ident #lifetimes>().check_slice::<#ampersand #mutability #inner>();
1599 });
1600 }
1601
1602 verify
1603}
1604
1605fn type_id(name: &Pair) -> TokenStream {
1606 let namespace_segments = name.namespace.iter();
1607 let mut segments = Vec::with_capacity(namespace_segments.len() + 1);
1608 segments.extend(namespace_segments.cloned());
1609 segments.push(Ident::new(&name.cxx.to_string(), Span::call_site()));
1610 let qualified = QualifiedName { segments };
1611 crate::type_id::expand(Crate::Cxx, qualified)
1612}
1613
1614fn expand_rust_box(
1615 key: &NamedImplKey,
1616 types: &Types,
1617 conditional_impl: &ConditionalImpl,
1618) -> TokenStream {
1619 let ident = key.rust;
1620 let resolve = types.resolve(ident);
1621 let link_prefix = format!("cxxbridge1$box${}$", resolve.name.to_symbol());
1622 let link_alloc = format!("{}alloc", link_prefix);
1623 let link_dealloc = format!("{}dealloc", link_prefix);
1624 let link_drop = format!("{}drop", link_prefix);
1625
1626 let local_prefix = format_ident!("{}__box_", ident);
1627 let local_alloc = format_ident!("{}alloc", local_prefix);
1628 let local_dealloc = format_ident!("{}dealloc", local_prefix);
1629 let local_drop = format_ident!("{}drop", local_prefix);
1630
1631 let (impl_generics, ty_generics) = generics::split_for_impl(key, conditional_impl, resolve);
1632
1633 let cfg = conditional_impl.cfg.into_attr();
1634 let begin_span = conditional_impl
1635 .explicit_impl
1636 .map_or(key.begin_span, |explicit| explicit.impl_token.span);
1637 let end_span = conditional_impl
1638 .explicit_impl
1639 .map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1640 let unsafe_token = format_ident!("unsafe", span = begin_span);
1641 let prevent_unwind_drop_label = format!("::{} as Drop>::drop", ident);
1642
1643 quote_spanned! {end_span=>
1644 #cfg
1645 #[automatically_derived]
1646 #[doc(hidden)]
1647 #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {}
1648
1649 #cfg
1650 #[doc(hidden)]
1651 #[#UnsafeAttr(#ExportNameAttr = #link_alloc)]
1652 unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics> {
1653 ::cxx::alloc::boxed::Box::into_raw(::cxx::alloc::boxed::Box::new(::cxx::core::mem::MaybeUninit::uninit()))
1659 }
1660
1661 #cfg
1662 #[doc(hidden)]
1663 #[#UnsafeAttr(#ExportNameAttr = #link_dealloc)]
1664 unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics>) {
1665 let _ = unsafe { ::cxx::alloc::boxed::Box::from_raw(ptr) };
1667 }
1668
1669 #cfg
1670 #[doc(hidden)]
1671 #[#UnsafeAttr(#ExportNameAttr = #link_drop)]
1672 unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::alloc::boxed::Box<#ident #ty_generics>) {
1673 let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1674 ::cxx::private::prevent_unwind(__fn, || unsafe { ::cxx::core::ptr::drop_in_place(this) });
1675 }
1676 }
1677}
1678
1679fn expand_rust_vec(
1680 key: &NamedImplKey,
1681 types: &Types,
1682 conditional_impl: &ConditionalImpl,
1683) -> TokenStream {
1684 let elem = key.rust;
1685 let resolve = types.resolve(elem);
1686 let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.name.to_symbol());
1687 let link_new = format!("{}new", link_prefix);
1688 let link_drop = format!("{}drop", link_prefix);
1689 let link_len = format!("{}len", link_prefix);
1690 let link_capacity = format!("{}capacity", link_prefix);
1691 let link_data = format!("{}data", link_prefix);
1692 let link_reserve_total = format!("{}reserve_total", link_prefix);
1693 let link_set_len = format!("{}set_len", link_prefix);
1694 let link_truncate = format!("{}truncate", link_prefix);
1695
1696 let local_prefix = format_ident!("{}__vec_", elem);
1697 let local_new = format_ident!("{}new", local_prefix);
1698 let local_drop = format_ident!("{}drop", local_prefix);
1699 let local_len = format_ident!("{}len", local_prefix);
1700 let local_capacity = format_ident!("{}capacity", local_prefix);
1701 let local_data = format_ident!("{}data", local_prefix);
1702 let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
1703 let local_set_len = format_ident!("{}set_len", local_prefix);
1704 let local_truncate = format_ident!("{}truncate", local_prefix);
1705
1706 let (impl_generics, ty_generics) = generics::split_for_impl(key, conditional_impl, resolve);
1707
1708 let cfg = conditional_impl.cfg.into_attr();
1709 let begin_span = conditional_impl
1710 .explicit_impl
1711 .map_or(key.begin_span, |explicit| explicit.impl_token.span);
1712 let end_span = conditional_impl
1713 .explicit_impl
1714 .map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1715 let unsafe_token = format_ident!("unsafe", span = begin_span);
1716 let prevent_unwind_drop_label = format!("::{} as Drop>::drop", elem);
1717
1718 quote_spanned! {end_span=>
1719 #cfg
1720 #[automatically_derived]
1721 #[doc(hidden)]
1722 #unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {}
1723
1724 #cfg
1725 #[doc(hidden)]
1726 #[#UnsafeAttr(#ExportNameAttr = #link_new)]
1727 unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
1728 unsafe {
1730 ::cxx::core::ptr::write(this, ::cxx::private::RustVec::new());
1731 }
1732 }
1733
1734 #cfg
1735 #[doc(hidden)]
1736 #[#UnsafeAttr(#ExportNameAttr = #link_drop)]
1737 unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
1738 let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1739 ::cxx::private::prevent_unwind(
1740 __fn,
1741 || unsafe { ::cxx::core::ptr::drop_in_place(this) },
1742 );
1743 }
1744
1745 #cfg
1746 #[doc(hidden)]
1747 #[#UnsafeAttr(#ExportNameAttr = #link_len)]
1748 unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
1749 unsafe { (*this).len() }
1751 }
1752
1753 #cfg
1754 #[doc(hidden)]
1755 #[#UnsafeAttr(#ExportNameAttr = #link_capacity)]
1756 unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
1757 unsafe { (*this).capacity() }
1759 }
1760
1761 #cfg
1762 #[doc(hidden)]
1763 #[#UnsafeAttr(#ExportNameAttr = #link_data)]
1764 unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics {
1765 unsafe { (*this).as_ptr() }
1767 }
1768
1769 #cfg
1770 #[doc(hidden)]
1771 #[#UnsafeAttr(#ExportNameAttr = #link_reserve_total)]
1772 unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, new_cap: usize) {
1773 unsafe {
1775 (*this).reserve_total(new_cap);
1776 }
1777 }
1778
1779 #cfg
1780 #[doc(hidden)]
1781 #[#UnsafeAttr(#ExportNameAttr = #link_set_len)]
1782 unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
1783 unsafe {
1785 (*this).set_len(len);
1786 }
1787 }
1788
1789 #cfg
1790 #[doc(hidden)]
1791 #[#UnsafeAttr(#ExportNameAttr = #link_truncate)]
1792 unsafe extern "C" fn #local_truncate #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
1793 let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1794 ::cxx::private::prevent_unwind(
1795 __fn,
1796 || unsafe { (*this).truncate(len) },
1797 );
1798 }
1799 }
1800}
1801
1802fn expand_unique_ptr(
1803 key: &NamedImplKey,
1804 types: &Types,
1805 conditional_impl: &ConditionalImpl,
1806) -> TokenStream {
1807 let ident = key.rust;
1808 let name = ident.to_string();
1809 let resolve = types.resolve(ident);
1810 let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.name.to_symbol());
1811 let link_null = format!("{}null", prefix);
1812 let link_uninit = format!("{}uninit", prefix);
1813 let link_raw = format!("{}raw", prefix);
1814 let link_get = format!("{}get", prefix);
1815 let link_release = format!("{}release", prefix);
1816 let link_drop = format!("{}drop", prefix);
1817
1818 let (impl_generics, ty_generics) = generics::split_for_impl(key, conditional_impl, resolve);
1819
1820 let can_construct_from_value = types.is_maybe_trivial(ident);
1821 let new_method = if can_construct_from_value {
1822 let raw_mut = if rustversion::cfg!(since(1.82)) {
1823 quote!(&raw mut)
1824 } else {
1825 quote!(&mut)
1826 };
1827 Some(quote! {
1828 fn __new(value: Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1829 #UnsafeExtern extern "C" {
1830 #[link_name = #link_uninit]
1831 fn __uninit(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void;
1832 }
1833 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1834 unsafe {
1835 __uninit(#raw_mut repr).cast::<#ident #ty_generics>().write(value);
1836 }
1837 repr
1838 }
1839 })
1840 } else {
1841 None
1842 };
1843
1844 let cfg = conditional_impl.cfg.into_attr();
1845 let begin_span = conditional_impl
1846 .explicit_impl
1847 .map_or(key.begin_span, |explicit| explicit.impl_token.span);
1848 let end_span = conditional_impl
1849 .explicit_impl
1850 .map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1851 let unsafe_token = format_ident!("unsafe", span = begin_span);
1852 let raw_const = if rustversion::cfg!(since(1.82)) {
1853 quote_spanned!(end_span=> &raw const)
1854 } else {
1855 quote_spanned!(end_span=> &)
1856 };
1857 let raw_mut = if rustversion::cfg!(since(1.82)) {
1858 quote_spanned!(end_span=> &raw mut)
1859 } else {
1860 quote_spanned!(end_span=> &mut)
1861 };
1862
1863 quote_spanned! {end_span=>
1864 #cfg
1865 #[automatically_derived]
1866 #unsafe_token impl #impl_generics ::cxx::memory::UniquePtrTarget for #ident #ty_generics {
1867 fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1868 f.write_str(#name)
1869 }
1870 fn __null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1871 #UnsafeExtern extern "C" {
1872 #[link_name = #link_null]
1873 fn __null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1874 }
1875 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1876 unsafe {
1877 __null(#raw_mut repr);
1878 }
1879 repr
1880 }
1881 #new_method
1882 unsafe fn __raw(raw: *mut Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1883 #UnsafeExtern extern "C" {
1884 #[link_name = #link_raw]
1885 fn __raw(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::core::ffi::c_void);
1886 }
1887 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1888 unsafe {
1889 __raw(#raw_mut repr, raw.cast());
1890 }
1891 repr
1892 }
1893 unsafe fn __get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const Self {
1894 #UnsafeExtern extern "C" {
1895 #[link_name = #link_get]
1896 fn __get(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::core::ffi::c_void;
1897 }
1898 unsafe { __get(#raw_const repr).cast() }
1899 }
1900 unsafe fn __release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut Self {
1901 #UnsafeExtern extern "C" {
1902 #[link_name = #link_release]
1903 fn __release(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void;
1904 }
1905 unsafe { __release(#raw_mut repr).cast() }
1906 }
1907 unsafe fn __drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) {
1908 #UnsafeExtern extern "C" {
1909 #[link_name = #link_drop]
1910 fn __drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1911 }
1912 unsafe {
1913 __drop(#raw_mut repr);
1914 }
1915 }
1916 }
1917 }
1918}
1919
1920fn expand_shared_ptr(
1921 key: &NamedImplKey,
1922 types: &Types,
1923 conditional_impl: &ConditionalImpl,
1924) -> TokenStream {
1925 let ident = key.rust;
1926 let name = ident.to_string();
1927 let resolve = types.resolve(ident);
1928 let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol());
1929 let link_null = format!("{}null", prefix);
1930 let link_uninit = format!("{}uninit", prefix);
1931 let link_raw = format!("{}raw", prefix);
1932 let link_clone = format!("{}clone", prefix);
1933 let link_get = format!("{}get", prefix);
1934 let link_drop = format!("{}drop", prefix);
1935
1936 let (impl_generics, ty_generics) = generics::split_for_impl(key, conditional_impl, resolve);
1937
1938 let can_construct_from_value = types.is_maybe_trivial(ident);
1939 let new_method = if can_construct_from_value {
1940 Some(quote! {
1941 unsafe fn __new(value: Self, new: *mut ::cxx::core::ffi::c_void) {
1942 #UnsafeExtern extern "C" {
1943 #[link_name = #link_uninit]
1944 fn __uninit(new: *mut ::cxx::core::ffi::c_void) -> *mut ::cxx::core::ffi::c_void;
1945 }
1946 unsafe {
1947 __uninit(new).cast::<#ident #ty_generics>().write(value);
1948 }
1949 }
1950 })
1951 } else {
1952 None
1953 };
1954
1955 let cfg = conditional_impl.cfg.into_attr();
1956 let begin_span = conditional_impl
1957 .explicit_impl
1958 .map_or(key.begin_span, |explicit| explicit.impl_token.span);
1959 let end_span = conditional_impl
1960 .explicit_impl
1961 .map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1962 let unsafe_token = format_ident!("unsafe", span = begin_span);
1963 let not_destructible_err = format!("{} is not destructible", display_namespaced(resolve.name));
1964
1965 quote_spanned! {end_span=>
1966 #cfg
1967 #[automatically_derived]
1968 #unsafe_token impl #impl_generics ::cxx::memory::SharedPtrTarget for #ident #ty_generics {
1969 fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1970 f.write_str(#name)
1971 }
1972 unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) {
1973 #UnsafeExtern extern "C" {
1974 #[link_name = #link_null]
1975 fn __null(new: *mut ::cxx::core::ffi::c_void);
1976 }
1977 unsafe {
1978 __null(new);
1979 }
1980 }
1981 #new_method
1982 #[track_caller]
1983 unsafe fn __raw(new: *mut ::cxx::core::ffi::c_void, raw: *mut Self) {
1984 #UnsafeExtern extern "C" {
1985 #[link_name = #link_raw]
1986 fn __raw(new: *const ::cxx::core::ffi::c_void, raw: *mut ::cxx::core::ffi::c_void) -> ::cxx::core::primitive::bool;
1987 }
1988 if !unsafe { __raw(new, raw as *mut ::cxx::core::ffi::c_void) } {
1989 ::cxx::core::panic!(#not_destructible_err);
1990 }
1991 }
1992 unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
1993 #UnsafeExtern extern "C" {
1994 #[link_name = #link_clone]
1995 fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void);
1996 }
1997 unsafe {
1998 __clone(this, new);
1999 }
2000 }
2001 unsafe fn __get(this: *const ::cxx::core::ffi::c_void) -> *const Self {
2002 #UnsafeExtern extern "C" {
2003 #[link_name = #link_get]
2004 fn __get(this: *const ::cxx::core::ffi::c_void) -> *const ::cxx::core::ffi::c_void;
2005 }
2006 unsafe { __get(this).cast() }
2007 }
2008 unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) {
2009 #UnsafeExtern extern "C" {
2010 #[link_name = #link_drop]
2011 fn __drop(this: *mut ::cxx::core::ffi::c_void);
2012 }
2013 unsafe {
2014 __drop(this);
2015 }
2016 }
2017 }
2018 }
2019}
2020
2021fn expand_weak_ptr(
2022 key: &NamedImplKey,
2023 types: &Types,
2024 conditional_impl: &ConditionalImpl,
2025) -> TokenStream {
2026 let ident = key.rust;
2027 let name = ident.to_string();
2028 let resolve = types.resolve(ident);
2029 let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.name.to_symbol());
2030 let link_null = format!("{}null", prefix);
2031 let link_clone = format!("{}clone", prefix);
2032 let link_downgrade = format!("{}downgrade", prefix);
2033 let link_upgrade = format!("{}upgrade", prefix);
2034 let link_drop = format!("{}drop", prefix);
2035
2036 let (impl_generics, ty_generics) = generics::split_for_impl(key, conditional_impl, resolve);
2037
2038 let cfg = conditional_impl.cfg.into_attr();
2039 let begin_span = conditional_impl
2040 .explicit_impl
2041 .map_or(key.begin_span, |explicit| explicit.impl_token.span);
2042 let end_span = conditional_impl
2043 .explicit_impl
2044 .map_or(key.end_span, |explicit| explicit.brace_token.span.join());
2045 let unsafe_token = format_ident!("unsafe", span = begin_span);
2046
2047 quote_spanned! {end_span=>
2048 #cfg
2049 #[automatically_derived]
2050 #unsafe_token impl #impl_generics ::cxx::memory::WeakPtrTarget for #ident #ty_generics {
2051 fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
2052 f.write_str(#name)
2053 }
2054 unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) {
2055 #UnsafeExtern extern "C" {
2056 #[link_name = #link_null]
2057 fn __null(new: *mut ::cxx::core::ffi::c_void);
2058 }
2059 unsafe {
2060 __null(new);
2061 }
2062 }
2063 unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
2064 #UnsafeExtern extern "C" {
2065 #[link_name = #link_clone]
2066 fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void);
2067 }
2068 unsafe {
2069 __clone(this, new);
2070 }
2071 }
2072 unsafe fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void) {
2073 #UnsafeExtern extern "C" {
2074 #[link_name = #link_downgrade]
2075 fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void);
2076 }
2077 unsafe {
2078 __downgrade(shared, weak);
2079 }
2080 }
2081 unsafe fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void) {
2082 #UnsafeExtern extern "C" {
2083 #[link_name = #link_upgrade]
2084 fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void);
2085 }
2086 unsafe {
2087 __upgrade(weak, shared);
2088 }
2089 }
2090 unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) {
2091 #UnsafeExtern extern "C" {
2092 #[link_name = #link_drop]
2093 fn __drop(this: *mut ::cxx::core::ffi::c_void);
2094 }
2095 unsafe {
2096 __drop(this);
2097 }
2098 }
2099 }
2100 }
2101}
2102
2103fn expand_cxx_vector(
2104 key: &NamedImplKey,
2105 conditional_impl: &ConditionalImpl,
2106 types: &Types,
2107) -> TokenStream {
2108 let elem = key.rust;
2109 let name = elem.to_string();
2110 let resolve = types.resolve(elem);
2111 let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
2112 let link_new = format!("{}new", prefix);
2113 let link_size = format!("{}size", prefix);
2114 let link_capacity = format!("{}capacity", prefix);
2115 let link_get_unchecked = format!("{}get_unchecked", prefix);
2116 let link_reserve = format!("{}reserve", prefix);
2117 let link_push_back = format!("{}push_back", prefix);
2118 let link_pop_back = format!("{}pop_back", prefix);
2119 let unique_ptr_prefix = format!(
2120 "cxxbridge1$unique_ptr$std$vector${}$",
2121 resolve.name.to_symbol(),
2122 );
2123 let link_unique_ptr_null = format!("{}null", unique_ptr_prefix);
2124 let link_unique_ptr_raw = format!("{}raw", unique_ptr_prefix);
2125 let link_unique_ptr_get = format!("{}get", unique_ptr_prefix);
2126 let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
2127 let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
2128
2129 let (impl_generics, ty_generics) = generics::split_for_impl(key, conditional_impl, resolve);
2130
2131 let cfg = conditional_impl.cfg.into_attr();
2132 let begin_span = conditional_impl
2133 .explicit_impl
2134 .map_or(key.begin_span, |explicit| explicit.impl_token.span);
2135 let end_span = conditional_impl
2136 .explicit_impl
2137 .map_or(key.end_span, |explicit| explicit.brace_token.span.join());
2138 let unsafe_token = format_ident!("unsafe", span = begin_span);
2139
2140 let can_pass_element_by_value = types.is_maybe_trivial(elem);
2141 let by_value_methods = if can_pass_element_by_value {
2142 Some(quote_spanned! {end_span=>
2143 unsafe fn __push_back(
2144 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
2145 value: &mut ::cxx::core::mem::ManuallyDrop<Self>,
2146 ) {
2147 #UnsafeExtern extern "C" {
2148 #[link_name = #link_push_back]
2149 fn __push_back #impl_generics(
2150 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
2151 value: *mut ::cxx::core::ffi::c_void,
2152 );
2153 }
2154 unsafe {
2155 __push_back(
2156 this,
2157 value as *mut ::cxx::core::mem::ManuallyDrop<Self> as *mut ::cxx::core::ffi::c_void,
2158 );
2159 }
2160 }
2161 unsafe fn __pop_back(
2162 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
2163 out: &mut ::cxx::core::mem::MaybeUninit<Self>,
2164 ) {
2165 #UnsafeExtern extern "C" {
2166 #[link_name = #link_pop_back]
2167 fn __pop_back #impl_generics(
2168 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
2169 out: *mut ::cxx::core::ffi::c_void,
2170 );
2171 }
2172 unsafe {
2173 __pop_back(
2174 this,
2175 out as *mut ::cxx::core::mem::MaybeUninit<Self> as *mut ::cxx::core::ffi::c_void,
2176 );
2177 }
2178 }
2179 })
2180 } else {
2181 None
2182 };
2183
2184 let raw_const = if rustversion::cfg!(since(1.82)) {
2185 quote_spanned!(end_span=> &raw const)
2186 } else {
2187 quote_spanned!(end_span=> &)
2188 };
2189 let raw_mut = if rustversion::cfg!(since(1.82)) {
2190 quote_spanned!(end_span=> &raw mut)
2191 } else {
2192 quote_spanned!(end_span=> &mut)
2193 };
2194
2195 quote_spanned! {end_span=>
2196 #cfg
2197 #[automatically_derived]
2198 #unsafe_token impl #impl_generics ::cxx::vector::VectorElement for #elem #ty_generics {
2199 fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
2200 f.write_str(#name)
2201 }
2202 fn __vector_new() -> *mut ::cxx::CxxVector<Self> {
2203 #UnsafeExtern extern "C" {
2204 #[link_name = #link_new]
2205 fn __vector_new #impl_generics() -> *mut ::cxx::CxxVector<#elem #ty_generics>;
2206 }
2207 unsafe { __vector_new() }
2208 }
2209 fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
2210 #UnsafeExtern extern "C" {
2211 #[link_name = #link_size]
2212 fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
2213 }
2214 unsafe { __vector_size(v) }
2215 }
2216 fn __vector_capacity(v: &::cxx::CxxVector<Self>) -> usize {
2217 #UnsafeExtern extern "C" {
2218 #[link_name = #link_capacity]
2219 fn __vector_capacity #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
2220 }
2221 unsafe { __vector_capacity(v) }
2222 }
2223 unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
2224 #UnsafeExtern extern "C" {
2225 #[link_name = #link_get_unchecked]
2226 fn __get_unchecked #impl_generics(
2227 v: *mut ::cxx::CxxVector<#elem #ty_generics>,
2228 pos: usize,
2229 ) -> *mut ::cxx::core::ffi::c_void;
2230 }
2231 unsafe { __get_unchecked(v, pos) as *mut Self }
2232 }
2233 unsafe fn __reserve(v: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>, new_cap: usize) {
2234 #UnsafeExtern extern "C" {
2235 #[link_name = #link_reserve]
2236 fn __reserve #impl_generics(
2237 v: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
2238 new_cap: usize,
2239 );
2240 }
2241 unsafe { __reserve(v, new_cap) }
2242 }
2243 #by_value_methods
2244 fn __unique_ptr_null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
2245 #UnsafeExtern extern "C" {
2246 #[link_name = #link_unique_ptr_null]
2247 fn __unique_ptr_null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
2248 }
2249 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
2250 unsafe {
2251 __unique_ptr_null(#raw_mut repr);
2252 }
2253 repr
2254 }
2255 unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
2256 #UnsafeExtern extern "C" {
2257 #[link_name = #link_unique_ptr_raw]
2258 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>);
2259 }
2260 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
2261 unsafe {
2262 __unique_ptr_raw(#raw_mut repr, raw);
2263 }
2264 repr
2265 }
2266 unsafe fn __unique_ptr_get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<Self> {
2267 #UnsafeExtern extern "C" {
2268 #[link_name = #link_unique_ptr_get]
2269 fn __unique_ptr_get #impl_generics(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<#elem #ty_generics>;
2270 }
2271 unsafe { __unique_ptr_get(#raw_const repr) }
2272 }
2273 unsafe fn __unique_ptr_release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<Self> {
2274 #UnsafeExtern extern "C" {
2275 #[link_name = #link_unique_ptr_release]
2276 fn __unique_ptr_release #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
2277 }
2278 unsafe { __unique_ptr_release(#raw_mut repr) }
2279 }
2280 unsafe fn __unique_ptr_drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) {
2281 #UnsafeExtern extern "C" {
2282 #[link_name = #link_unique_ptr_drop]
2283 fn __unique_ptr_drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
2284 }
2285 unsafe {
2286 __unique_ptr_drop(#raw_mut repr);
2287 }
2288 }
2289 }
2290 }
2291}
2292
2293fn expand_return_type(ret: &Option<Type>) -> TokenStream {
2294 match ret {
2295 Some(ret) => quote!(-> #ret),
2296 None => TokenStream::new(),
2297 }
2298}
2299
2300fn indirect_return(sig: &Signature, types: &Types, lang: Lang) -> bool {
2301 sig.ret.as_ref().is_some_and(|ret| {
2302 sig.throws
2303 || types.needs_indirect_abi(ret)
2304 || match lang {
2305 Lang::Cxx | Lang::CxxUnwind => types.contains_elided_lifetime(ret),
2306 Lang::Rust => false,
2307 }
2308 })
2309}
2310
2311fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
2312 match ty {
2313 Type::Ident(ident) if ident.rust == RustString => {
2314 let span = ident.rust.span();
2315 quote_spanned!(span=> ::cxx::private::RustString)
2316 }
2317 Type::RustBox(ty) | Type::UniquePtr(ty) => {
2318 let span = ty.name.span();
2319 if proper && types.is_considered_improper_ctype(&ty.inner) {
2320 quote_spanned!(span=> *mut ::cxx::core::ffi::c_void)
2321 } else {
2322 let inner = expand_extern_type(&ty.inner, types, proper);
2323 quote_spanned!(span=> *mut #inner)
2324 }
2325 }
2326 Type::RustVec(ty) => {
2327 let span = ty.name.span();
2328 let langle = ty.langle;
2329 let elem = expand_extern_type(&ty.inner, types, proper);
2330 let rangle = ty.rangle;
2331 quote_spanned!(span=> ::cxx::private::RustVec #langle #elem #rangle)
2332 }
2333 Type::Ref(ty) => {
2334 let ampersand = ty.ampersand;
2335 let lifetime = &ty.lifetime;
2336 let mutability = ty.mutability;
2337 match &ty.inner {
2338 Type::Ident(ident) if ident.rust == RustString => {
2339 let span = ident.rust.span();
2340 quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustString)
2341 }
2342 Type::RustVec(ty) => {
2343 let span = ty.name.span();
2344 let langle = ty.langle;
2345 let inner = expand_extern_type(&ty.inner, types, proper);
2346 let rangle = ty.rangle;
2347 quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustVec #langle #inner #rangle)
2348 }
2349 inner if proper && types.is_considered_improper_ctype(inner) => {
2350 let star = Token;
2351 match ty.mutable {
2352 false => quote!(#star const ::cxx::core::ffi::c_void),
2353 true => quote!(#star #mutability ::cxx::core::ffi::c_void),
2354 }
2355 }
2356 _ => quote!(#ty),
2357 }
2358 }
2359 Type::Ptr(ty) => {
2360 if proper && types.is_considered_improper_ctype(&ty.inner) {
2361 let star = ty.star;
2362 let mutability = ty.mutability;
2363 let constness = ty.constness;
2364 quote!(#star #mutability #constness ::cxx::core::ffi::c_void)
2365 } else {
2366 quote!(#ty)
2367 }
2368 }
2369 Type::Str(ty) => {
2370 let span = ty.ampersand.span;
2371 let rust_str = Ident::new("RustStr", syn::spanned::Spanned::span(&ty.inner));
2372 quote_spanned!(span=> ::cxx::private::#rust_str)
2373 }
2374 Type::SliceRef(ty) => {
2375 let span = ty.ampersand.span;
2376 let rust_slice = Ident::new("RustSlice", ty.bracket.span.join());
2377 quote_spanned!(span=> ::cxx::private::#rust_slice)
2378 }
2379 _ => quote!(#ty),
2380 }
2381}
2382
2383fn expand_extern_return_type(
2384 sig: &Signature,
2385 types: &Types,
2386 proper: bool,
2387 lang: Lang,
2388) -> TokenStream {
2389 let ret = match &sig.ret {
2390 Some(ret) if !indirect_return(sig, types, lang) => ret,
2391 _ => return TokenStream::new(),
2392 };
2393 let ty = expand_extern_type(ret, types, proper);
2394 quote!(-> #ty)
2395}
2396
2397fn display_namespaced(name: &Pair) -> impl Display + '_ {
2398 struct Namespaced<'a>(&'a Pair);
2399
2400 impl<'a> Display for Namespaced<'a> {
2401 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2402 for segment in &self.0.namespace {
2403 write!(formatter, "{segment}::")?;
2404 }
2405 write!(formatter, "{}", self.0.cxx)
2406 }
2407 }
2408
2409 Namespaced(name)
2410}
2411
2412struct UnsafeExtern;
2415
2416impl ToTokens for UnsafeExtern {
2417 fn to_tokens(&self, tokens: &mut TokenStream) {
2418 if rustversion::cfg!(since(1.82)) {
2419 Token).to_tokens(tokens);
2420 }
2421 }
2422}
2423
2424struct UnsafeAttr;
2427struct ExportNameAttr;
2428
2429impl ToTokens for UnsafeAttr {
2430 fn to_tokens(&self, tokens: &mut TokenStream) {
2431 if rustversion::cfg!(since(1.82)) {
2432 Token).to_tokens(tokens);
2433 } else {
2434 Ident::new("cfg_attr", Span::call_site()).to_tokens(tokens);
2435 }
2436 }
2437}
2438
2439impl ToTokens for ExportNameAttr {
2440 fn to_tokens(&self, tokens: &mut TokenStream) {
2441 if rustversion::cfg!(since(1.82)) {
2442 Ident::new("export_name", Span::call_site()).to_tokens(tokens);
2443 } else {
2444 tokens.extend(quote!(all(), export_name));
2445 }
2446 }
2447}