133d722a9Sopenharmony_ciuse crate::syntax::atom::Atom::*;
233d722a9Sopenharmony_ciuse crate::syntax::attrs::{self, OtherAttrs};
333d722a9Sopenharmony_ciuse crate::syntax::cfg::CfgExpr;
433d722a9Sopenharmony_ciuse crate::syntax::file::Module;
533d722a9Sopenharmony_ciuse crate::syntax::instantiate::{ImplKey, NamedImplKey};
633d722a9Sopenharmony_ciuse crate::syntax::qualified::QualifiedName;
733d722a9Sopenharmony_ciuse crate::syntax::report::Errors;
833d722a9Sopenharmony_ciuse crate::syntax::symbol::Symbol;
933d722a9Sopenharmony_ciuse crate::syntax::{
1033d722a9Sopenharmony_ci    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature,
1133d722a9Sopenharmony_ci    Struct, Trait, Type, TypeAlias, Types,
1233d722a9Sopenharmony_ci};
1333d722a9Sopenharmony_ciuse crate::type_id::Crate;
1433d722a9Sopenharmony_ciuse crate::{derive, generics};
1533d722a9Sopenharmony_ciuse proc_macro2::{Ident, Span, TokenStream};
1633d722a9Sopenharmony_ciuse quote::{format_ident, quote, quote_spanned, ToTokens};
1733d722a9Sopenharmony_ciuse std::mem;
1833d722a9Sopenharmony_ciuse syn::{parse_quote, punctuated, Generics, Lifetime, Result, Token};
1933d722a9Sopenharmony_ci
2033d722a9Sopenharmony_cipub fn bridge(mut ffi: Module) -> Result<TokenStream> {
2133d722a9Sopenharmony_ci    let ref mut errors = Errors::new();
2233d722a9Sopenharmony_ci
2333d722a9Sopenharmony_ci    let mut cfg = CfgExpr::Unconditional;
2433d722a9Sopenharmony_ci    let mut doc = Doc::new();
2533d722a9Sopenharmony_ci    let attrs = attrs::parse(
2633d722a9Sopenharmony_ci        errors,
2733d722a9Sopenharmony_ci        mem::take(&mut ffi.attrs),
2833d722a9Sopenharmony_ci        attrs::Parser {
2933d722a9Sopenharmony_ci            cfg: Some(&mut cfg),
3033d722a9Sopenharmony_ci            doc: Some(&mut doc),
3133d722a9Sopenharmony_ci            ..Default::default()
3233d722a9Sopenharmony_ci        },
3333d722a9Sopenharmony_ci    );
3433d722a9Sopenharmony_ci
3533d722a9Sopenharmony_ci    let content = mem::take(&mut ffi.content);
3633d722a9Sopenharmony_ci    let trusted = ffi.unsafety.is_some();
3733d722a9Sopenharmony_ci    let namespace = &ffi.namespace;
3833d722a9Sopenharmony_ci    let ref mut apis = syntax::parse_items(errors, content, trusted, namespace);
3933d722a9Sopenharmony_ci    #[cfg(feature = "experimental-enum-variants-from-header")]
4033d722a9Sopenharmony_ci    crate::load::load(errors, apis);
4133d722a9Sopenharmony_ci    let ref types = Types::collect(errors, apis);
4233d722a9Sopenharmony_ci    errors.propagate()?;
4333d722a9Sopenharmony_ci
4433d722a9Sopenharmony_ci    let generator = check::Generator::Macro;
4533d722a9Sopenharmony_ci    check::typecheck(errors, apis, types, generator);
4633d722a9Sopenharmony_ci    errors.propagate()?;
4733d722a9Sopenharmony_ci
4833d722a9Sopenharmony_ci    Ok(expand(ffi, doc, attrs, apis, types))
4933d722a9Sopenharmony_ci}
5033d722a9Sopenharmony_ci
5133d722a9Sopenharmony_cifn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream {
5233d722a9Sopenharmony_ci    let mut expanded = TokenStream::new();
5333d722a9Sopenharmony_ci    let mut hidden = TokenStream::new();
5433d722a9Sopenharmony_ci    let mut forbid = TokenStream::new();
5533d722a9Sopenharmony_ci
5633d722a9Sopenharmony_ci    for api in apis {
5733d722a9Sopenharmony_ci        if let Api::RustType(ety) = api {
5833d722a9Sopenharmony_ci            expanded.extend(expand_rust_type_import(ety));
5933d722a9Sopenharmony_ci            hidden.extend(expand_rust_type_assert_unpin(ety, types));
6033d722a9Sopenharmony_ci        }
6133d722a9Sopenharmony_ci    }
6233d722a9Sopenharmony_ci
6333d722a9Sopenharmony_ci    for api in apis {
6433d722a9Sopenharmony_ci        match api {
6533d722a9Sopenharmony_ci            Api::Include(_) | Api::Impl(_) => {}
6633d722a9Sopenharmony_ci            Api::Struct(strct) => {
6733d722a9Sopenharmony_ci                expanded.extend(expand_struct(strct));
6833d722a9Sopenharmony_ci                hidden.extend(expand_struct_operators(strct));
6933d722a9Sopenharmony_ci                forbid.extend(expand_struct_forbid_drop(strct));
7033d722a9Sopenharmony_ci            }
7133d722a9Sopenharmony_ci            Api::Enum(enm) => expanded.extend(expand_enum(enm)),
7233d722a9Sopenharmony_ci            Api::CxxType(ety) => {
7333d722a9Sopenharmony_ci                let ident = &ety.name.rust;
7433d722a9Sopenharmony_ci                if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
7533d722a9Sopenharmony_ci                    expanded.extend(expand_cxx_type(ety));
7633d722a9Sopenharmony_ci                    hidden.extend(expand_cxx_type_assert_pinned(ety, types));
7733d722a9Sopenharmony_ci                }
7833d722a9Sopenharmony_ci            }
7933d722a9Sopenharmony_ci            Api::CxxFunction(efn) => {
8033d722a9Sopenharmony_ci                expanded.extend(expand_cxx_function_shim(efn, types));
8133d722a9Sopenharmony_ci            }
8233d722a9Sopenharmony_ci            Api::RustType(ety) => {
8333d722a9Sopenharmony_ci                expanded.extend(expand_rust_type_impl(ety));
8433d722a9Sopenharmony_ci                hidden.extend(expand_rust_type_layout(ety, types));
8533d722a9Sopenharmony_ci            }
8633d722a9Sopenharmony_ci            Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
8733d722a9Sopenharmony_ci            Api::TypeAlias(alias) => {
8833d722a9Sopenharmony_ci                expanded.extend(expand_type_alias(alias));
8933d722a9Sopenharmony_ci                hidden.extend(expand_type_alias_verify(alias, types));
9033d722a9Sopenharmony_ci            }
9133d722a9Sopenharmony_ci        }
9233d722a9Sopenharmony_ci    }
9333d722a9Sopenharmony_ci
9433d722a9Sopenharmony_ci    for (impl_key, &explicit_impl) in &types.impls {
9533d722a9Sopenharmony_ci        match *impl_key {
9633d722a9Sopenharmony_ci            ImplKey::RustBox(ident) => {
9733d722a9Sopenharmony_ci                hidden.extend(expand_rust_box(ident, types, explicit_impl));
9833d722a9Sopenharmony_ci            }
9933d722a9Sopenharmony_ci            ImplKey::RustVec(ident) => {
10033d722a9Sopenharmony_ci                hidden.extend(expand_rust_vec(ident, types, explicit_impl));
10133d722a9Sopenharmony_ci            }
10233d722a9Sopenharmony_ci            ImplKey::UniquePtr(ident) => {
10333d722a9Sopenharmony_ci                expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
10433d722a9Sopenharmony_ci            }
10533d722a9Sopenharmony_ci            ImplKey::SharedPtr(ident) => {
10633d722a9Sopenharmony_ci                expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
10733d722a9Sopenharmony_ci            }
10833d722a9Sopenharmony_ci            ImplKey::WeakPtr(ident) => {
10933d722a9Sopenharmony_ci                expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
11033d722a9Sopenharmony_ci            }
11133d722a9Sopenharmony_ci            ImplKey::CxxVector(ident) => {
11233d722a9Sopenharmony_ci                expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
11333d722a9Sopenharmony_ci            }
11433d722a9Sopenharmony_ci        }
11533d722a9Sopenharmony_ci    }
11633d722a9Sopenharmony_ci
11733d722a9Sopenharmony_ci    if !forbid.is_empty() {
11833d722a9Sopenharmony_ci        hidden.extend(expand_forbid(forbid));
11933d722a9Sopenharmony_ci    }
12033d722a9Sopenharmony_ci
12133d722a9Sopenharmony_ci    // Work around https://github.com/rust-lang/rust/issues/67851.
12233d722a9Sopenharmony_ci    if !hidden.is_empty() {
12333d722a9Sopenharmony_ci        expanded.extend(quote! {
12433d722a9Sopenharmony_ci            #[doc(hidden)]
12533d722a9Sopenharmony_ci            const _: () = {
12633d722a9Sopenharmony_ci                #hidden
12733d722a9Sopenharmony_ci            };
12833d722a9Sopenharmony_ci        });
12933d722a9Sopenharmony_ci    }
13033d722a9Sopenharmony_ci
13133d722a9Sopenharmony_ci    let vis = &ffi.vis;
13233d722a9Sopenharmony_ci    let mod_token = &ffi.mod_token;
13333d722a9Sopenharmony_ci    let ident = &ffi.ident;
13433d722a9Sopenharmony_ci    let span = ffi.brace_token.span;
13533d722a9Sopenharmony_ci    let expanded = quote_spanned!(span=> {#expanded});
13633d722a9Sopenharmony_ci
13733d722a9Sopenharmony_ci    quote! {
13833d722a9Sopenharmony_ci        #doc
13933d722a9Sopenharmony_ci        #attrs
14033d722a9Sopenharmony_ci        #[deny(improper_ctypes, improper_ctypes_definitions)]
14133d722a9Sopenharmony_ci        #[allow(clippy::unknown_clippy_lints)]
14233d722a9Sopenharmony_ci        #[allow(
14333d722a9Sopenharmony_ci            non_camel_case_types,
14433d722a9Sopenharmony_ci            non_snake_case,
14533d722a9Sopenharmony_ci            clippy::extra_unused_type_parameters,
14633d722a9Sopenharmony_ci            clippy::ptr_as_ptr,
14733d722a9Sopenharmony_ci            clippy::upper_case_acronyms,
14833d722a9Sopenharmony_ci            clippy::use_self,
14933d722a9Sopenharmony_ci        )]
15033d722a9Sopenharmony_ci        #vis #mod_token #ident #expanded
15133d722a9Sopenharmony_ci    }
15233d722a9Sopenharmony_ci}
15333d722a9Sopenharmony_ci
15433d722a9Sopenharmony_cifn expand_struct(strct: &Struct) -> TokenStream {
15533d722a9Sopenharmony_ci    let ident = &strct.name.rust;
15633d722a9Sopenharmony_ci    let doc = &strct.doc;
15733d722a9Sopenharmony_ci    let attrs = &strct.attrs;
15833d722a9Sopenharmony_ci    let generics = &strct.generics;
15933d722a9Sopenharmony_ci    let type_id = type_id(&strct.name);
16033d722a9Sopenharmony_ci    let fields = strct.fields.iter().map(|field| {
16133d722a9Sopenharmony_ci        let doc = &field.doc;
16233d722a9Sopenharmony_ci        let attrs = &field.attrs;
16333d722a9Sopenharmony_ci        // This span on the pub makes "private type in public interface" errors
16433d722a9Sopenharmony_ci        // appear in the right place.
16533d722a9Sopenharmony_ci        let vis = field.visibility;
16633d722a9Sopenharmony_ci        quote!(#doc #attrs #vis #field)
16733d722a9Sopenharmony_ci    });
16833d722a9Sopenharmony_ci    let mut derives = None;
16933d722a9Sopenharmony_ci    let derived_traits = derive::expand_struct(strct, &mut derives);
17033d722a9Sopenharmony_ci
17133d722a9Sopenharmony_ci    let span = ident.span();
17233d722a9Sopenharmony_ci    let visibility = strct.visibility;
17333d722a9Sopenharmony_ci    let struct_token = strct.struct_token;
17433d722a9Sopenharmony_ci    let struct_def = quote_spanned! {span=>
17533d722a9Sopenharmony_ci        #visibility #struct_token #ident #generics {
17633d722a9Sopenharmony_ci            #(#fields,)*
17733d722a9Sopenharmony_ci        }
17833d722a9Sopenharmony_ci    };
17933d722a9Sopenharmony_ci
18033d722a9Sopenharmony_ci    quote! {
18133d722a9Sopenharmony_ci        #doc
18233d722a9Sopenharmony_ci        #derives
18333d722a9Sopenharmony_ci        #attrs
18433d722a9Sopenharmony_ci        #[repr(C)]
18533d722a9Sopenharmony_ci        #struct_def
18633d722a9Sopenharmony_ci
18733d722a9Sopenharmony_ci        unsafe impl #generics ::cxx::ExternType for #ident #generics {
18833d722a9Sopenharmony_ci            #[allow(unused_attributes)] // incorrect lint
18933d722a9Sopenharmony_ci            #[doc(hidden)]
19033d722a9Sopenharmony_ci            type Id = #type_id;
19133d722a9Sopenharmony_ci            type Kind = ::cxx::kind::Trivial;
19233d722a9Sopenharmony_ci        }
19333d722a9Sopenharmony_ci
19433d722a9Sopenharmony_ci        #derived_traits
19533d722a9Sopenharmony_ci    }
19633d722a9Sopenharmony_ci}
19733d722a9Sopenharmony_ci
19833d722a9Sopenharmony_cifn expand_struct_operators(strct: &Struct) -> TokenStream {
19933d722a9Sopenharmony_ci    let ident = &strct.name.rust;
20033d722a9Sopenharmony_ci    let generics = &strct.generics;
20133d722a9Sopenharmony_ci    let mut operators = TokenStream::new();
20233d722a9Sopenharmony_ci
20333d722a9Sopenharmony_ci    for derive in &strct.derives {
20433d722a9Sopenharmony_ci        let span = derive.span;
20533d722a9Sopenharmony_ci        match derive.what {
20633d722a9Sopenharmony_ci            Trait::PartialEq => {
20733d722a9Sopenharmony_ci                let link_name = mangle::operator(&strct.name, "eq");
20833d722a9Sopenharmony_ci                let local_name = format_ident!("__operator_eq_{}", strct.name.rust);
20933d722a9Sopenharmony_ci                let prevent_unwind_label = format!("::{} as PartialEq>::eq", strct.name.rust);
21033d722a9Sopenharmony_ci                operators.extend(quote_spanned! {span=>
21133d722a9Sopenharmony_ci                    #[doc(hidden)]
21233d722a9Sopenharmony_ci                    #[export_name = #link_name]
21333d722a9Sopenharmony_ci                    extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
21433d722a9Sopenharmony_ci                        let __fn = concat!("<", module_path!(), #prevent_unwind_label);
21533d722a9Sopenharmony_ci                        ::cxx::private::prevent_unwind(__fn, || *lhs == *rhs)
21633d722a9Sopenharmony_ci                    }
21733d722a9Sopenharmony_ci                });
21833d722a9Sopenharmony_ci
21933d722a9Sopenharmony_ci                if !derive::contains(&strct.derives, Trait::Eq) {
22033d722a9Sopenharmony_ci                    let link_name = mangle::operator(&strct.name, "ne");
22133d722a9Sopenharmony_ci                    let local_name = format_ident!("__operator_ne_{}", strct.name.rust);
22233d722a9Sopenharmony_ci                    let prevent_unwind_label = format!("::{} as PartialEq>::ne", strct.name.rust);
22333d722a9Sopenharmony_ci                    operators.extend(quote_spanned! {span=>
22433d722a9Sopenharmony_ci                        #[doc(hidden)]
22533d722a9Sopenharmony_ci                        #[export_name = #link_name]
22633d722a9Sopenharmony_ci                        extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
22733d722a9Sopenharmony_ci                            let __fn = concat!("<", module_path!(), #prevent_unwind_label);
22833d722a9Sopenharmony_ci                            ::cxx::private::prevent_unwind(__fn, || *lhs != *rhs)
22933d722a9Sopenharmony_ci                        }
23033d722a9Sopenharmony_ci                    });
23133d722a9Sopenharmony_ci                }
23233d722a9Sopenharmony_ci            }
23333d722a9Sopenharmony_ci            Trait::PartialOrd => {
23433d722a9Sopenharmony_ci                let link_name = mangle::operator(&strct.name, "lt");
23533d722a9Sopenharmony_ci                let local_name = format_ident!("__operator_lt_{}", strct.name.rust);
23633d722a9Sopenharmony_ci                let prevent_unwind_label = format!("::{} as PartialOrd>::lt", strct.name.rust);
23733d722a9Sopenharmony_ci                operators.extend(quote_spanned! {span=>
23833d722a9Sopenharmony_ci                    #[doc(hidden)]
23933d722a9Sopenharmony_ci                    #[export_name = #link_name]
24033d722a9Sopenharmony_ci                    extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
24133d722a9Sopenharmony_ci                        let __fn = concat!("<", module_path!(), #prevent_unwind_label);
24233d722a9Sopenharmony_ci                        ::cxx::private::prevent_unwind(__fn, || *lhs < *rhs)
24333d722a9Sopenharmony_ci                    }
24433d722a9Sopenharmony_ci                });
24533d722a9Sopenharmony_ci
24633d722a9Sopenharmony_ci                let link_name = mangle::operator(&strct.name, "le");
24733d722a9Sopenharmony_ci                let local_name = format_ident!("__operator_le_{}", strct.name.rust);
24833d722a9Sopenharmony_ci                let prevent_unwind_label = format!("::{} as PartialOrd>::le", strct.name.rust);
24933d722a9Sopenharmony_ci                operators.extend(quote_spanned! {span=>
25033d722a9Sopenharmony_ci                    #[doc(hidden)]
25133d722a9Sopenharmony_ci                    #[export_name = #link_name]
25233d722a9Sopenharmony_ci                    extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
25333d722a9Sopenharmony_ci                        let __fn = concat!("<", module_path!(), #prevent_unwind_label);
25433d722a9Sopenharmony_ci                        ::cxx::private::prevent_unwind(__fn, || *lhs <= *rhs)
25533d722a9Sopenharmony_ci                    }
25633d722a9Sopenharmony_ci                });
25733d722a9Sopenharmony_ci
25833d722a9Sopenharmony_ci                if !derive::contains(&strct.derives, Trait::Ord) {
25933d722a9Sopenharmony_ci                    let link_name = mangle::operator(&strct.name, "gt");
26033d722a9Sopenharmony_ci                    let local_name = format_ident!("__operator_gt_{}", strct.name.rust);
26133d722a9Sopenharmony_ci                    let prevent_unwind_label = format!("::{} as PartialOrd>::gt", strct.name.rust);
26233d722a9Sopenharmony_ci                    operators.extend(quote_spanned! {span=>
26333d722a9Sopenharmony_ci                        #[doc(hidden)]
26433d722a9Sopenharmony_ci                        #[export_name = #link_name]
26533d722a9Sopenharmony_ci                        extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
26633d722a9Sopenharmony_ci                            let __fn = concat!("<", module_path!(), #prevent_unwind_label);
26733d722a9Sopenharmony_ci                            ::cxx::private::prevent_unwind(__fn, || *lhs > *rhs)
26833d722a9Sopenharmony_ci                        }
26933d722a9Sopenharmony_ci                    });
27033d722a9Sopenharmony_ci
27133d722a9Sopenharmony_ci                    let link_name = mangle::operator(&strct.name, "ge");
27233d722a9Sopenharmony_ci                    let local_name = format_ident!("__operator_ge_{}", strct.name.rust);
27333d722a9Sopenharmony_ci                    let prevent_unwind_label = format!("::{} as PartialOrd>::ge", strct.name.rust);
27433d722a9Sopenharmony_ci                    operators.extend(quote_spanned! {span=>
27533d722a9Sopenharmony_ci                        #[doc(hidden)]
27633d722a9Sopenharmony_ci                        #[export_name = #link_name]
27733d722a9Sopenharmony_ci                        extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
27833d722a9Sopenharmony_ci                            let __fn = concat!("<", module_path!(), #prevent_unwind_label);
27933d722a9Sopenharmony_ci                            ::cxx::private::prevent_unwind(__fn, || *lhs >= *rhs)
28033d722a9Sopenharmony_ci                        }
28133d722a9Sopenharmony_ci                    });
28233d722a9Sopenharmony_ci                }
28333d722a9Sopenharmony_ci            }
28433d722a9Sopenharmony_ci            Trait::Hash => {
28533d722a9Sopenharmony_ci                let link_name = mangle::operator(&strct.name, "hash");
28633d722a9Sopenharmony_ci                let local_name = format_ident!("__operator_hash_{}", strct.name.rust);
28733d722a9Sopenharmony_ci                let prevent_unwind_label = format!("::{} as Hash>::hash", strct.name.rust);
28833d722a9Sopenharmony_ci                operators.extend(quote_spanned! {span=>
28933d722a9Sopenharmony_ci                    #[doc(hidden)]
29033d722a9Sopenharmony_ci                    #[export_name = #link_name]
29133d722a9Sopenharmony_ci                    #[allow(clippy::cast_possible_truncation)]
29233d722a9Sopenharmony_ci                    extern "C" fn #local_name #generics(this: &#ident #generics) -> usize {
29333d722a9Sopenharmony_ci                        let __fn = concat!("<", module_path!(), #prevent_unwind_label);
29433d722a9Sopenharmony_ci                        ::cxx::private::prevent_unwind(__fn, || ::cxx::private::hash(this))
29533d722a9Sopenharmony_ci                    }
29633d722a9Sopenharmony_ci                });
29733d722a9Sopenharmony_ci            }
29833d722a9Sopenharmony_ci            _ => {}
29933d722a9Sopenharmony_ci        }
30033d722a9Sopenharmony_ci    }
30133d722a9Sopenharmony_ci
30233d722a9Sopenharmony_ci    operators
30333d722a9Sopenharmony_ci}
30433d722a9Sopenharmony_ci
30533d722a9Sopenharmony_cifn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
30633d722a9Sopenharmony_ci    let ident = &strct.name.rust;
30733d722a9Sopenharmony_ci    let generics = &strct.generics;
30833d722a9Sopenharmony_ci    let span = ident.span();
30933d722a9Sopenharmony_ci    let impl_token = Token![impl](strct.visibility.span);
31033d722a9Sopenharmony_ci
31133d722a9Sopenharmony_ci    quote_spanned! {span=>
31233d722a9Sopenharmony_ci        #impl_token #generics self::Drop for super::#ident #generics {}
31333d722a9Sopenharmony_ci    }
31433d722a9Sopenharmony_ci}
31533d722a9Sopenharmony_ci
31633d722a9Sopenharmony_cifn expand_enum(enm: &Enum) -> TokenStream {
31733d722a9Sopenharmony_ci    let ident = &enm.name.rust;
31833d722a9Sopenharmony_ci    let doc = &enm.doc;
31933d722a9Sopenharmony_ci    let attrs = &enm.attrs;
32033d722a9Sopenharmony_ci    let repr = &enm.repr;
32133d722a9Sopenharmony_ci    let type_id = type_id(&enm.name);
32233d722a9Sopenharmony_ci    let variants = enm.variants.iter().map(|variant| {
32333d722a9Sopenharmony_ci        let doc = &variant.doc;
32433d722a9Sopenharmony_ci        let attrs = &variant.attrs;
32533d722a9Sopenharmony_ci        let variant_ident = &variant.name.rust;
32633d722a9Sopenharmony_ci        let discriminant = &variant.discriminant;
32733d722a9Sopenharmony_ci        let span = variant_ident.span();
32833d722a9Sopenharmony_ci        Some(quote_spanned! {span=>
32933d722a9Sopenharmony_ci            #doc
33033d722a9Sopenharmony_ci            #attrs
33133d722a9Sopenharmony_ci            #[allow(dead_code)]
33233d722a9Sopenharmony_ci            pub const #variant_ident: Self = #ident { repr: #discriminant };
33333d722a9Sopenharmony_ci        })
33433d722a9Sopenharmony_ci    });
33533d722a9Sopenharmony_ci    let mut derives = None;
33633d722a9Sopenharmony_ci    let derived_traits = derive::expand_enum(enm, &mut derives);
33733d722a9Sopenharmony_ci
33833d722a9Sopenharmony_ci    let span = ident.span();
33933d722a9Sopenharmony_ci    let visibility = enm.visibility;
34033d722a9Sopenharmony_ci    let struct_token = Token![struct](enm.enum_token.span);
34133d722a9Sopenharmony_ci    let enum_repr = quote! {
34233d722a9Sopenharmony_ci        #[allow(missing_docs)]
34333d722a9Sopenharmony_ci        pub repr: #repr,
34433d722a9Sopenharmony_ci    };
34533d722a9Sopenharmony_ci    let enum_def = quote_spanned! {span=>
34633d722a9Sopenharmony_ci        #visibility #struct_token #ident {
34733d722a9Sopenharmony_ci            #enum_repr
34833d722a9Sopenharmony_ci        }
34933d722a9Sopenharmony_ci    };
35033d722a9Sopenharmony_ci
35133d722a9Sopenharmony_ci    quote! {
35233d722a9Sopenharmony_ci        #doc
35333d722a9Sopenharmony_ci        #derives
35433d722a9Sopenharmony_ci        #attrs
35533d722a9Sopenharmony_ci        #[repr(transparent)]
35633d722a9Sopenharmony_ci        #enum_def
35733d722a9Sopenharmony_ci
35833d722a9Sopenharmony_ci        #[allow(non_upper_case_globals)]
35933d722a9Sopenharmony_ci        impl #ident {
36033d722a9Sopenharmony_ci            #(#variants)*
36133d722a9Sopenharmony_ci        }
36233d722a9Sopenharmony_ci
36333d722a9Sopenharmony_ci        unsafe impl ::cxx::ExternType for #ident {
36433d722a9Sopenharmony_ci            #[allow(unused_attributes)] // incorrect lint
36533d722a9Sopenharmony_ci            #[doc(hidden)]
36633d722a9Sopenharmony_ci            type Id = #type_id;
36733d722a9Sopenharmony_ci            type Kind = ::cxx::kind::Trivial;
36833d722a9Sopenharmony_ci        }
36933d722a9Sopenharmony_ci
37033d722a9Sopenharmony_ci        #derived_traits
37133d722a9Sopenharmony_ci    }
37233d722a9Sopenharmony_ci}
37333d722a9Sopenharmony_ci
37433d722a9Sopenharmony_cifn expand_cxx_type(ety: &ExternType) -> TokenStream {
37533d722a9Sopenharmony_ci    let ident = &ety.name.rust;
37633d722a9Sopenharmony_ci    let doc = &ety.doc;
37733d722a9Sopenharmony_ci    let attrs = &ety.attrs;
37833d722a9Sopenharmony_ci    let generics = &ety.generics;
37933d722a9Sopenharmony_ci    let type_id = type_id(&ety.name);
38033d722a9Sopenharmony_ci
38133d722a9Sopenharmony_ci    let lifetime_fields = ety.generics.lifetimes.iter().map(|lifetime| {
38233d722a9Sopenharmony_ci        let field = format_ident!("_lifetime_{}", lifetime.ident);
38333d722a9Sopenharmony_ci        quote!(#field: ::cxx::core::marker::PhantomData<&#lifetime ()>)
38433d722a9Sopenharmony_ci    });
38533d722a9Sopenharmony_ci    let repr_fields = quote! {
38633d722a9Sopenharmony_ci        _private: ::cxx::private::Opaque,
38733d722a9Sopenharmony_ci        #(#lifetime_fields,)*
38833d722a9Sopenharmony_ci    };
38933d722a9Sopenharmony_ci
39033d722a9Sopenharmony_ci    let span = ident.span();
39133d722a9Sopenharmony_ci    let visibility = &ety.visibility;
39233d722a9Sopenharmony_ci    let struct_token = Token![struct](ety.type_token.span);
39333d722a9Sopenharmony_ci    let extern_type_def = quote_spanned! {span=>
39433d722a9Sopenharmony_ci        #visibility #struct_token #ident #generics {
39533d722a9Sopenharmony_ci            #repr_fields
39633d722a9Sopenharmony_ci        }
39733d722a9Sopenharmony_ci    };
39833d722a9Sopenharmony_ci
39933d722a9Sopenharmony_ci    quote! {
40033d722a9Sopenharmony_ci        #doc
40133d722a9Sopenharmony_ci        #attrs
40233d722a9Sopenharmony_ci        #[repr(C)]
40333d722a9Sopenharmony_ci        #extern_type_def
40433d722a9Sopenharmony_ci
40533d722a9Sopenharmony_ci        unsafe impl #generics ::cxx::ExternType for #ident #generics {
40633d722a9Sopenharmony_ci            #[allow(unused_attributes)] // incorrect lint
40733d722a9Sopenharmony_ci            #[doc(hidden)]
40833d722a9Sopenharmony_ci            type Id = #type_id;
40933d722a9Sopenharmony_ci            type Kind = ::cxx::kind::Opaque;
41033d722a9Sopenharmony_ci        }
41133d722a9Sopenharmony_ci    }
41233d722a9Sopenharmony_ci}
41333d722a9Sopenharmony_ci
41433d722a9Sopenharmony_cifn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream {
41533d722a9Sopenharmony_ci    let ident = &ety.name.rust;
41633d722a9Sopenharmony_ci    let infer = Token![_](ident.span());
41733d722a9Sopenharmony_ci
41833d722a9Sopenharmony_ci    let resolve = types.resolve(ident);
41933d722a9Sopenharmony_ci    let lifetimes = resolve.generics.to_underscore_lifetimes();
42033d722a9Sopenharmony_ci
42133d722a9Sopenharmony_ci    quote! {
42233d722a9Sopenharmony_ci        let _: fn() = {
42333d722a9Sopenharmony_ci            // Derived from https://github.com/nvzqz/static-assertions-rs.
42433d722a9Sopenharmony_ci            trait __AmbiguousIfImpl<A> {
42533d722a9Sopenharmony_ci                fn infer() {}
42633d722a9Sopenharmony_ci            }
42733d722a9Sopenharmony_ci
42833d722a9Sopenharmony_ci            impl<T> __AmbiguousIfImpl<()> for T
42933d722a9Sopenharmony_ci            where
43033d722a9Sopenharmony_ci                T: ?::cxx::core::marker::Sized
43133d722a9Sopenharmony_ci            {}
43233d722a9Sopenharmony_ci
43333d722a9Sopenharmony_ci            #[allow(dead_code)]
43433d722a9Sopenharmony_ci            struct __Invalid;
43533d722a9Sopenharmony_ci
43633d722a9Sopenharmony_ci            impl<T> __AmbiguousIfImpl<__Invalid> for T
43733d722a9Sopenharmony_ci            where
43833d722a9Sopenharmony_ci                T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin,
43933d722a9Sopenharmony_ci            {}
44033d722a9Sopenharmony_ci
44133d722a9Sopenharmony_ci            // If there is only one specialized trait impl, type inference with
44233d722a9Sopenharmony_ci            // `_` can be resolved and this can compile. Fails to compile if
44333d722a9Sopenharmony_ci            // user has added a manual Unpin impl for their opaque C++ type as
44433d722a9Sopenharmony_ci            // then `__AmbiguousIfImpl<__Invalid>` also exists.
44533d722a9Sopenharmony_ci            <#ident #lifetimes as __AmbiguousIfImpl<#infer>>::infer
44633d722a9Sopenharmony_ci        };
44733d722a9Sopenharmony_ci    }
44833d722a9Sopenharmony_ci}
44933d722a9Sopenharmony_ci
45033d722a9Sopenharmony_cifn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
45133d722a9Sopenharmony_ci    let generics = &efn.generics;
45233d722a9Sopenharmony_ci    let receiver = efn.receiver.iter().map(|receiver| {
45333d722a9Sopenharmony_ci        let receiver_type = receiver.ty();
45433d722a9Sopenharmony_ci        quote!(_: #receiver_type)
45533d722a9Sopenharmony_ci    });
45633d722a9Sopenharmony_ci    let args = efn.args.iter().map(|arg| {
45733d722a9Sopenharmony_ci        let var = &arg.name.rust;
45833d722a9Sopenharmony_ci        let colon = arg.colon_token;
45933d722a9Sopenharmony_ci        let ty = expand_extern_type(&arg.ty, types, true);
46033d722a9Sopenharmony_ci        if arg.ty == RustString {
46133d722a9Sopenharmony_ci            quote!(#var #colon *const #ty)
46233d722a9Sopenharmony_ci        } else if let Type::RustVec(_) = arg.ty {
46333d722a9Sopenharmony_ci            quote!(#var #colon *const #ty)
46433d722a9Sopenharmony_ci        } else if let Type::Fn(_) = arg.ty {
46533d722a9Sopenharmony_ci            quote!(#var #colon ::cxx::private::FatFunction)
46633d722a9Sopenharmony_ci        } else if types.needs_indirect_abi(&arg.ty) {
46733d722a9Sopenharmony_ci            quote!(#var #colon *mut #ty)
46833d722a9Sopenharmony_ci        } else {
46933d722a9Sopenharmony_ci            quote!(#var #colon #ty)
47033d722a9Sopenharmony_ci        }
47133d722a9Sopenharmony_ci    });
47233d722a9Sopenharmony_ci    let all_args = receiver.chain(args);
47333d722a9Sopenharmony_ci    let ret = if efn.throws {
47433d722a9Sopenharmony_ci        quote!(-> ::cxx::private::Result)
47533d722a9Sopenharmony_ci    } else {
47633d722a9Sopenharmony_ci        expand_extern_return_type(&efn.ret, types, true)
47733d722a9Sopenharmony_ci    };
47833d722a9Sopenharmony_ci    let mut outparam = None;
47933d722a9Sopenharmony_ci    if indirect_return(efn, types) {
48033d722a9Sopenharmony_ci        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
48133d722a9Sopenharmony_ci        outparam = Some(quote!(__return: *mut #ret));
48233d722a9Sopenharmony_ci    }
48333d722a9Sopenharmony_ci    let link_name = mangle::extern_fn(efn, types);
48433d722a9Sopenharmony_ci    let local_name = format_ident!("__{}", efn.name.rust);
48533d722a9Sopenharmony_ci    quote! {
48633d722a9Sopenharmony_ci        #[link_name = #link_name]
48733d722a9Sopenharmony_ci        fn #local_name #generics(#(#all_args,)* #outparam) #ret;
48833d722a9Sopenharmony_ci    }
48933d722a9Sopenharmony_ci}
49033d722a9Sopenharmony_ci
49133d722a9Sopenharmony_cifn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
49233d722a9Sopenharmony_ci    let doc = &efn.doc;
49333d722a9Sopenharmony_ci    let attrs = &efn.attrs;
49433d722a9Sopenharmony_ci    let decl = expand_cxx_function_decl(efn, types);
49533d722a9Sopenharmony_ci    let receiver = efn.receiver.iter().map(|receiver| {
49633d722a9Sopenharmony_ci        let var = receiver.var;
49733d722a9Sopenharmony_ci        if receiver.pinned {
49833d722a9Sopenharmony_ci            let colon = receiver.colon_token;
49933d722a9Sopenharmony_ci            let ty = receiver.ty_self();
50033d722a9Sopenharmony_ci            quote!(#var #colon #ty)
50133d722a9Sopenharmony_ci        } else {
50233d722a9Sopenharmony_ci            let ampersand = receiver.ampersand;
50333d722a9Sopenharmony_ci            let lifetime = &receiver.lifetime;
50433d722a9Sopenharmony_ci            let mutability = receiver.mutability;
50533d722a9Sopenharmony_ci            quote!(#ampersand #lifetime #mutability #var)
50633d722a9Sopenharmony_ci        }
50733d722a9Sopenharmony_ci    });
50833d722a9Sopenharmony_ci    let args = efn.args.iter().map(|arg| quote!(#arg));
50933d722a9Sopenharmony_ci    let all_args = receiver.chain(args);
51033d722a9Sopenharmony_ci    let ret = if efn.throws {
51133d722a9Sopenharmony_ci        let ok = match &efn.ret {
51233d722a9Sopenharmony_ci            Some(ret) => quote!(#ret),
51333d722a9Sopenharmony_ci            None => quote!(()),
51433d722a9Sopenharmony_ci        };
51533d722a9Sopenharmony_ci        quote!(-> ::cxx::core::result::Result<#ok, ::cxx::Exception>)
51633d722a9Sopenharmony_ci    } else {
51733d722a9Sopenharmony_ci        expand_return_type(&efn.ret)
51833d722a9Sopenharmony_ci    };
51933d722a9Sopenharmony_ci    let indirect_return = indirect_return(efn, types);
52033d722a9Sopenharmony_ci    let receiver_var = efn
52133d722a9Sopenharmony_ci        .receiver
52233d722a9Sopenharmony_ci        .iter()
52333d722a9Sopenharmony_ci        .map(|receiver| receiver.var.to_token_stream());
52433d722a9Sopenharmony_ci    let arg_vars = efn.args.iter().map(|arg| {
52533d722a9Sopenharmony_ci        let var = &arg.name.rust;
52633d722a9Sopenharmony_ci        let span = var.span();
52733d722a9Sopenharmony_ci        match &arg.ty {
52833d722a9Sopenharmony_ci            Type::Ident(ident) if ident.rust == RustString => {
52933d722a9Sopenharmony_ci                quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustString)
53033d722a9Sopenharmony_ci            }
53133d722a9Sopenharmony_ci            Type::RustBox(ty) => {
53233d722a9Sopenharmony_ci                if types.is_considered_improper_ctype(&ty.inner) {
53333d722a9Sopenharmony_ci                    quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var).cast())
53433d722a9Sopenharmony_ci                } else {
53533d722a9Sopenharmony_ci                    quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var))
53633d722a9Sopenharmony_ci                }
53733d722a9Sopenharmony_ci            }
53833d722a9Sopenharmony_ci            Type::UniquePtr(ty) => {
53933d722a9Sopenharmony_ci                if types.is_considered_improper_ctype(&ty.inner) {
54033d722a9Sopenharmony_ci                    quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var).cast())
54133d722a9Sopenharmony_ci                } else {
54233d722a9Sopenharmony_ci                    quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var))
54333d722a9Sopenharmony_ci                }
54433d722a9Sopenharmony_ci            }
54533d722a9Sopenharmony_ci            Type::RustVec(_) => quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
54633d722a9Sopenharmony_ci            Type::Ref(ty) => match &ty.inner {
54733d722a9Sopenharmony_ci                Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
54833d722a9Sopenharmony_ci                    false => quote_spanned!(span=> ::cxx::private::RustString::from_ref(#var)),
54933d722a9Sopenharmony_ci                    true => quote_spanned!(span=> ::cxx::private::RustString::from_mut(#var)),
55033d722a9Sopenharmony_ci                },
55133d722a9Sopenharmony_ci                Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
55233d722a9Sopenharmony_ci                    false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string(#var)),
55333d722a9Sopenharmony_ci                    true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string(#var)),
55433d722a9Sopenharmony_ci                },
55533d722a9Sopenharmony_ci                Type::RustVec(_) => match ty.mutable {
55633d722a9Sopenharmony_ci                    false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref(#var)),
55733d722a9Sopenharmony_ci                    true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut(#var)),
55833d722a9Sopenharmony_ci                },
55933d722a9Sopenharmony_ci                inner if types.is_considered_improper_ctype(inner) => {
56033d722a9Sopenharmony_ci                    let var = match ty.pinned {
56133d722a9Sopenharmony_ci                        false => quote!(#var),
56233d722a9Sopenharmony_ci                        true => quote_spanned!(span=> ::cxx::core::pin::Pin::into_inner_unchecked(#var)),
56333d722a9Sopenharmony_ci                    };
56433d722a9Sopenharmony_ci                    match ty.mutable {
56533d722a9Sopenharmony_ci                        false => {
56633d722a9Sopenharmony_ci                            quote_spanned!(span=> #var as *const #inner as *const ::cxx::core::ffi::c_void)
56733d722a9Sopenharmony_ci                        }
56833d722a9Sopenharmony_ci                        true => quote_spanned!(span=> #var as *mut #inner as *mut ::cxx::core::ffi::c_void),
56933d722a9Sopenharmony_ci                    }
57033d722a9Sopenharmony_ci                }
57133d722a9Sopenharmony_ci                _ => quote!(#var),
57233d722a9Sopenharmony_ci            },
57333d722a9Sopenharmony_ci            Type::Ptr(ty) => {
57433d722a9Sopenharmony_ci                if types.is_considered_improper_ctype(&ty.inner) {
57533d722a9Sopenharmony_ci                    quote_spanned!(span=> #var.cast())
57633d722a9Sopenharmony_ci                } else {
57733d722a9Sopenharmony_ci                    quote!(#var)
57833d722a9Sopenharmony_ci                }
57933d722a9Sopenharmony_ci            }
58033d722a9Sopenharmony_ci            Type::Str(_) => quote_spanned!(span=> ::cxx::private::RustStr::from(#var)),
58133d722a9Sopenharmony_ci            Type::SliceRef(ty) => match ty.mutable {
58233d722a9Sopenharmony_ci                false => quote_spanned!(span=> ::cxx::private::RustSlice::from_ref(#var)),
58333d722a9Sopenharmony_ci                true => quote_spanned!(span=> ::cxx::private::RustSlice::from_mut(#var)),
58433d722a9Sopenharmony_ci            },
58533d722a9Sopenharmony_ci            ty if types.needs_indirect_abi(ty) => quote_spanned!(span=> #var.as_mut_ptr()),
58633d722a9Sopenharmony_ci            _ => quote!(#var),
58733d722a9Sopenharmony_ci        }
58833d722a9Sopenharmony_ci    });
58933d722a9Sopenharmony_ci    let vars = receiver_var.chain(arg_vars);
59033d722a9Sopenharmony_ci    let trampolines = efn
59133d722a9Sopenharmony_ci        .args
59233d722a9Sopenharmony_ci        .iter()
59333d722a9Sopenharmony_ci        .filter_map(|arg| {
59433d722a9Sopenharmony_ci            if let Type::Fn(f) = &arg.ty {
59533d722a9Sopenharmony_ci                let var = &arg.name;
59633d722a9Sopenharmony_ci                Some(expand_function_pointer_trampoline(efn, var, f, types))
59733d722a9Sopenharmony_ci            } else {
59833d722a9Sopenharmony_ci                None
59933d722a9Sopenharmony_ci            }
60033d722a9Sopenharmony_ci        })
60133d722a9Sopenharmony_ci        .collect::<TokenStream>();
60233d722a9Sopenharmony_ci    let mut setup = efn
60333d722a9Sopenharmony_ci        .args
60433d722a9Sopenharmony_ci        .iter()
60533d722a9Sopenharmony_ci        .filter(|arg| types.needs_indirect_abi(&arg.ty))
60633d722a9Sopenharmony_ci        .map(|arg| {
60733d722a9Sopenharmony_ci            let var = &arg.name.rust;
60833d722a9Sopenharmony_ci            let span = var.span();
60933d722a9Sopenharmony_ci            // These are arguments for which C++ has taken ownership of the data
61033d722a9Sopenharmony_ci            // behind the mut reference it received.
61133d722a9Sopenharmony_ci            quote_spanned! {span=>
61233d722a9Sopenharmony_ci                let mut #var = ::cxx::core::mem::MaybeUninit::new(#var);
61333d722a9Sopenharmony_ci            }
61433d722a9Sopenharmony_ci        })
61533d722a9Sopenharmony_ci        .collect::<TokenStream>();
61633d722a9Sopenharmony_ci    let local_name = format_ident!("__{}", efn.name.rust);
61733d722a9Sopenharmony_ci    let span = efn.semi_token.span;
61833d722a9Sopenharmony_ci    let call = if indirect_return {
61933d722a9Sopenharmony_ci        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
62033d722a9Sopenharmony_ci        setup.extend(quote_spanned! {span=>
62133d722a9Sopenharmony_ci            let mut __return = ::cxx::core::mem::MaybeUninit::<#ret>::uninit();
62233d722a9Sopenharmony_ci        });
62333d722a9Sopenharmony_ci        setup.extend(if efn.throws {
62433d722a9Sopenharmony_ci            quote_spanned! {span=>
62533d722a9Sopenharmony_ci                #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
62633d722a9Sopenharmony_ci            }
62733d722a9Sopenharmony_ci        } else {
62833d722a9Sopenharmony_ci            quote_spanned! {span=>
62933d722a9Sopenharmony_ci                #local_name(#(#vars,)* __return.as_mut_ptr());
63033d722a9Sopenharmony_ci            }
63133d722a9Sopenharmony_ci        });
63233d722a9Sopenharmony_ci        quote_spanned!(span=> __return.assume_init())
63333d722a9Sopenharmony_ci    } else if efn.throws {
63433d722a9Sopenharmony_ci        quote_spanned! {span=>
63533d722a9Sopenharmony_ci            #local_name(#(#vars),*).exception()
63633d722a9Sopenharmony_ci        }
63733d722a9Sopenharmony_ci    } else {
63833d722a9Sopenharmony_ci        quote_spanned! {span=>
63933d722a9Sopenharmony_ci            #local_name(#(#vars),*)
64033d722a9Sopenharmony_ci        }
64133d722a9Sopenharmony_ci    };
64233d722a9Sopenharmony_ci    let mut expr;
64333d722a9Sopenharmony_ci    if efn.throws && efn.sig.ret.is_none() {
64433d722a9Sopenharmony_ci        expr = call;
64533d722a9Sopenharmony_ci    } else {
64633d722a9Sopenharmony_ci        expr = match &efn.ret {
64733d722a9Sopenharmony_ci            None => call,
64833d722a9Sopenharmony_ci            Some(ret) => match ret {
64933d722a9Sopenharmony_ci                Type::Ident(ident) if ident.rust == RustString => {
65033d722a9Sopenharmony_ci                    quote_spanned!(span=> #call.into_string())
65133d722a9Sopenharmony_ci                }
65233d722a9Sopenharmony_ci                Type::RustBox(ty) => {
65333d722a9Sopenharmony_ci                    if types.is_considered_improper_ctype(&ty.inner) {
65433d722a9Sopenharmony_ci                        quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call.cast()))
65533d722a9Sopenharmony_ci                    } else {
65633d722a9Sopenharmony_ci                        quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call))
65733d722a9Sopenharmony_ci                    }
65833d722a9Sopenharmony_ci                }
65933d722a9Sopenharmony_ci                Type::RustVec(vec) => {
66033d722a9Sopenharmony_ci                    if vec.inner == RustString {
66133d722a9Sopenharmony_ci                        quote_spanned!(span=> #call.into_vec_string())
66233d722a9Sopenharmony_ci                    } else {
66333d722a9Sopenharmony_ci                        quote_spanned!(span=> #call.into_vec())
66433d722a9Sopenharmony_ci                    }
66533d722a9Sopenharmony_ci                }
66633d722a9Sopenharmony_ci                Type::UniquePtr(ty) => {
66733d722a9Sopenharmony_ci                    if types.is_considered_improper_ctype(&ty.inner) {
66833d722a9Sopenharmony_ci                        quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call.cast()))
66933d722a9Sopenharmony_ci                    } else {
67033d722a9Sopenharmony_ci                        quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call))
67133d722a9Sopenharmony_ci                    }
67233d722a9Sopenharmony_ci                }
67333d722a9Sopenharmony_ci                Type::Ref(ty) => match &ty.inner {
67433d722a9Sopenharmony_ci                    Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
67533d722a9Sopenharmony_ci                        false => quote_spanned!(span=> #call.as_string()),
67633d722a9Sopenharmony_ci                        true => quote_spanned!(span=> #call.as_mut_string()),
67733d722a9Sopenharmony_ci                    },
67833d722a9Sopenharmony_ci                    Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
67933d722a9Sopenharmony_ci                        false => quote_spanned!(span=> #call.as_vec_string()),
68033d722a9Sopenharmony_ci                        true => quote_spanned!(span=> #call.as_mut_vec_string()),
68133d722a9Sopenharmony_ci                    },
68233d722a9Sopenharmony_ci                    Type::RustVec(_) => match ty.mutable {
68333d722a9Sopenharmony_ci                        false => quote_spanned!(span=> #call.as_vec()),
68433d722a9Sopenharmony_ci                        true => quote_spanned!(span=> #call.as_mut_vec()),
68533d722a9Sopenharmony_ci                    },
68633d722a9Sopenharmony_ci                    inner if types.is_considered_improper_ctype(inner) => {
68733d722a9Sopenharmony_ci                        let mutability = ty.mutability;
68833d722a9Sopenharmony_ci                        let deref_mut = quote_spanned!(span=> &#mutability *#call.cast());
68933d722a9Sopenharmony_ci                        match ty.pinned {
69033d722a9Sopenharmony_ci                            false => deref_mut,
69133d722a9Sopenharmony_ci                            true => {
69233d722a9Sopenharmony_ci                                quote_spanned!(span=> ::cxx::core::pin::Pin::new_unchecked(#deref_mut))
69333d722a9Sopenharmony_ci                            }
69433d722a9Sopenharmony_ci                        }
69533d722a9Sopenharmony_ci                    }
69633d722a9Sopenharmony_ci                    _ => call,
69733d722a9Sopenharmony_ci                },
69833d722a9Sopenharmony_ci                Type::Ptr(ty) => {
69933d722a9Sopenharmony_ci                    if types.is_considered_improper_ctype(&ty.inner) {
70033d722a9Sopenharmony_ci                        quote_spanned!(span=> #call.cast())
70133d722a9Sopenharmony_ci                    } else {
70233d722a9Sopenharmony_ci                        call
70333d722a9Sopenharmony_ci                    }
70433d722a9Sopenharmony_ci                }
70533d722a9Sopenharmony_ci                Type::Str(_) => quote_spanned!(span=> #call.as_str()),
70633d722a9Sopenharmony_ci                Type::SliceRef(slice) => {
70733d722a9Sopenharmony_ci                    let inner = &slice.inner;
70833d722a9Sopenharmony_ci                    match slice.mutable {
70933d722a9Sopenharmony_ci                        false => quote_spanned!(span=> #call.as_slice::<#inner>()),
71033d722a9Sopenharmony_ci                        true => quote_spanned!(span=> #call.as_mut_slice::<#inner>()),
71133d722a9Sopenharmony_ci                    }
71233d722a9Sopenharmony_ci                }
71333d722a9Sopenharmony_ci                _ => call,
71433d722a9Sopenharmony_ci            },
71533d722a9Sopenharmony_ci        };
71633d722a9Sopenharmony_ci        if efn.throws {
71733d722a9Sopenharmony_ci            expr = quote_spanned!(span=> ::cxx::core::result::Result::Ok(#expr));
71833d722a9Sopenharmony_ci        }
71933d722a9Sopenharmony_ci    };
72033d722a9Sopenharmony_ci    let mut dispatch = quote!(#setup #expr);
72133d722a9Sopenharmony_ci    let visibility = efn.visibility;
72233d722a9Sopenharmony_ci    let unsafety = &efn.sig.unsafety;
72333d722a9Sopenharmony_ci    if unsafety.is_none() {
72433d722a9Sopenharmony_ci        dispatch = quote_spanned!(span=> unsafe { #dispatch });
72533d722a9Sopenharmony_ci    }
72633d722a9Sopenharmony_ci    let fn_token = efn.sig.fn_token;
72733d722a9Sopenharmony_ci    let ident = &efn.name.rust;
72833d722a9Sopenharmony_ci    let generics = &efn.generics;
72933d722a9Sopenharmony_ci    let arg_list = quote_spanned!(efn.sig.paren_token.span=> (#(#all_args,)*));
73033d722a9Sopenharmony_ci    let fn_body = quote_spanned!(span=> {
73133d722a9Sopenharmony_ci        extern "C" {
73233d722a9Sopenharmony_ci            #decl
73333d722a9Sopenharmony_ci        }
73433d722a9Sopenharmony_ci        #trampolines
73533d722a9Sopenharmony_ci        #dispatch
73633d722a9Sopenharmony_ci    });
73733d722a9Sopenharmony_ci    match &efn.receiver {
73833d722a9Sopenharmony_ci        None => {
73933d722a9Sopenharmony_ci            quote! {
74033d722a9Sopenharmony_ci                #doc
74133d722a9Sopenharmony_ci                #attrs
74233d722a9Sopenharmony_ci                #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
74333d722a9Sopenharmony_ci            }
74433d722a9Sopenharmony_ci        }
74533d722a9Sopenharmony_ci        Some(receiver) => {
74633d722a9Sopenharmony_ci            let elided_generics;
74733d722a9Sopenharmony_ci            let receiver_ident = &receiver.ty.rust;
74833d722a9Sopenharmony_ci            let resolve = types.resolve(&receiver.ty);
74933d722a9Sopenharmony_ci            let receiver_generics = if receiver.ty.generics.lt_token.is_some() {
75033d722a9Sopenharmony_ci                &receiver.ty.generics
75133d722a9Sopenharmony_ci            } else {
75233d722a9Sopenharmony_ci                elided_generics = Lifetimes {
75333d722a9Sopenharmony_ci                    lt_token: resolve.generics.lt_token,
75433d722a9Sopenharmony_ci                    lifetimes: resolve
75533d722a9Sopenharmony_ci                        .generics
75633d722a9Sopenharmony_ci                        .lifetimes
75733d722a9Sopenharmony_ci                        .pairs()
75833d722a9Sopenharmony_ci                        .map(|pair| {
75933d722a9Sopenharmony_ci                            let lifetime = Lifetime::new("'_", pair.value().apostrophe);
76033d722a9Sopenharmony_ci                            let punct = pair.punct().map(|&&comma| comma);
76133d722a9Sopenharmony_ci                            punctuated::Pair::new(lifetime, punct)
76233d722a9Sopenharmony_ci                        })
76333d722a9Sopenharmony_ci                        .collect(),
76433d722a9Sopenharmony_ci                    gt_token: resolve.generics.gt_token,
76533d722a9Sopenharmony_ci                };
76633d722a9Sopenharmony_ci                &elided_generics
76733d722a9Sopenharmony_ci            };
76833d722a9Sopenharmony_ci            quote_spanned! {ident.span()=>
76933d722a9Sopenharmony_ci                impl #generics #receiver_ident #receiver_generics {
77033d722a9Sopenharmony_ci                    #doc
77133d722a9Sopenharmony_ci                    #attrs
77233d722a9Sopenharmony_ci                    #visibility #unsafety #fn_token #ident #arg_list #ret #fn_body
77333d722a9Sopenharmony_ci                }
77433d722a9Sopenharmony_ci            }
77533d722a9Sopenharmony_ci        }
77633d722a9Sopenharmony_ci    }
77733d722a9Sopenharmony_ci}
77833d722a9Sopenharmony_ci
77933d722a9Sopenharmony_cifn expand_function_pointer_trampoline(
78033d722a9Sopenharmony_ci    efn: &ExternFn,
78133d722a9Sopenharmony_ci    var: &Pair,
78233d722a9Sopenharmony_ci    sig: &Signature,
78333d722a9Sopenharmony_ci    types: &Types,
78433d722a9Sopenharmony_ci) -> TokenStream {
78533d722a9Sopenharmony_ci    let c_trampoline = mangle::c_trampoline(efn, var, types);
78633d722a9Sopenharmony_ci    let r_trampoline = mangle::r_trampoline(efn, var, types);
78733d722a9Sopenharmony_ci    let local_name = parse_quote!(__);
78833d722a9Sopenharmony_ci    let prevent_unwind_label = format!("::{}::{}", efn.name.rust, var.rust);
78933d722a9Sopenharmony_ci    let body_span = efn.semi_token.span;
79033d722a9Sopenharmony_ci    let shim = expand_rust_function_shim_impl(
79133d722a9Sopenharmony_ci        sig,
79233d722a9Sopenharmony_ci        types,
79333d722a9Sopenharmony_ci        &r_trampoline,
79433d722a9Sopenharmony_ci        local_name,
79533d722a9Sopenharmony_ci        prevent_unwind_label,
79633d722a9Sopenharmony_ci        None,
79733d722a9Sopenharmony_ci        Some(&efn.generics),
79833d722a9Sopenharmony_ci        &efn.attrs,
79933d722a9Sopenharmony_ci        body_span,
80033d722a9Sopenharmony_ci    );
80133d722a9Sopenharmony_ci    let var = &var.rust;
80233d722a9Sopenharmony_ci
80333d722a9Sopenharmony_ci    quote! {
80433d722a9Sopenharmony_ci        let #var = ::cxx::private::FatFunction {
80533d722a9Sopenharmony_ci            trampoline: {
80633d722a9Sopenharmony_ci                extern "C" {
80733d722a9Sopenharmony_ci                    #[link_name = #c_trampoline]
80833d722a9Sopenharmony_ci                    fn trampoline();
80933d722a9Sopenharmony_ci                }
81033d722a9Sopenharmony_ci                #shim
81133d722a9Sopenharmony_ci                trampoline as usize as *const ::cxx::core::ffi::c_void
81233d722a9Sopenharmony_ci            },
81333d722a9Sopenharmony_ci            ptr: #var as usize as *const ::cxx::core::ffi::c_void,
81433d722a9Sopenharmony_ci        };
81533d722a9Sopenharmony_ci    }
81633d722a9Sopenharmony_ci}
81733d722a9Sopenharmony_ci
81833d722a9Sopenharmony_cifn expand_rust_type_import(ety: &ExternType) -> TokenStream {
81933d722a9Sopenharmony_ci    let ident = &ety.name.rust;
82033d722a9Sopenharmony_ci    let span = ident.span();
82133d722a9Sopenharmony_ci
82233d722a9Sopenharmony_ci    quote_spanned! {span=>
82333d722a9Sopenharmony_ci        use super::#ident;
82433d722a9Sopenharmony_ci    }
82533d722a9Sopenharmony_ci}
82633d722a9Sopenharmony_ci
82733d722a9Sopenharmony_cifn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
82833d722a9Sopenharmony_ci    let ident = &ety.name.rust;
82933d722a9Sopenharmony_ci    let generics = &ety.generics;
83033d722a9Sopenharmony_ci    let span = ident.span();
83133d722a9Sopenharmony_ci    let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
83233d722a9Sopenharmony_ci
83333d722a9Sopenharmony_ci    let mut impls = quote_spanned! {span=>
83433d722a9Sopenharmony_ci        #[doc(hidden)]
83533d722a9Sopenharmony_ci        #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {}
83633d722a9Sopenharmony_ci    };
83733d722a9Sopenharmony_ci
83833d722a9Sopenharmony_ci    for derive in &ety.derives {
83933d722a9Sopenharmony_ci        if derive.what == Trait::ExternType {
84033d722a9Sopenharmony_ci            let type_id = type_id(&ety.name);
84133d722a9Sopenharmony_ci            let span = derive.span;
84233d722a9Sopenharmony_ci            impls.extend(quote_spanned! {span=>
84333d722a9Sopenharmony_ci                unsafe impl #generics ::cxx::ExternType for #ident #generics {
84433d722a9Sopenharmony_ci                    #[allow(unused_attributes)] // incorrect lint
84533d722a9Sopenharmony_ci                    #[doc(hidden)]
84633d722a9Sopenharmony_ci                    type Id = #type_id;
84733d722a9Sopenharmony_ci                    type Kind = ::cxx::kind::Opaque;
84833d722a9Sopenharmony_ci                }
84933d722a9Sopenharmony_ci            });
85033d722a9Sopenharmony_ci        }
85133d722a9Sopenharmony_ci    }
85233d722a9Sopenharmony_ci
85333d722a9Sopenharmony_ci    impls
85433d722a9Sopenharmony_ci}
85533d722a9Sopenharmony_ci
85633d722a9Sopenharmony_cifn expand_rust_type_assert_unpin(ety: &ExternType, types: &Types) -> TokenStream {
85733d722a9Sopenharmony_ci    let ident = &ety.name.rust;
85833d722a9Sopenharmony_ci    let begin_span = Token![::](ety.type_token.span);
85933d722a9Sopenharmony_ci    let unpin = quote_spanned! {ety.semi_token.span=>
86033d722a9Sopenharmony_ci        #begin_span cxx::core::marker::Unpin
86133d722a9Sopenharmony_ci    };
86233d722a9Sopenharmony_ci
86333d722a9Sopenharmony_ci    let resolve = types.resolve(ident);
86433d722a9Sopenharmony_ci    let lifetimes = resolve.generics.to_underscore_lifetimes();
86533d722a9Sopenharmony_ci
86633d722a9Sopenharmony_ci    quote_spanned! {ident.span()=>
86733d722a9Sopenharmony_ci        let _ = {
86833d722a9Sopenharmony_ci            fn __AssertUnpin<T: ?::cxx::core::marker::Sized + #unpin>() {}
86933d722a9Sopenharmony_ci            __AssertUnpin::<#ident #lifetimes>
87033d722a9Sopenharmony_ci        };
87133d722a9Sopenharmony_ci    }
87233d722a9Sopenharmony_ci}
87333d722a9Sopenharmony_ci
87433d722a9Sopenharmony_cifn expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStream {
87533d722a9Sopenharmony_ci    // Rustc will render as follows if not sized:
87633d722a9Sopenharmony_ci    //
87733d722a9Sopenharmony_ci    //     type TheirType;
87833d722a9Sopenharmony_ci    //     -----^^^^^^^^^-
87933d722a9Sopenharmony_ci    //     |    |
88033d722a9Sopenharmony_ci    //     |    doesn't have a size known at compile-time
88133d722a9Sopenharmony_ci    //     required by this bound in `__AssertSized`
88233d722a9Sopenharmony_ci
88333d722a9Sopenharmony_ci    let ident = &ety.name.rust;
88433d722a9Sopenharmony_ci    let begin_span = Token![::](ety.type_token.span);
88533d722a9Sopenharmony_ci    let sized = quote_spanned! {ety.semi_token.span=>
88633d722a9Sopenharmony_ci        #begin_span cxx::core::marker::Sized
88733d722a9Sopenharmony_ci    };
88833d722a9Sopenharmony_ci
88933d722a9Sopenharmony_ci    let link_sizeof = mangle::operator(&ety.name, "sizeof");
89033d722a9Sopenharmony_ci    let link_alignof = mangle::operator(&ety.name, "alignof");
89133d722a9Sopenharmony_ci
89233d722a9Sopenharmony_ci    let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
89333d722a9Sopenharmony_ci    let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
89433d722a9Sopenharmony_ci
89533d722a9Sopenharmony_ci    let resolve = types.resolve(ident);
89633d722a9Sopenharmony_ci    let lifetimes = resolve.generics.to_underscore_lifetimes();
89733d722a9Sopenharmony_ci
89833d722a9Sopenharmony_ci    quote_spanned! {ident.span()=>
89933d722a9Sopenharmony_ci        {
90033d722a9Sopenharmony_ci            #[doc(hidden)]
90133d722a9Sopenharmony_ci            fn __AssertSized<T: ?#sized + #sized>() -> ::cxx::core::alloc::Layout {
90233d722a9Sopenharmony_ci                ::cxx::core::alloc::Layout::new::<T>()
90333d722a9Sopenharmony_ci            }
90433d722a9Sopenharmony_ci            #[doc(hidden)]
90533d722a9Sopenharmony_ci            #[export_name = #link_sizeof]
90633d722a9Sopenharmony_ci            extern "C" fn #local_sizeof() -> usize {
90733d722a9Sopenharmony_ci                __AssertSized::<#ident #lifetimes>().size()
90833d722a9Sopenharmony_ci            }
90933d722a9Sopenharmony_ci            #[doc(hidden)]
91033d722a9Sopenharmony_ci            #[export_name = #link_alignof]
91133d722a9Sopenharmony_ci            extern "C" fn #local_alignof() -> usize {
91233d722a9Sopenharmony_ci                __AssertSized::<#ident #lifetimes>().align()
91333d722a9Sopenharmony_ci            }
91433d722a9Sopenharmony_ci        }
91533d722a9Sopenharmony_ci    }
91633d722a9Sopenharmony_ci}
91733d722a9Sopenharmony_ci
91833d722a9Sopenharmony_cifn expand_forbid(impls: TokenStream) -> TokenStream {
91933d722a9Sopenharmony_ci    quote! {
92033d722a9Sopenharmony_ci        mod forbid {
92133d722a9Sopenharmony_ci            pub trait Drop {}
92233d722a9Sopenharmony_ci            #[allow(drop_bounds)]
92333d722a9Sopenharmony_ci            impl<T: ?::cxx::core::marker::Sized + ::cxx::core::ops::Drop> self::Drop for T {}
92433d722a9Sopenharmony_ci            #impls
92533d722a9Sopenharmony_ci        }
92633d722a9Sopenharmony_ci    }
92733d722a9Sopenharmony_ci}
92833d722a9Sopenharmony_ci
92933d722a9Sopenharmony_cifn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
93033d722a9Sopenharmony_ci    let link_name = mangle::extern_fn(efn, types);
93133d722a9Sopenharmony_ci    let local_name = match &efn.receiver {
93233d722a9Sopenharmony_ci        None => format_ident!("__{}", efn.name.rust),
93333d722a9Sopenharmony_ci        Some(receiver) => format_ident!("__{}__{}", receiver.ty.rust, efn.name.rust),
93433d722a9Sopenharmony_ci    };
93533d722a9Sopenharmony_ci    let prevent_unwind_label = match &efn.receiver {
93633d722a9Sopenharmony_ci        None => format!("::{}", efn.name.rust),
93733d722a9Sopenharmony_ci        Some(receiver) => format!("::{}::{}", receiver.ty.rust, efn.name.rust),
93833d722a9Sopenharmony_ci    };
93933d722a9Sopenharmony_ci    let invoke = Some(&efn.name.rust);
94033d722a9Sopenharmony_ci    let body_span = efn.semi_token.span;
94133d722a9Sopenharmony_ci    expand_rust_function_shim_impl(
94233d722a9Sopenharmony_ci        efn,
94333d722a9Sopenharmony_ci        types,
94433d722a9Sopenharmony_ci        &link_name,
94533d722a9Sopenharmony_ci        local_name,
94633d722a9Sopenharmony_ci        prevent_unwind_label,
94733d722a9Sopenharmony_ci        invoke,
94833d722a9Sopenharmony_ci        None,
94933d722a9Sopenharmony_ci        &efn.attrs,
95033d722a9Sopenharmony_ci        body_span,
95133d722a9Sopenharmony_ci    )
95233d722a9Sopenharmony_ci}
95333d722a9Sopenharmony_ci
95433d722a9Sopenharmony_cifn expand_rust_function_shim_impl(
95533d722a9Sopenharmony_ci    sig: &Signature,
95633d722a9Sopenharmony_ci    types: &Types,
95733d722a9Sopenharmony_ci    link_name: &Symbol,
95833d722a9Sopenharmony_ci    local_name: Ident,
95933d722a9Sopenharmony_ci    prevent_unwind_label: String,
96033d722a9Sopenharmony_ci    invoke: Option<&Ident>,
96133d722a9Sopenharmony_ci    outer_generics: Option<&Generics>,
96233d722a9Sopenharmony_ci    attrs: &OtherAttrs,
96333d722a9Sopenharmony_ci    body_span: Span,
96433d722a9Sopenharmony_ci) -> TokenStream {
96533d722a9Sopenharmony_ci    let generics = outer_generics.unwrap_or(&sig.generics);
96633d722a9Sopenharmony_ci    let receiver_var = sig
96733d722a9Sopenharmony_ci        .receiver
96833d722a9Sopenharmony_ci        .as_ref()
96933d722a9Sopenharmony_ci        .map(|receiver| quote_spanned!(receiver.var.span=> __self));
97033d722a9Sopenharmony_ci    let receiver = sig.receiver.as_ref().map(|receiver| {
97133d722a9Sopenharmony_ci        let colon = receiver.colon_token;
97233d722a9Sopenharmony_ci        let receiver_type = receiver.ty();
97333d722a9Sopenharmony_ci        quote!(#receiver_var #colon #receiver_type)
97433d722a9Sopenharmony_ci    });
97533d722a9Sopenharmony_ci    let args = sig.args.iter().map(|arg| {
97633d722a9Sopenharmony_ci        let var = &arg.name.rust;
97733d722a9Sopenharmony_ci        let colon = arg.colon_token;
97833d722a9Sopenharmony_ci        let ty = expand_extern_type(&arg.ty, types, false);
97933d722a9Sopenharmony_ci        if types.needs_indirect_abi(&arg.ty) {
98033d722a9Sopenharmony_ci            quote!(#var #colon *mut #ty)
98133d722a9Sopenharmony_ci        } else {
98233d722a9Sopenharmony_ci            quote!(#var #colon #ty)
98333d722a9Sopenharmony_ci        }
98433d722a9Sopenharmony_ci    });
98533d722a9Sopenharmony_ci    let all_args = receiver.into_iter().chain(args);
98633d722a9Sopenharmony_ci
98733d722a9Sopenharmony_ci    let arg_vars = sig.args.iter().map(|arg| {
98833d722a9Sopenharmony_ci        let var = &arg.name.rust;
98933d722a9Sopenharmony_ci        let span = var.span();
99033d722a9Sopenharmony_ci        match &arg.ty {
99133d722a9Sopenharmony_ci            Type::Ident(i) if i.rust == RustString => {
99233d722a9Sopenharmony_ci                quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_string()))
99333d722a9Sopenharmony_ci            }
99433d722a9Sopenharmony_ci            Type::RustBox(_) => quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#var)),
99533d722a9Sopenharmony_ci            Type::RustVec(vec) => {
99633d722a9Sopenharmony_ci                if vec.inner == RustString {
99733d722a9Sopenharmony_ci                    quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec_string()))
99833d722a9Sopenharmony_ci                } else {
99933d722a9Sopenharmony_ci                    quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec()))
100033d722a9Sopenharmony_ci                }
100133d722a9Sopenharmony_ci            }
100233d722a9Sopenharmony_ci            Type::UniquePtr(_) => quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#var)),
100333d722a9Sopenharmony_ci            Type::Ref(ty) => match &ty.inner {
100433d722a9Sopenharmony_ci                Type::Ident(i) if i.rust == RustString => match ty.mutable {
100533d722a9Sopenharmony_ci                    false => quote_spanned!(span=> #var.as_string()),
100633d722a9Sopenharmony_ci                    true => quote_spanned!(span=> #var.as_mut_string()),
100733d722a9Sopenharmony_ci                },
100833d722a9Sopenharmony_ci                Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
100933d722a9Sopenharmony_ci                    false => quote_spanned!(span=> #var.as_vec_string()),
101033d722a9Sopenharmony_ci                    true => quote_spanned!(span=> #var.as_mut_vec_string()),
101133d722a9Sopenharmony_ci                },
101233d722a9Sopenharmony_ci                Type::RustVec(_) => match ty.mutable {
101333d722a9Sopenharmony_ci                    false => quote_spanned!(span=> #var.as_vec()),
101433d722a9Sopenharmony_ci                    true => quote_spanned!(span=> #var.as_mut_vec()),
101533d722a9Sopenharmony_ci                },
101633d722a9Sopenharmony_ci                _ => quote!(#var),
101733d722a9Sopenharmony_ci            },
101833d722a9Sopenharmony_ci            Type::Str(_) => quote_spanned!(span=> #var.as_str()),
101933d722a9Sopenharmony_ci            Type::SliceRef(slice) => {
102033d722a9Sopenharmony_ci                let inner = &slice.inner;
102133d722a9Sopenharmony_ci                match slice.mutable {
102233d722a9Sopenharmony_ci                    false => quote_spanned!(span=> #var.as_slice::<#inner>()),
102333d722a9Sopenharmony_ci                    true => quote_spanned!(span=> #var.as_mut_slice::<#inner>()),
102433d722a9Sopenharmony_ci                }
102533d722a9Sopenharmony_ci            }
102633d722a9Sopenharmony_ci            ty if types.needs_indirect_abi(ty) => {
102733d722a9Sopenharmony_ci                quote_spanned!(span=> ::cxx::core::ptr::read(#var))
102833d722a9Sopenharmony_ci            }
102933d722a9Sopenharmony_ci            _ => quote!(#var),
103033d722a9Sopenharmony_ci        }
103133d722a9Sopenharmony_ci    });
103233d722a9Sopenharmony_ci    let vars: Vec<_> = receiver_var.into_iter().chain(arg_vars).collect();
103333d722a9Sopenharmony_ci
103433d722a9Sopenharmony_ci    let wrap_super = invoke.map(|invoke| expand_rust_function_shim_super(sig, &local_name, invoke));
103533d722a9Sopenharmony_ci
103633d722a9Sopenharmony_ci    let mut requires_closure;
103733d722a9Sopenharmony_ci    let mut call = match invoke {
103833d722a9Sopenharmony_ci        Some(_) => {
103933d722a9Sopenharmony_ci            requires_closure = false;
104033d722a9Sopenharmony_ci            quote!(#local_name)
104133d722a9Sopenharmony_ci        }
104233d722a9Sopenharmony_ci        None => {
104333d722a9Sopenharmony_ci            requires_closure = true;
104433d722a9Sopenharmony_ci            quote!(::cxx::core::mem::transmute::<*const (), #sig>(__extern))
104533d722a9Sopenharmony_ci        }
104633d722a9Sopenharmony_ci    };
104733d722a9Sopenharmony_ci    requires_closure |= !vars.is_empty();
104833d722a9Sopenharmony_ci    call.extend(quote! { (#(#vars),*) });
104933d722a9Sopenharmony_ci
105033d722a9Sopenharmony_ci    let span = body_span;
105133d722a9Sopenharmony_ci    let conversion = sig.ret.as_ref().and_then(|ret| match ret {
105233d722a9Sopenharmony_ci        Type::Ident(ident) if ident.rust == RustString => {
105333d722a9Sopenharmony_ci            Some(quote_spanned!(span=> ::cxx::private::RustString::from))
105433d722a9Sopenharmony_ci        }
105533d722a9Sopenharmony_ci        Type::RustBox(_) => Some(quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw)),
105633d722a9Sopenharmony_ci        Type::RustVec(vec) => {
105733d722a9Sopenharmony_ci            if vec.inner == RustString {
105833d722a9Sopenharmony_ci                Some(quote_spanned!(span=> ::cxx::private::RustVec::from_vec_string))
105933d722a9Sopenharmony_ci            } else {
106033d722a9Sopenharmony_ci                Some(quote_spanned!(span=> ::cxx::private::RustVec::from))
106133d722a9Sopenharmony_ci            }
106233d722a9Sopenharmony_ci        }
106333d722a9Sopenharmony_ci        Type::UniquePtr(_) => Some(quote_spanned!(span=> ::cxx::UniquePtr::into_raw)),
106433d722a9Sopenharmony_ci        Type::Ref(ty) => match &ty.inner {
106533d722a9Sopenharmony_ci            Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
106633d722a9Sopenharmony_ci                false => Some(quote_spanned!(span=> ::cxx::private::RustString::from_ref)),
106733d722a9Sopenharmony_ci                true => Some(quote_spanned!(span=> ::cxx::private::RustString::from_mut)),
106833d722a9Sopenharmony_ci            },
106933d722a9Sopenharmony_ci            Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
107033d722a9Sopenharmony_ci                false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string)),
107133d722a9Sopenharmony_ci                true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string)),
107233d722a9Sopenharmony_ci            },
107333d722a9Sopenharmony_ci            Type::RustVec(_) => match ty.mutable {
107433d722a9Sopenharmony_ci                false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref)),
107533d722a9Sopenharmony_ci                true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut)),
107633d722a9Sopenharmony_ci            },
107733d722a9Sopenharmony_ci            _ => None,
107833d722a9Sopenharmony_ci        },
107933d722a9Sopenharmony_ci        Type::Str(_) => Some(quote_spanned!(span=> ::cxx::private::RustStr::from)),
108033d722a9Sopenharmony_ci        Type::SliceRef(ty) => match ty.mutable {
108133d722a9Sopenharmony_ci            false => Some(quote_spanned!(span=> ::cxx::private::RustSlice::from_ref)),
108233d722a9Sopenharmony_ci            true => Some(quote_spanned!(span=> ::cxx::private::RustSlice::from_mut)),
108333d722a9Sopenharmony_ci        },
108433d722a9Sopenharmony_ci        _ => None,
108533d722a9Sopenharmony_ci    });
108633d722a9Sopenharmony_ci
108733d722a9Sopenharmony_ci    let mut expr = match conversion {
108833d722a9Sopenharmony_ci        None => call,
108933d722a9Sopenharmony_ci        Some(conversion) if !sig.throws => {
109033d722a9Sopenharmony_ci            requires_closure = true;
109133d722a9Sopenharmony_ci            quote_spanned!(span=> #conversion(#call))
109233d722a9Sopenharmony_ci        }
109333d722a9Sopenharmony_ci        Some(conversion) => {
109433d722a9Sopenharmony_ci            requires_closure = true;
109533d722a9Sopenharmony_ci            quote_spanned!(span=> ::cxx::core::result::Result::map(#call, #conversion))
109633d722a9Sopenharmony_ci        }
109733d722a9Sopenharmony_ci    };
109833d722a9Sopenharmony_ci
109933d722a9Sopenharmony_ci    let mut outparam = None;
110033d722a9Sopenharmony_ci    let indirect_return = indirect_return(sig, types);
110133d722a9Sopenharmony_ci    if indirect_return {
110233d722a9Sopenharmony_ci        let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types, false);
110333d722a9Sopenharmony_ci        outparam = Some(quote_spanned!(span=> __return: *mut #ret,));
110433d722a9Sopenharmony_ci    }
110533d722a9Sopenharmony_ci    if sig.throws {
110633d722a9Sopenharmony_ci        let out = match sig.ret {
110733d722a9Sopenharmony_ci            Some(_) => quote_spanned!(span=> __return),
110833d722a9Sopenharmony_ci            None => quote_spanned!(span=> &mut ()),
110933d722a9Sopenharmony_ci        };
111033d722a9Sopenharmony_ci        requires_closure = true;
111133d722a9Sopenharmony_ci        expr = quote_spanned!(span=> ::cxx::private::r#try(#out, #expr));
111233d722a9Sopenharmony_ci    } else if indirect_return {
111333d722a9Sopenharmony_ci        requires_closure = true;
111433d722a9Sopenharmony_ci        expr = quote_spanned!(span=> ::cxx::core::ptr::write(__return, #expr));
111533d722a9Sopenharmony_ci    }
111633d722a9Sopenharmony_ci
111733d722a9Sopenharmony_ci    let closure = if requires_closure {
111833d722a9Sopenharmony_ci        quote_spanned!(span=> move || #expr)
111933d722a9Sopenharmony_ci    } else {
112033d722a9Sopenharmony_ci        quote!(#local_name)
112133d722a9Sopenharmony_ci    };
112233d722a9Sopenharmony_ci
112333d722a9Sopenharmony_ci    expr = quote_spanned!(span=> ::cxx::private::prevent_unwind(__fn, #closure));
112433d722a9Sopenharmony_ci
112533d722a9Sopenharmony_ci    let ret = if sig.throws {
112633d722a9Sopenharmony_ci        quote!(-> ::cxx::private::Result)
112733d722a9Sopenharmony_ci    } else {
112833d722a9Sopenharmony_ci        expand_extern_return_type(&sig.ret, types, false)
112933d722a9Sopenharmony_ci    };
113033d722a9Sopenharmony_ci
113133d722a9Sopenharmony_ci    let pointer = match invoke {
113233d722a9Sopenharmony_ci        None => Some(quote_spanned!(span=> __extern: *const ())),
113333d722a9Sopenharmony_ci        Some(_) => None,
113433d722a9Sopenharmony_ci    };
113533d722a9Sopenharmony_ci
113633d722a9Sopenharmony_ci    quote_spanned! {span=>
113733d722a9Sopenharmony_ci        #attrs
113833d722a9Sopenharmony_ci        #[doc(hidden)]
113933d722a9Sopenharmony_ci        #[export_name = #link_name]
114033d722a9Sopenharmony_ci        unsafe extern "C" fn #local_name #generics(#(#all_args,)* #outparam #pointer) #ret {
114133d722a9Sopenharmony_ci            let __fn = ::cxx::private::concat!(::cxx::private::module_path!(), #prevent_unwind_label);
114233d722a9Sopenharmony_ci            #wrap_super
114333d722a9Sopenharmony_ci            #expr
114433d722a9Sopenharmony_ci        }
114533d722a9Sopenharmony_ci    }
114633d722a9Sopenharmony_ci}
114733d722a9Sopenharmony_ci
114833d722a9Sopenharmony_ci// A wrapper like `fn f(x: Arg) { super::f(x) }` just to ensure we have the
114933d722a9Sopenharmony_ci// accurate unsafety declaration and no problematic elided lifetimes.
115033d722a9Sopenharmony_cifn expand_rust_function_shim_super(
115133d722a9Sopenharmony_ci    sig: &Signature,
115233d722a9Sopenharmony_ci    local_name: &Ident,
115333d722a9Sopenharmony_ci    invoke: &Ident,
115433d722a9Sopenharmony_ci) -> TokenStream {
115533d722a9Sopenharmony_ci    let unsafety = sig.unsafety;
115633d722a9Sopenharmony_ci    let generics = &sig.generics;
115733d722a9Sopenharmony_ci
115833d722a9Sopenharmony_ci    let receiver_var = sig
115933d722a9Sopenharmony_ci        .receiver
116033d722a9Sopenharmony_ci        .as_ref()
116133d722a9Sopenharmony_ci        .map(|receiver| Ident::new("__self", receiver.var.span));
116233d722a9Sopenharmony_ci    let receiver = sig.receiver.iter().map(|receiver| {
116333d722a9Sopenharmony_ci        let receiver_type = receiver.ty();
116433d722a9Sopenharmony_ci        quote!(#receiver_var: #receiver_type)
116533d722a9Sopenharmony_ci    });
116633d722a9Sopenharmony_ci    let args = sig.args.iter().map(|arg| quote!(#arg));
116733d722a9Sopenharmony_ci    let all_args = receiver.chain(args);
116833d722a9Sopenharmony_ci
116933d722a9Sopenharmony_ci    let ret = if let Some((result, _langle, rangle)) = sig.throws_tokens {
117033d722a9Sopenharmony_ci        let ok = match &sig.ret {
117133d722a9Sopenharmony_ci            Some(ret) => quote!(#ret),
117233d722a9Sopenharmony_ci            None => quote!(()),
117333d722a9Sopenharmony_ci        };
117433d722a9Sopenharmony_ci        // Set spans that result in the `Result<...>` written by the user being
117533d722a9Sopenharmony_ci        // highlighted as the cause if their error type has no Display impl.
117633d722a9Sopenharmony_ci        let result_begin = quote_spanned!(result.span=> ::cxx::core::result::Result<#ok, impl);
117733d722a9Sopenharmony_ci        let result_end = quote_spanned!(rangle.span=> ::cxx::core::fmt::Display>);
117833d722a9Sopenharmony_ci        quote!(-> #result_begin #result_end)
117933d722a9Sopenharmony_ci    } else {
118033d722a9Sopenharmony_ci        expand_return_type(&sig.ret)
118133d722a9Sopenharmony_ci    };
118233d722a9Sopenharmony_ci
118333d722a9Sopenharmony_ci    let arg_vars = sig.args.iter().map(|arg| &arg.name.rust);
118433d722a9Sopenharmony_ci    let vars = receiver_var.iter().chain(arg_vars);
118533d722a9Sopenharmony_ci
118633d722a9Sopenharmony_ci    let span = invoke.span();
118733d722a9Sopenharmony_ci    let call = match &sig.receiver {
118833d722a9Sopenharmony_ci        None => quote_spanned!(span=> super::#invoke),
118933d722a9Sopenharmony_ci        Some(receiver) => {
119033d722a9Sopenharmony_ci            let receiver_type = &receiver.ty.rust;
119133d722a9Sopenharmony_ci            quote_spanned!(span=> #receiver_type::#invoke)
119233d722a9Sopenharmony_ci        }
119333d722a9Sopenharmony_ci    };
119433d722a9Sopenharmony_ci
119533d722a9Sopenharmony_ci    quote_spanned! {span=>
119633d722a9Sopenharmony_ci        #unsafety fn #local_name #generics(#(#all_args,)*) #ret {
119733d722a9Sopenharmony_ci            #call(#(#vars,)*)
119833d722a9Sopenharmony_ci        }
119933d722a9Sopenharmony_ci    }
120033d722a9Sopenharmony_ci}
120133d722a9Sopenharmony_ci
120233d722a9Sopenharmony_cifn expand_type_alias(alias: &TypeAlias) -> TokenStream {
120333d722a9Sopenharmony_ci    let doc = &alias.doc;
120433d722a9Sopenharmony_ci    let attrs = &alias.attrs;
120533d722a9Sopenharmony_ci    let visibility = alias.visibility;
120633d722a9Sopenharmony_ci    let type_token = alias.type_token;
120733d722a9Sopenharmony_ci    let ident = &alias.name.rust;
120833d722a9Sopenharmony_ci    let generics = &alias.generics;
120933d722a9Sopenharmony_ci    let eq_token = alias.eq_token;
121033d722a9Sopenharmony_ci    let ty = &alias.ty;
121133d722a9Sopenharmony_ci    let semi_token = alias.semi_token;
121233d722a9Sopenharmony_ci
121333d722a9Sopenharmony_ci    quote! {
121433d722a9Sopenharmony_ci        #doc
121533d722a9Sopenharmony_ci        #attrs
121633d722a9Sopenharmony_ci        #visibility #type_token #ident #generics #eq_token #ty #semi_token
121733d722a9Sopenharmony_ci    }
121833d722a9Sopenharmony_ci}
121933d722a9Sopenharmony_ci
122033d722a9Sopenharmony_cifn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
122133d722a9Sopenharmony_ci    let ident = &alias.name.rust;
122233d722a9Sopenharmony_ci    let type_id = type_id(&alias.name);
122333d722a9Sopenharmony_ci    let begin_span = alias.type_token.span;
122433d722a9Sopenharmony_ci    let end_span = alias.semi_token.span;
122533d722a9Sopenharmony_ci    let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_type::<);
122633d722a9Sopenharmony_ci    let end = quote_spanned!(end_span=> >);
122733d722a9Sopenharmony_ci
122833d722a9Sopenharmony_ci    let mut verify = quote! {
122933d722a9Sopenharmony_ci        const _: fn() = #begin #ident, #type_id #end;
123033d722a9Sopenharmony_ci    };
123133d722a9Sopenharmony_ci
123233d722a9Sopenharmony_ci    if types.required_trivial.contains_key(&alias.name.rust) {
123333d722a9Sopenharmony_ci        let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
123433d722a9Sopenharmony_ci        verify.extend(quote! {
123533d722a9Sopenharmony_ci            const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
123633d722a9Sopenharmony_ci        });
123733d722a9Sopenharmony_ci    }
123833d722a9Sopenharmony_ci
123933d722a9Sopenharmony_ci    verify
124033d722a9Sopenharmony_ci}
124133d722a9Sopenharmony_ci
124233d722a9Sopenharmony_cifn type_id(name: &Pair) -> TokenStream {
124333d722a9Sopenharmony_ci    let namespace_segments = name.namespace.iter();
124433d722a9Sopenharmony_ci    let mut segments = Vec::with_capacity(namespace_segments.len() + 1);
124533d722a9Sopenharmony_ci    segments.extend(namespace_segments.cloned());
124633d722a9Sopenharmony_ci    segments.push(Ident::new(&name.cxx.to_string(), Span::call_site()));
124733d722a9Sopenharmony_ci    let qualified = QualifiedName { segments };
124833d722a9Sopenharmony_ci    crate::type_id::expand(Crate::Cxx, qualified)
124933d722a9Sopenharmony_ci}
125033d722a9Sopenharmony_ci
125133d722a9Sopenharmony_cifn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
125233d722a9Sopenharmony_ci    let ident = key.rust;
125333d722a9Sopenharmony_ci    let resolve = types.resolve(ident);
125433d722a9Sopenharmony_ci    let link_prefix = format!("cxxbridge1$box${}$", resolve.name.to_symbol());
125533d722a9Sopenharmony_ci    let link_alloc = format!("{}alloc", link_prefix);
125633d722a9Sopenharmony_ci    let link_dealloc = format!("{}dealloc", link_prefix);
125733d722a9Sopenharmony_ci    let link_drop = format!("{}drop", link_prefix);
125833d722a9Sopenharmony_ci
125933d722a9Sopenharmony_ci    let local_prefix = format_ident!("{}__box_", ident);
126033d722a9Sopenharmony_ci    let local_alloc = format_ident!("{}alloc", local_prefix);
126133d722a9Sopenharmony_ci    let local_dealloc = format_ident!("{}dealloc", local_prefix);
126233d722a9Sopenharmony_ci    let local_drop = format_ident!("{}drop", local_prefix);
126333d722a9Sopenharmony_ci
126433d722a9Sopenharmony_ci    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
126533d722a9Sopenharmony_ci
126633d722a9Sopenharmony_ci    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
126733d722a9Sopenharmony_ci    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
126833d722a9Sopenharmony_ci    let unsafe_token = format_ident!("unsafe", span = begin_span);
126933d722a9Sopenharmony_ci    let prevent_unwind_drop_label = format!("::{} as Drop>::drop", ident);
127033d722a9Sopenharmony_ci
127133d722a9Sopenharmony_ci    quote_spanned! {end_span=>
127233d722a9Sopenharmony_ci        #[doc(hidden)]
127333d722a9Sopenharmony_ci        #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {}
127433d722a9Sopenharmony_ci        #[doc(hidden)]
127533d722a9Sopenharmony_ci        #[export_name = #link_alloc]
127633d722a9Sopenharmony_ci        unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics> {
127733d722a9Sopenharmony_ci            // No prevent_unwind: the global allocator is not allowed to panic.
127833d722a9Sopenharmony_ci            //
127933d722a9Sopenharmony_ci            // TODO: replace with Box::new_uninit when stable.
128033d722a9Sopenharmony_ci            // https://doc.rust-lang.org/std/boxed/struct.Box.html#method.new_uninit
128133d722a9Sopenharmony_ci            // https://github.com/rust-lang/rust/issues/63291
128233d722a9Sopenharmony_ci            ::cxx::alloc::boxed::Box::into_raw(::cxx::alloc::boxed::Box::new(::cxx::core::mem::MaybeUninit::uninit()))
128333d722a9Sopenharmony_ci        }
128433d722a9Sopenharmony_ci        #[doc(hidden)]
128533d722a9Sopenharmony_ci        #[export_name = #link_dealloc]
128633d722a9Sopenharmony_ci        unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics>) {
128733d722a9Sopenharmony_ci            // No prevent_unwind: the global allocator is not allowed to panic.
128833d722a9Sopenharmony_ci            let _ = ::cxx::alloc::boxed::Box::from_raw(ptr);
128933d722a9Sopenharmony_ci        }
129033d722a9Sopenharmony_ci        #[doc(hidden)]
129133d722a9Sopenharmony_ci        #[export_name = #link_drop]
129233d722a9Sopenharmony_ci        unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::alloc::boxed::Box<#ident #ty_generics>) {
129333d722a9Sopenharmony_ci            let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
129433d722a9Sopenharmony_ci            ::cxx::private::prevent_unwind(__fn, || ::cxx::core::ptr::drop_in_place(this));
129533d722a9Sopenharmony_ci        }
129633d722a9Sopenharmony_ci    }
129733d722a9Sopenharmony_ci}
129833d722a9Sopenharmony_ci
129933d722a9Sopenharmony_cifn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
130033d722a9Sopenharmony_ci    let elem = key.rust;
130133d722a9Sopenharmony_ci    let resolve = types.resolve(elem);
130233d722a9Sopenharmony_ci    let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.name.to_symbol());
130333d722a9Sopenharmony_ci    let link_new = format!("{}new", link_prefix);
130433d722a9Sopenharmony_ci    let link_drop = format!("{}drop", link_prefix);
130533d722a9Sopenharmony_ci    let link_len = format!("{}len", link_prefix);
130633d722a9Sopenharmony_ci    let link_capacity = format!("{}capacity", link_prefix);
130733d722a9Sopenharmony_ci    let link_data = format!("{}data", link_prefix);
130833d722a9Sopenharmony_ci    let link_reserve_total = format!("{}reserve_total", link_prefix);
130933d722a9Sopenharmony_ci    let link_set_len = format!("{}set_len", link_prefix);
131033d722a9Sopenharmony_ci    let link_truncate = format!("{}truncate", link_prefix);
131133d722a9Sopenharmony_ci
131233d722a9Sopenharmony_ci    let local_prefix = format_ident!("{}__vec_", elem);
131333d722a9Sopenharmony_ci    let local_new = format_ident!("{}new", local_prefix);
131433d722a9Sopenharmony_ci    let local_drop = format_ident!("{}drop", local_prefix);
131533d722a9Sopenharmony_ci    let local_len = format_ident!("{}len", local_prefix);
131633d722a9Sopenharmony_ci    let local_capacity = format_ident!("{}capacity", local_prefix);
131733d722a9Sopenharmony_ci    let local_data = format_ident!("{}data", local_prefix);
131833d722a9Sopenharmony_ci    let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
131933d722a9Sopenharmony_ci    let local_set_len = format_ident!("{}set_len", local_prefix);
132033d722a9Sopenharmony_ci    let local_truncate = format_ident!("{}truncate", local_prefix);
132133d722a9Sopenharmony_ci
132233d722a9Sopenharmony_ci    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
132333d722a9Sopenharmony_ci
132433d722a9Sopenharmony_ci    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
132533d722a9Sopenharmony_ci    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
132633d722a9Sopenharmony_ci    let unsafe_token = format_ident!("unsafe", span = begin_span);
132733d722a9Sopenharmony_ci    let prevent_unwind_drop_label = format!("::{} as Drop>::drop", elem);
132833d722a9Sopenharmony_ci
132933d722a9Sopenharmony_ci    quote_spanned! {end_span=>
133033d722a9Sopenharmony_ci        #[doc(hidden)]
133133d722a9Sopenharmony_ci        #unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {}
133233d722a9Sopenharmony_ci        #[doc(hidden)]
133333d722a9Sopenharmony_ci        #[export_name = #link_new]
133433d722a9Sopenharmony_ci        unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
133533d722a9Sopenharmony_ci            // No prevent_unwind: cannot panic.
133633d722a9Sopenharmony_ci            ::cxx::core::ptr::write(this, ::cxx::private::RustVec::new());
133733d722a9Sopenharmony_ci        }
133833d722a9Sopenharmony_ci        #[doc(hidden)]
133933d722a9Sopenharmony_ci        #[export_name = #link_drop]
134033d722a9Sopenharmony_ci        unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
134133d722a9Sopenharmony_ci            let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
134233d722a9Sopenharmony_ci            ::cxx::private::prevent_unwind(__fn, || ::cxx::core::ptr::drop_in_place(this));
134333d722a9Sopenharmony_ci        }
134433d722a9Sopenharmony_ci        #[doc(hidden)]
134533d722a9Sopenharmony_ci        #[export_name = #link_len]
134633d722a9Sopenharmony_ci        unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
134733d722a9Sopenharmony_ci            // No prevent_unwind: cannot panic.
134833d722a9Sopenharmony_ci            (*this).len()
134933d722a9Sopenharmony_ci        }
135033d722a9Sopenharmony_ci        #[doc(hidden)]
135133d722a9Sopenharmony_ci        #[export_name = #link_capacity]
135233d722a9Sopenharmony_ci        unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
135333d722a9Sopenharmony_ci            // No prevent_unwind: cannot panic.
135433d722a9Sopenharmony_ci            (*this).capacity()
135533d722a9Sopenharmony_ci        }
135633d722a9Sopenharmony_ci        #[doc(hidden)]
135733d722a9Sopenharmony_ci        #[export_name = #link_data]
135833d722a9Sopenharmony_ci        unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics {
135933d722a9Sopenharmony_ci            // No prevent_unwind: cannot panic.
136033d722a9Sopenharmony_ci            (*this).as_ptr()
136133d722a9Sopenharmony_ci        }
136233d722a9Sopenharmony_ci        #[doc(hidden)]
136333d722a9Sopenharmony_ci        #[export_name = #link_reserve_total]
136433d722a9Sopenharmony_ci        unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, new_cap: usize) {
136533d722a9Sopenharmony_ci            // No prevent_unwind: the global allocator is not allowed to panic.
136633d722a9Sopenharmony_ci            (*this).reserve_total(new_cap);
136733d722a9Sopenharmony_ci        }
136833d722a9Sopenharmony_ci        #[doc(hidden)]
136933d722a9Sopenharmony_ci        #[export_name = #link_set_len]
137033d722a9Sopenharmony_ci        unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
137133d722a9Sopenharmony_ci            // No prevent_unwind: cannot panic.
137233d722a9Sopenharmony_ci            (*this).set_len(len);
137333d722a9Sopenharmony_ci        }
137433d722a9Sopenharmony_ci        #[doc(hidden)]
137533d722a9Sopenharmony_ci        #[export_name = #link_truncate]
137633d722a9Sopenharmony_ci        unsafe extern "C" fn #local_truncate #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
137733d722a9Sopenharmony_ci            let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
137833d722a9Sopenharmony_ci            ::cxx::private::prevent_unwind(__fn, || (*this).truncate(len));
137933d722a9Sopenharmony_ci        }
138033d722a9Sopenharmony_ci    }
138133d722a9Sopenharmony_ci}
138233d722a9Sopenharmony_ci
138333d722a9Sopenharmony_cifn expand_unique_ptr(
138433d722a9Sopenharmony_ci    key: NamedImplKey,
138533d722a9Sopenharmony_ci    types: &Types,
138633d722a9Sopenharmony_ci    explicit_impl: Option<&Impl>,
138733d722a9Sopenharmony_ci) -> TokenStream {
138833d722a9Sopenharmony_ci    let ident = key.rust;
138933d722a9Sopenharmony_ci    let name = ident.to_string();
139033d722a9Sopenharmony_ci    let resolve = types.resolve(ident);
139133d722a9Sopenharmony_ci    let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.name.to_symbol());
139233d722a9Sopenharmony_ci    let link_null = format!("{}null", prefix);
139333d722a9Sopenharmony_ci    let link_uninit = format!("{}uninit", prefix);
139433d722a9Sopenharmony_ci    let link_raw = format!("{}raw", prefix);
139533d722a9Sopenharmony_ci    let link_get = format!("{}get", prefix);
139633d722a9Sopenharmony_ci    let link_release = format!("{}release", prefix);
139733d722a9Sopenharmony_ci    let link_drop = format!("{}drop", prefix);
139833d722a9Sopenharmony_ci
139933d722a9Sopenharmony_ci    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
140033d722a9Sopenharmony_ci
140133d722a9Sopenharmony_ci    let can_construct_from_value = types.is_maybe_trivial(ident);
140233d722a9Sopenharmony_ci    let new_method = if can_construct_from_value {
140333d722a9Sopenharmony_ci        Some(quote! {
140433d722a9Sopenharmony_ci            fn __new(value: Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
140533d722a9Sopenharmony_ci                extern "C" {
140633d722a9Sopenharmony_ci                    #[link_name = #link_uninit]
140733d722a9Sopenharmony_ci                    fn __uninit(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void;
140833d722a9Sopenharmony_ci                }
140933d722a9Sopenharmony_ci                let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
141033d722a9Sopenharmony_ci                unsafe { __uninit(&mut repr).cast::<#ident #ty_generics>().write(value) }
141133d722a9Sopenharmony_ci                repr
141233d722a9Sopenharmony_ci            }
141333d722a9Sopenharmony_ci        })
141433d722a9Sopenharmony_ci    } else {
141533d722a9Sopenharmony_ci        None
141633d722a9Sopenharmony_ci    };
141733d722a9Sopenharmony_ci
141833d722a9Sopenharmony_ci    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
141933d722a9Sopenharmony_ci    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
142033d722a9Sopenharmony_ci    let unsafe_token = format_ident!("unsafe", span = begin_span);
142133d722a9Sopenharmony_ci
142233d722a9Sopenharmony_ci    quote_spanned! {end_span=>
142333d722a9Sopenharmony_ci        #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
142433d722a9Sopenharmony_ci            fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
142533d722a9Sopenharmony_ci                f.write_str(#name)
142633d722a9Sopenharmony_ci            }
142733d722a9Sopenharmony_ci            fn __null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
142833d722a9Sopenharmony_ci                extern "C" {
142933d722a9Sopenharmony_ci                    #[link_name = #link_null]
143033d722a9Sopenharmony_ci                    fn __null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
143133d722a9Sopenharmony_ci                }
143233d722a9Sopenharmony_ci                let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
143333d722a9Sopenharmony_ci                unsafe { __null(&mut repr) }
143433d722a9Sopenharmony_ci                repr
143533d722a9Sopenharmony_ci            }
143633d722a9Sopenharmony_ci            #new_method
143733d722a9Sopenharmony_ci            unsafe fn __raw(raw: *mut Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
143833d722a9Sopenharmony_ci                extern "C" {
143933d722a9Sopenharmony_ci                    #[link_name = #link_raw]
144033d722a9Sopenharmony_ci                    fn __raw(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::core::ffi::c_void);
144133d722a9Sopenharmony_ci                }
144233d722a9Sopenharmony_ci                let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
144333d722a9Sopenharmony_ci                __raw(&mut repr, raw.cast());
144433d722a9Sopenharmony_ci                repr
144533d722a9Sopenharmony_ci            }
144633d722a9Sopenharmony_ci            unsafe fn __get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const Self {
144733d722a9Sopenharmony_ci                extern "C" {
144833d722a9Sopenharmony_ci                    #[link_name = #link_get]
144933d722a9Sopenharmony_ci                    fn __get(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::core::ffi::c_void;
145033d722a9Sopenharmony_ci                }
145133d722a9Sopenharmony_ci                __get(&repr).cast()
145233d722a9Sopenharmony_ci            }
145333d722a9Sopenharmony_ci            unsafe fn __release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut Self {
145433d722a9Sopenharmony_ci                extern "C" {
145533d722a9Sopenharmony_ci                    #[link_name = #link_release]
145633d722a9Sopenharmony_ci                    fn __release(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void;
145733d722a9Sopenharmony_ci                }
145833d722a9Sopenharmony_ci                __release(&mut repr).cast()
145933d722a9Sopenharmony_ci            }
146033d722a9Sopenharmony_ci            unsafe fn __drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) {
146133d722a9Sopenharmony_ci                extern "C" {
146233d722a9Sopenharmony_ci                    #[link_name = #link_drop]
146333d722a9Sopenharmony_ci                    fn __drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
146433d722a9Sopenharmony_ci                }
146533d722a9Sopenharmony_ci                __drop(&mut repr);
146633d722a9Sopenharmony_ci            }
146733d722a9Sopenharmony_ci        }
146833d722a9Sopenharmony_ci    }
146933d722a9Sopenharmony_ci}
147033d722a9Sopenharmony_ci
147133d722a9Sopenharmony_cifn expand_shared_ptr(
147233d722a9Sopenharmony_ci    key: NamedImplKey,
147333d722a9Sopenharmony_ci    types: &Types,
147433d722a9Sopenharmony_ci    explicit_impl: Option<&Impl>,
147533d722a9Sopenharmony_ci) -> TokenStream {
147633d722a9Sopenharmony_ci    let ident = key.rust;
147733d722a9Sopenharmony_ci    let name = ident.to_string();
147833d722a9Sopenharmony_ci    let resolve = types.resolve(ident);
147933d722a9Sopenharmony_ci    let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol());
148033d722a9Sopenharmony_ci    let link_null = format!("{}null", prefix);
148133d722a9Sopenharmony_ci    let link_uninit = format!("{}uninit", prefix);
148233d722a9Sopenharmony_ci    let link_clone = format!("{}clone", prefix);
148333d722a9Sopenharmony_ci    let link_get = format!("{}get", prefix);
148433d722a9Sopenharmony_ci    let link_drop = format!("{}drop", prefix);
148533d722a9Sopenharmony_ci
148633d722a9Sopenharmony_ci    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
148733d722a9Sopenharmony_ci
148833d722a9Sopenharmony_ci    let can_construct_from_value = types.is_maybe_trivial(ident);
148933d722a9Sopenharmony_ci    let new_method = if can_construct_from_value {
149033d722a9Sopenharmony_ci        Some(quote! {
149133d722a9Sopenharmony_ci            unsafe fn __new(value: Self, new: *mut ::cxx::core::ffi::c_void) {
149233d722a9Sopenharmony_ci                extern "C" {
149333d722a9Sopenharmony_ci                    #[link_name = #link_uninit]
149433d722a9Sopenharmony_ci                    fn __uninit(new: *mut ::cxx::core::ffi::c_void) -> *mut ::cxx::core::ffi::c_void;
149533d722a9Sopenharmony_ci                }
149633d722a9Sopenharmony_ci                __uninit(new).cast::<#ident #ty_generics>().write(value);
149733d722a9Sopenharmony_ci            }
149833d722a9Sopenharmony_ci        })
149933d722a9Sopenharmony_ci    } else {
150033d722a9Sopenharmony_ci        None
150133d722a9Sopenharmony_ci    };
150233d722a9Sopenharmony_ci
150333d722a9Sopenharmony_ci    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
150433d722a9Sopenharmony_ci    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
150533d722a9Sopenharmony_ci    let unsafe_token = format_ident!("unsafe", span = begin_span);
150633d722a9Sopenharmony_ci
150733d722a9Sopenharmony_ci    quote_spanned! {end_span=>
150833d722a9Sopenharmony_ci        #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
150933d722a9Sopenharmony_ci            fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
151033d722a9Sopenharmony_ci                f.write_str(#name)
151133d722a9Sopenharmony_ci            }
151233d722a9Sopenharmony_ci            unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) {
151333d722a9Sopenharmony_ci                extern "C" {
151433d722a9Sopenharmony_ci                    #[link_name = #link_null]
151533d722a9Sopenharmony_ci                    fn __null(new: *mut ::cxx::core::ffi::c_void);
151633d722a9Sopenharmony_ci                }
151733d722a9Sopenharmony_ci                __null(new);
151833d722a9Sopenharmony_ci            }
151933d722a9Sopenharmony_ci            #new_method
152033d722a9Sopenharmony_ci            unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
152133d722a9Sopenharmony_ci                extern "C" {
152233d722a9Sopenharmony_ci                    #[link_name = #link_clone]
152333d722a9Sopenharmony_ci                    fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void);
152433d722a9Sopenharmony_ci                }
152533d722a9Sopenharmony_ci                __clone(this, new);
152633d722a9Sopenharmony_ci            }
152733d722a9Sopenharmony_ci            unsafe fn __get(this: *const ::cxx::core::ffi::c_void) -> *const Self {
152833d722a9Sopenharmony_ci                extern "C" {
152933d722a9Sopenharmony_ci                    #[link_name = #link_get]
153033d722a9Sopenharmony_ci                    fn __get(this: *const ::cxx::core::ffi::c_void) -> *const ::cxx::core::ffi::c_void;
153133d722a9Sopenharmony_ci                }
153233d722a9Sopenharmony_ci                __get(this).cast()
153333d722a9Sopenharmony_ci            }
153433d722a9Sopenharmony_ci            unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) {
153533d722a9Sopenharmony_ci                extern "C" {
153633d722a9Sopenharmony_ci                    #[link_name = #link_drop]
153733d722a9Sopenharmony_ci                    fn __drop(this: *mut ::cxx::core::ffi::c_void);
153833d722a9Sopenharmony_ci                }
153933d722a9Sopenharmony_ci                __drop(this);
154033d722a9Sopenharmony_ci            }
154133d722a9Sopenharmony_ci        }
154233d722a9Sopenharmony_ci    }
154333d722a9Sopenharmony_ci}
154433d722a9Sopenharmony_ci
154533d722a9Sopenharmony_cifn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
154633d722a9Sopenharmony_ci    let ident = key.rust;
154733d722a9Sopenharmony_ci    let name = ident.to_string();
154833d722a9Sopenharmony_ci    let resolve = types.resolve(ident);
154933d722a9Sopenharmony_ci    let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.name.to_symbol());
155033d722a9Sopenharmony_ci    let link_null = format!("{}null", prefix);
155133d722a9Sopenharmony_ci    let link_clone = format!("{}clone", prefix);
155233d722a9Sopenharmony_ci    let link_downgrade = format!("{}downgrade", prefix);
155333d722a9Sopenharmony_ci    let link_upgrade = format!("{}upgrade", prefix);
155433d722a9Sopenharmony_ci    let link_drop = format!("{}drop", prefix);
155533d722a9Sopenharmony_ci
155633d722a9Sopenharmony_ci    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
155733d722a9Sopenharmony_ci
155833d722a9Sopenharmony_ci    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
155933d722a9Sopenharmony_ci    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
156033d722a9Sopenharmony_ci    let unsafe_token = format_ident!("unsafe", span = begin_span);
156133d722a9Sopenharmony_ci
156233d722a9Sopenharmony_ci    quote_spanned! {end_span=>
156333d722a9Sopenharmony_ci        #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
156433d722a9Sopenharmony_ci            fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
156533d722a9Sopenharmony_ci                f.write_str(#name)
156633d722a9Sopenharmony_ci            }
156733d722a9Sopenharmony_ci            unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) {
156833d722a9Sopenharmony_ci                extern "C" {
156933d722a9Sopenharmony_ci                    #[link_name = #link_null]
157033d722a9Sopenharmony_ci                    fn __null(new: *mut ::cxx::core::ffi::c_void);
157133d722a9Sopenharmony_ci                }
157233d722a9Sopenharmony_ci                __null(new);
157333d722a9Sopenharmony_ci            }
157433d722a9Sopenharmony_ci            unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
157533d722a9Sopenharmony_ci                extern "C" {
157633d722a9Sopenharmony_ci                    #[link_name = #link_clone]
157733d722a9Sopenharmony_ci                    fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void);
157833d722a9Sopenharmony_ci                }
157933d722a9Sopenharmony_ci                __clone(this, new);
158033d722a9Sopenharmony_ci            }
158133d722a9Sopenharmony_ci            unsafe fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void) {
158233d722a9Sopenharmony_ci                extern "C" {
158333d722a9Sopenharmony_ci                    #[link_name = #link_downgrade]
158433d722a9Sopenharmony_ci                    fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void);
158533d722a9Sopenharmony_ci                }
158633d722a9Sopenharmony_ci                __downgrade(shared, weak);
158733d722a9Sopenharmony_ci            }
158833d722a9Sopenharmony_ci            unsafe fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void) {
158933d722a9Sopenharmony_ci                extern "C" {
159033d722a9Sopenharmony_ci                    #[link_name = #link_upgrade]
159133d722a9Sopenharmony_ci                    fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void);
159233d722a9Sopenharmony_ci                }
159333d722a9Sopenharmony_ci                __upgrade(weak, shared);
159433d722a9Sopenharmony_ci            }
159533d722a9Sopenharmony_ci            unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) {
159633d722a9Sopenharmony_ci                extern "C" {
159733d722a9Sopenharmony_ci                    #[link_name = #link_drop]
159833d722a9Sopenharmony_ci                    fn __drop(this: *mut ::cxx::core::ffi::c_void);
159933d722a9Sopenharmony_ci                }
160033d722a9Sopenharmony_ci                __drop(this);
160133d722a9Sopenharmony_ci            }
160233d722a9Sopenharmony_ci        }
160333d722a9Sopenharmony_ci    }
160433d722a9Sopenharmony_ci}
160533d722a9Sopenharmony_ci
160633d722a9Sopenharmony_cifn expand_cxx_vector(
160733d722a9Sopenharmony_ci    key: NamedImplKey,
160833d722a9Sopenharmony_ci    explicit_impl: Option<&Impl>,
160933d722a9Sopenharmony_ci    types: &Types,
161033d722a9Sopenharmony_ci) -> TokenStream {
161133d722a9Sopenharmony_ci    let elem = key.rust;
161233d722a9Sopenharmony_ci    let name = elem.to_string();
161333d722a9Sopenharmony_ci    let resolve = types.resolve(elem);
161433d722a9Sopenharmony_ci    let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
161533d722a9Sopenharmony_ci    let link_size = format!("{}size", prefix);
161633d722a9Sopenharmony_ci    let link_get_unchecked = format!("{}get_unchecked", prefix);
161733d722a9Sopenharmony_ci    let link_push_back = format!("{}push_back", prefix);
161833d722a9Sopenharmony_ci    let link_pop_back = format!("{}pop_back", prefix);
161933d722a9Sopenharmony_ci    let unique_ptr_prefix = format!(
162033d722a9Sopenharmony_ci        "cxxbridge1$unique_ptr$std$vector${}$",
162133d722a9Sopenharmony_ci        resolve.name.to_symbol(),
162233d722a9Sopenharmony_ci    );
162333d722a9Sopenharmony_ci    let link_unique_ptr_null = format!("{}null", unique_ptr_prefix);
162433d722a9Sopenharmony_ci    let link_unique_ptr_raw = format!("{}raw", unique_ptr_prefix);
162533d722a9Sopenharmony_ci    let link_unique_ptr_get = format!("{}get", unique_ptr_prefix);
162633d722a9Sopenharmony_ci    let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
162733d722a9Sopenharmony_ci    let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
162833d722a9Sopenharmony_ci
162933d722a9Sopenharmony_ci    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
163033d722a9Sopenharmony_ci
163133d722a9Sopenharmony_ci    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
163233d722a9Sopenharmony_ci    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
163333d722a9Sopenharmony_ci    let unsafe_token = format_ident!("unsafe", span = begin_span);
163433d722a9Sopenharmony_ci
163533d722a9Sopenharmony_ci    let can_pass_element_by_value = types.is_maybe_trivial(elem);
163633d722a9Sopenharmony_ci    let by_value_methods = if can_pass_element_by_value {
163733d722a9Sopenharmony_ci        Some(quote_spanned! {end_span=>
163833d722a9Sopenharmony_ci            unsafe fn __push_back(
163933d722a9Sopenharmony_ci                this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
164033d722a9Sopenharmony_ci                value: &mut ::cxx::core::mem::ManuallyDrop<Self>,
164133d722a9Sopenharmony_ci            ) {
164233d722a9Sopenharmony_ci                extern "C" {
164333d722a9Sopenharmony_ci                    #[link_name = #link_push_back]
164433d722a9Sopenharmony_ci                    fn __push_back #impl_generics(
164533d722a9Sopenharmony_ci                        this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
164633d722a9Sopenharmony_ci                        value: *mut ::cxx::core::ffi::c_void,
164733d722a9Sopenharmony_ci                    );
164833d722a9Sopenharmony_ci                }
164933d722a9Sopenharmony_ci                __push_back(this, value as *mut ::cxx::core::mem::ManuallyDrop<Self> as *mut ::cxx::core::ffi::c_void);
165033d722a9Sopenharmony_ci            }
165133d722a9Sopenharmony_ci            unsafe fn __pop_back(
165233d722a9Sopenharmony_ci                this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
165333d722a9Sopenharmony_ci                out: &mut ::cxx::core::mem::MaybeUninit<Self>,
165433d722a9Sopenharmony_ci            ) {
165533d722a9Sopenharmony_ci                extern "C" {
165633d722a9Sopenharmony_ci                    #[link_name = #link_pop_back]
165733d722a9Sopenharmony_ci                    fn __pop_back #impl_generics(
165833d722a9Sopenharmony_ci                        this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
165933d722a9Sopenharmony_ci                        out: *mut ::cxx::core::ffi::c_void,
166033d722a9Sopenharmony_ci                    );
166133d722a9Sopenharmony_ci                }
166233d722a9Sopenharmony_ci                __pop_back(this, out as *mut ::cxx::core::mem::MaybeUninit<Self> as *mut ::cxx::core::ffi::c_void);
166333d722a9Sopenharmony_ci            }
166433d722a9Sopenharmony_ci        })
166533d722a9Sopenharmony_ci    } else {
166633d722a9Sopenharmony_ci        None
166733d722a9Sopenharmony_ci    };
166833d722a9Sopenharmony_ci
166933d722a9Sopenharmony_ci    quote_spanned! {end_span=>
167033d722a9Sopenharmony_ci        #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
167133d722a9Sopenharmony_ci            fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
167233d722a9Sopenharmony_ci                f.write_str(#name)
167333d722a9Sopenharmony_ci            }
167433d722a9Sopenharmony_ci            fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
167533d722a9Sopenharmony_ci                extern "C" {
167633d722a9Sopenharmony_ci                    #[link_name = #link_size]
167733d722a9Sopenharmony_ci                    fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
167833d722a9Sopenharmony_ci                }
167933d722a9Sopenharmony_ci                unsafe { __vector_size(v) }
168033d722a9Sopenharmony_ci            }
168133d722a9Sopenharmony_ci            unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
168233d722a9Sopenharmony_ci                extern "C" {
168333d722a9Sopenharmony_ci                    #[link_name = #link_get_unchecked]
168433d722a9Sopenharmony_ci                    fn __get_unchecked #impl_generics(
168533d722a9Sopenharmony_ci                        v: *mut ::cxx::CxxVector<#elem #ty_generics>,
168633d722a9Sopenharmony_ci                        pos: usize,
168733d722a9Sopenharmony_ci                    ) -> *mut ::cxx::core::ffi::c_void;
168833d722a9Sopenharmony_ci                }
168933d722a9Sopenharmony_ci                __get_unchecked(v, pos) as *mut Self
169033d722a9Sopenharmony_ci            }
169133d722a9Sopenharmony_ci            #by_value_methods
169233d722a9Sopenharmony_ci            fn __unique_ptr_null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
169333d722a9Sopenharmony_ci                extern "C" {
169433d722a9Sopenharmony_ci                    #[link_name = #link_unique_ptr_null]
169533d722a9Sopenharmony_ci                    fn __unique_ptr_null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
169633d722a9Sopenharmony_ci                }
169733d722a9Sopenharmony_ci                let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
169833d722a9Sopenharmony_ci                unsafe { __unique_ptr_null(&mut repr) }
169933d722a9Sopenharmony_ci                repr
170033d722a9Sopenharmony_ci            }
170133d722a9Sopenharmony_ci            unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
170233d722a9Sopenharmony_ci                extern "C" {
170333d722a9Sopenharmony_ci                    #[link_name = #link_unique_ptr_raw]
170433d722a9Sopenharmony_ci                    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>);
170533d722a9Sopenharmony_ci                }
170633d722a9Sopenharmony_ci                let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
170733d722a9Sopenharmony_ci                __unique_ptr_raw(&mut repr, raw);
170833d722a9Sopenharmony_ci                repr
170933d722a9Sopenharmony_ci            }
171033d722a9Sopenharmony_ci            unsafe fn __unique_ptr_get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<Self> {
171133d722a9Sopenharmony_ci                extern "C" {
171233d722a9Sopenharmony_ci                    #[link_name = #link_unique_ptr_get]
171333d722a9Sopenharmony_ci                    fn __unique_ptr_get #impl_generics(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<#elem #ty_generics>;
171433d722a9Sopenharmony_ci                }
171533d722a9Sopenharmony_ci                __unique_ptr_get(&repr)
171633d722a9Sopenharmony_ci            }
171733d722a9Sopenharmony_ci            unsafe fn __unique_ptr_release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<Self> {
171833d722a9Sopenharmony_ci                extern "C" {
171933d722a9Sopenharmony_ci                    #[link_name = #link_unique_ptr_release]
172033d722a9Sopenharmony_ci                    fn __unique_ptr_release #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
172133d722a9Sopenharmony_ci                }
172233d722a9Sopenharmony_ci                __unique_ptr_release(&mut repr)
172333d722a9Sopenharmony_ci            }
172433d722a9Sopenharmony_ci            unsafe fn __unique_ptr_drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) {
172533d722a9Sopenharmony_ci                extern "C" {
172633d722a9Sopenharmony_ci                    #[link_name = #link_unique_ptr_drop]
172733d722a9Sopenharmony_ci                    fn __unique_ptr_drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
172833d722a9Sopenharmony_ci                }
172933d722a9Sopenharmony_ci                __unique_ptr_drop(&mut repr);
173033d722a9Sopenharmony_ci            }
173133d722a9Sopenharmony_ci        }
173233d722a9Sopenharmony_ci    }
173333d722a9Sopenharmony_ci}
173433d722a9Sopenharmony_ci
173533d722a9Sopenharmony_cifn expand_return_type(ret: &Option<Type>) -> TokenStream {
173633d722a9Sopenharmony_ci    match ret {
173733d722a9Sopenharmony_ci        Some(ret) => quote!(-> #ret),
173833d722a9Sopenharmony_ci        None => TokenStream::new(),
173933d722a9Sopenharmony_ci    }
174033d722a9Sopenharmony_ci}
174133d722a9Sopenharmony_ci
174233d722a9Sopenharmony_cifn indirect_return(sig: &Signature, types: &Types) -> bool {
174333d722a9Sopenharmony_ci    sig.ret
174433d722a9Sopenharmony_ci        .as_ref()
174533d722a9Sopenharmony_ci        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
174633d722a9Sopenharmony_ci}
174733d722a9Sopenharmony_ci
174833d722a9Sopenharmony_cifn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
174933d722a9Sopenharmony_ci    match ty {
175033d722a9Sopenharmony_ci        Type::Ident(ident) if ident.rust == RustString => {
175133d722a9Sopenharmony_ci            let span = ident.rust.span();
175233d722a9Sopenharmony_ci            quote_spanned!(span=> ::cxx::private::RustString)
175333d722a9Sopenharmony_ci        }
175433d722a9Sopenharmony_ci        Type::RustBox(ty) | Type::UniquePtr(ty) => {
175533d722a9Sopenharmony_ci            let span = ty.name.span();
175633d722a9Sopenharmony_ci            if proper && types.is_considered_improper_ctype(&ty.inner) {
175733d722a9Sopenharmony_ci                quote_spanned!(span=> *mut ::cxx::core::ffi::c_void)
175833d722a9Sopenharmony_ci            } else {
175933d722a9Sopenharmony_ci                let inner = expand_extern_type(&ty.inner, types, proper);
176033d722a9Sopenharmony_ci                quote_spanned!(span=> *mut #inner)
176133d722a9Sopenharmony_ci            }
176233d722a9Sopenharmony_ci        }
176333d722a9Sopenharmony_ci        Type::RustVec(ty) => {
176433d722a9Sopenharmony_ci            let span = ty.name.span();
176533d722a9Sopenharmony_ci            let langle = ty.langle;
176633d722a9Sopenharmony_ci            let elem = expand_extern_type(&ty.inner, types, proper);
176733d722a9Sopenharmony_ci            let rangle = ty.rangle;
176833d722a9Sopenharmony_ci            quote_spanned!(span=> ::cxx::private::RustVec #langle #elem #rangle)
176933d722a9Sopenharmony_ci        }
177033d722a9Sopenharmony_ci        Type::Ref(ty) => {
177133d722a9Sopenharmony_ci            let ampersand = ty.ampersand;
177233d722a9Sopenharmony_ci            let lifetime = &ty.lifetime;
177333d722a9Sopenharmony_ci            let mutability = ty.mutability;
177433d722a9Sopenharmony_ci            match &ty.inner {
177533d722a9Sopenharmony_ci                Type::Ident(ident) if ident.rust == RustString => {
177633d722a9Sopenharmony_ci                    let span = ident.rust.span();
177733d722a9Sopenharmony_ci                    quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustString)
177833d722a9Sopenharmony_ci                }
177933d722a9Sopenharmony_ci                Type::RustVec(ty) => {
178033d722a9Sopenharmony_ci                    let span = ty.name.span();
178133d722a9Sopenharmony_ci                    let langle = ty.langle;
178233d722a9Sopenharmony_ci                    let inner = expand_extern_type(&ty.inner, types, proper);
178333d722a9Sopenharmony_ci                    let rangle = ty.rangle;
178433d722a9Sopenharmony_ci                    quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustVec #langle #inner #rangle)
178533d722a9Sopenharmony_ci                }
178633d722a9Sopenharmony_ci                inner if proper && types.is_considered_improper_ctype(inner) => {
178733d722a9Sopenharmony_ci                    let star = Token![*](ampersand.span);
178833d722a9Sopenharmony_ci                    match ty.mutable {
178933d722a9Sopenharmony_ci                        false => quote!(#star const ::cxx::core::ffi::c_void),
179033d722a9Sopenharmony_ci                        true => quote!(#star #mutability ::cxx::core::ffi::c_void),
179133d722a9Sopenharmony_ci                    }
179233d722a9Sopenharmony_ci                }
179333d722a9Sopenharmony_ci                _ => quote!(#ty),
179433d722a9Sopenharmony_ci            }
179533d722a9Sopenharmony_ci        }
179633d722a9Sopenharmony_ci        Type::Ptr(ty) => {
179733d722a9Sopenharmony_ci            if proper && types.is_considered_improper_ctype(&ty.inner) {
179833d722a9Sopenharmony_ci                let star = ty.star;
179933d722a9Sopenharmony_ci                let mutability = ty.mutability;
180033d722a9Sopenharmony_ci                let constness = ty.constness;
180133d722a9Sopenharmony_ci                quote!(#star #mutability #constness ::cxx::core::ffi::c_void)
180233d722a9Sopenharmony_ci            } else {
180333d722a9Sopenharmony_ci                quote!(#ty)
180433d722a9Sopenharmony_ci            }
180533d722a9Sopenharmony_ci        }
180633d722a9Sopenharmony_ci        Type::Str(ty) => {
180733d722a9Sopenharmony_ci            let span = ty.ampersand.span;
180833d722a9Sopenharmony_ci            let rust_str = Ident::new("RustStr", syn::spanned::Spanned::span(&ty.inner));
180933d722a9Sopenharmony_ci            quote_spanned!(span=> ::cxx::private::#rust_str)
181033d722a9Sopenharmony_ci        }
181133d722a9Sopenharmony_ci        Type::SliceRef(ty) => {
181233d722a9Sopenharmony_ci            let span = ty.ampersand.span;
181333d722a9Sopenharmony_ci            let rust_slice = Ident::new("RustSlice", ty.bracket.span.join());
181433d722a9Sopenharmony_ci            quote_spanned!(span=> ::cxx::private::#rust_slice)
181533d722a9Sopenharmony_ci        }
181633d722a9Sopenharmony_ci        _ => quote!(#ty),
181733d722a9Sopenharmony_ci    }
181833d722a9Sopenharmony_ci}
181933d722a9Sopenharmony_ci
182033d722a9Sopenharmony_cifn expand_extern_return_type(ret: &Option<Type>, types: &Types, proper: bool) -> TokenStream {
182133d722a9Sopenharmony_ci    let ret = match ret {
182233d722a9Sopenharmony_ci        Some(ret) if !types.needs_indirect_abi(ret) => ret,
182333d722a9Sopenharmony_ci        _ => return TokenStream::new(),
182433d722a9Sopenharmony_ci    };
182533d722a9Sopenharmony_ci    let ty = expand_extern_type(ret, types, proper);
182633d722a9Sopenharmony_ci    quote!(-> #ty)
182733d722a9Sopenharmony_ci}
1828