Skip to main content

cxx_gen/bridge/
write.rs

1use crate::bridge::block::Block;
2use crate::bridge::guard::Guard;
3use crate::bridge::nested::NamespaceEntries;
4use crate::bridge::out::{InfallibleWrite, OutFile};
5use crate::bridge::{Opt, builtin, include, pragma};
6use crate::syntax::atom::Atom::{self, *};
7use crate::syntax::discriminant::{Discriminant, Limits};
8use crate::syntax::instantiate::{ImplKey, NamedImplKey};
9use crate::syntax::map::UnorderedMap as Map;
10use crate::syntax::namespace::Namespace;
11use crate::syntax::primitive::{self, PrimitiveKind};
12use crate::syntax::set::UnorderedSet;
13use crate::syntax::symbol::Symbol;
14use crate::syntax::trivial::{self, TrivialReason};
15use crate::syntax::{
16    Api, Doc, Enum, ExternFn, ExternType, FnKind, Lang, Pair, Signature, Struct, Trait, Type,
17    TypeAlias, Types, Var, derive, mangle,
18};
19
20pub(super) fn generate(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u8> {
21    let mut out_file = OutFile::new(header, opt, types);
22    let out = &mut out_file;
23
24    pick_includes_and_builtins(out, apis);
25    out.include.extend(&opt.include);
26
27    write_macros(out, apis);
28    write_forward_declarations(out, apis);
29    write_data_structures(out, apis);
30    write_functions(out, apis);
31    write_generic_instantiations(out);
32
33    builtin::write(out);
34    pragma::write(out);
35    include::write(out);
36
37    out_file.content()
38}
39
40fn write_macros(out: &mut OutFile, apis: &[Api]) {
41    let mut needs_default_value = false;
42    for api in apis {
43        if let Api::Struct(strct) = api
44            && !out.types.cxx.contains(&strct.name.rust)
45        {
46            for field in &strct.fields {
47                needs_default_value |= primitive::kind(&field.ty).is_some();
48            }
49        }
50    }
51
52    if needs_default_value {
53        out.next_section();
54        out.write_fmt(format_args!("#if __cplusplus >= 201402L\n"));writeln!(out, "#if __cplusplus >= 201402L");
55        out.write_fmt(format_args!("#define CXX_DEFAULT_VALUE(value) = value\n"));writeln!(out, "#define CXX_DEFAULT_VALUE(value) = value");
56        out.write_fmt(format_args!("#else\n"));writeln!(out, "#else");
57        out.write_fmt(format_args!("#define CXX_DEFAULT_VALUE(value)\n"));writeln!(out, "#define CXX_DEFAULT_VALUE(value)");
58        out.write_fmt(format_args!("#endif\n"));writeln!(out, "#endif");
59    }
60}
61
62fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
63    let needs_forward_declaration = |api: &&Api| match api {
64        Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true,
65        Api::Enum(enm) => !out.types.cxx.contains(&enm.name.rust),
66        _ => false,
67    };
68
69    let apis_by_namespace =
70        NamespaceEntries::new(apis.iter().filter(needs_forward_declaration).collect());
71
72    out.next_section();
73    write(out, &apis_by_namespace, 0);
74
75    fn write(out: &mut OutFile, ns_entries: &NamespaceEntries, indent: usize) {
76        let apis = ns_entries.direct_content();
77
78        for api in apis {
79            out.write_fmt(format_args!("{0:1$}", "", indent));write!(out, "{:1$}", "", indent);
80            match api {
81                Api::Struct(strct) => write_struct_decl(out, &strct.name),
82                Api::Enum(enm) => write_enum_decl(out, enm),
83                Api::CxxType(ety) => write_struct_using(out, &ety.name),
84                Api::RustType(ety) => write_struct_decl(out, &ety.name),
85                _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
86            }
87        }
88
89        for (namespace, nested_ns_entries) in ns_entries.nested_content() {
90            out.write_fmt(format_args!("{0:2$}namespace {1} {{\n", "", namespace,
        indent));writeln!(out, "{:2$}namespace {} {{", "", namespace, indent);
91            write(out, nested_ns_entries, indent + 2);
92            out.write_fmt(format_args!("{0:1$}}}\n", "", indent));writeln!(out, "{:1$}}}", "", indent);
93        }
94    }
95}
96
97fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
98    let mut methods_for_type = Map::new();
99    for api in apis {
100        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api
101            && let Some(self_type) = efn.self_type()
102        {
103            methods_for_type
104                .entry(self_type)
105                .or_insert_with(Vec::new)
106                .push(efn);
107        }
108    }
109
110    let mut structs_written = UnorderedSet::new();
111    let mut toposorted_structs = out.types.toposorted_structs.iter();
112    for api in apis {
113        match api {
114            Api::Struct(strct) if !structs_written.contains(&strct.name.rust) => {
115                for next in &mut toposorted_structs {
116                    if !out.types.cxx.contains(&next.name.rust) {
117                        out.next_section();
118                        let methods = methods_for_type
119                            .get(&next.name.rust)
120                            .map(Vec::as_slice)
121                            .unwrap_or_default();
122                        write_struct(out, next, methods);
123                    }
124                    structs_written.insert(&next.name.rust);
125                    if next.name.rust == strct.name.rust {
126                        break;
127                    }
128                }
129            }
130            Api::Enum(enm) => {
131                out.next_section();
132                if out.types.cxx.contains(&enm.name.rust) {
133                    check_enum(out, enm);
134                } else {
135                    write_enum(out, enm);
136                }
137            }
138            Api::RustType(ety) => {
139                out.next_section();
140                let methods = methods_for_type
141                    .get(&ety.name.rust)
142                    .map(Vec::as_slice)
143                    .unwrap_or_default();
144                write_opaque_type(out, ety, methods);
145            }
146            _ => {}
147        }
148    }
149
150    if out.header {
151        return;
152    }
153
154    out.set_namespace(Default::default());
155
156    out.next_section();
157    for api in apis {
158        if let Api::TypeAlias(ety) = api
159            && let Some(reasons) = out.types.required_trivial.get(&ety.name.rust)
160        {
161            check_trivial_extern_type(out, ety, reasons);
162        }
163    }
164}
165
166fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
167    if !out.header {
168        for api in apis {
169            match api {
170                Api::Struct(strct) => write_struct_operator_decls(out, strct),
171                Api::RustType(ety) => write_opaque_type_layout_decls(out, ety),
172                Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
173                Api::RustFunction(efn) => write_rust_function_decl(out, efn),
174                _ => {}
175            }
176        }
177
178        write_std_specializations(out, apis);
179    }
180
181    for api in apis {
182        match api {
183            Api::Struct(strct) => write_struct_operators(out, strct),
184            Api::RustType(ety) => write_opaque_type_layout(out, ety),
185            Api::RustFunction(efn) => {
186                out.next_section();
187                write_rust_function_shim(out, efn);
188            }
189            _ => {}
190        }
191    }
192}
193
194fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
195    out.set_namespace(Default::default());
196    out.begin_block(Block::Namespace("std"));
197
198    for api in apis {
199        if let Api::Struct(strct) = api
200            && derive::contains(&strct.derives, Trait::Hash)
201        {
202            out.next_section();
203            out.include.cstddef = true;
204            out.include.functional = true;
205            out.pragma.dollar_in_identifier = true;
206            let qualified = strct.name.to_fully_qualified();
207            out.write_fmt(format_args!("template <> struct hash<{0}> {{\n", qualified));writeln!(out, "template <> struct hash<{}> {{", qualified);
208            out.write_fmt(format_args!("  ::std::size_t operator()({0} const &self) const noexcept {{\n",
        qualified));writeln!(
209                out,
210                "  ::std::size_t operator()({} const &self) const noexcept {{",
211                qualified,
212            );
213            let link_name = mangle::operator(&strct.name, "hash");
214            out.write_fmt(format_args!("    return ::"));write!(out, "    return ::");
215            for name in &strct.name.namespace {
216                out.write_fmt(format_args!("{0}::", name));write!(out, "{}::", name);
217            }
218            out.write_fmt(format_args!("{0}(self);\n", link_name));writeln!(out, "{}(self);", link_name);
219            out.write_fmt(format_args!("  }}\n"));writeln!(out, "  }}");
220            out.write_fmt(format_args!("}};\n"));writeln!(out, "}};");
221        }
222    }
223
224    out.end_block(Block::Namespace("std"));
225}
226
227fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
228    for api in apis {
229        if let Api::Include(include) = api {
230            out.include.insert(include);
231        }
232    }
233
234    for ty in out.types {
235        match ty {
236            Type::Ident(ident) => match Atom::from(&ident.rust) {
237                Some(U8 | U16 | U32 | U64 | I8 | I16 | I32 | I64) => out.include.cstdint = true,
238                Some(Usize) => out.include.cstddef = true,
239                Some(Isize) => out.builtin.rust_isize = true,
240                Some(CxxString) => out.include.string = true,
241                Some(RustString) => out.builtin.rust_string = true,
242                Some(Bool | Char | F32 | F64) | None => {}
243            },
244            Type::RustBox(_) => out.builtin.rust_box = true,
245            Type::RustVec(_) => out.builtin.rust_vec = true,
246            Type::UniquePtr(_) => out.include.memory = true,
247            Type::SharedPtr(_) | Type::WeakPtr(_) => out.include.memory = true,
248            Type::Str(_) => out.builtin.rust_str = true,
249            Type::CxxVector(_) => out.include.vector = true,
250            Type::Fn(_) => out.builtin.rust_fn = true,
251            Type::SliceRef(_) => out.builtin.rust_slice = true,
252            Type::Array(_) => out.include.array = true,
253            Type::Ref(_) | Type::Void(_) | Type::Ptr(_) => {}
254        }
255    }
256}
257
258fn write_doc(out: &mut OutFile, indent: &str, doc: &Doc) {
259    let mut lines = 0;
260    for line in doc.to_string().lines() {
261        if out.opt.doxygen {
262            out.write_fmt(format_args!("{0}///{1}\n", indent, line));writeln!(out, "{}///{}", indent, line);
263        } else {
264            out.write_fmt(format_args!("{0}//{1}\n", indent, line));writeln!(out, "{}//{}", indent, line);
265        }
266        lines += 1;
267    }
268    // According to https://www.doxygen.nl/manual/docblocks.html, Doxygen only
269    // interprets `///` as a Doxygen comment block if there are at least 2 of
270    // them. In Rust, a single `///` is definitely still documentation so we
271    // make sure to propagate that as a Doxygen comment.
272    if out.opt.doxygen && lines == 1 {
273        out.write_fmt(format_args!("{0}///\n", indent));writeln!(out, "{}///", indent);
274    }
275}
276
277fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
278    let operator_eq = derive::contains(&strct.derives, Trait::PartialEq);
279    let operator_ord = derive::contains(&strct.derives, Trait::PartialOrd);
280
281    out.set_namespace(&strct.name.namespace);
282    let guard = Guard::new(out, "CXXBRIDGE1_STRUCT", &strct.name);
283    out.write_fmt(format_args!("#ifndef {0}\n", guard));writeln!(out, "#ifndef {}", guard);
284    out.write_fmt(format_args!("#define {0}\n", guard));writeln!(out, "#define {}", guard);
285    write_doc(out, "", &strct.doc);
286    out.write_fmt(format_args!("struct"));write!(out, "struct");
287    if let Some(align) = &strct.align {
288        out.builtin.alignmax = true;
289        out.write_fmt(format_args!(" alignas(::rust::repr::alignmax<\n"));writeln!(out, " alignas(::rust::repr::alignmax<");
290        out.write_fmt(format_args!("  {0},\n", align.base10_parse::<u32>().unwrap()));writeln!(out, "  {},", align.base10_parse::<u32>().unwrap());
291        for (i, field) in strct.fields.iter().enumerate() {
292            out.write_fmt(format_args!("  alignof("));write!(out, "  alignof(");
293            write_type(out, &field.ty);
294            out.write_fmt(format_args!(")"));write!(out, ")");
295            if i + 1 != strct.fields.len() {
296                out.write_fmt(format_args!(","));write!(out, ",");
297            }
298            out.write_fmt(format_args!("\n"));writeln!(out);
299        }
300        out.write_fmt(format_args!(">)"));write!(out, ">)");
301    }
302    out.write_fmt(format_args!(" {0} final {{\n", strct.name.cxx));writeln!(out, " {} final {{", strct.name.cxx);
303
304    for field in &strct.fields {
305        write_doc(out, "  ", &field.doc);
306        out.write_fmt(format_args!("  "));write!(out, "  ");
307        write_type_space(out, &field.ty);
308        out.write_fmt(format_args!("{0}", field.name.cxx));write!(out, "{}", field.name.cxx);
309        if let Some(primitive) = primitive::kind(&field.ty) {
310            let default_value = match primitive {
311                PrimitiveKind::Boolean => "false",
312                PrimitiveKind::Number => "0",
313                PrimitiveKind::Pointer => "nullptr",
314            };
315            out.write_fmt(format_args!(" CXX_DEFAULT_VALUE({0})", default_value));write!(out, " CXX_DEFAULT_VALUE({})", default_value);
316        }
317        out.write_fmt(format_args!(";\n"));writeln!(out, ";");
318    }
319
320    out.next_section();
321
322    for method in methods {
323        if !method.doc.is_empty() {
324            out.next_section();
325        }
326        write_doc(out, "  ", &method.doc);
327        out.write_fmt(format_args!("  "));write!(out, "  ");
328        let local_name = method.name.cxx.to_string();
329        let sig = &method.sig;
330        let in_class = true;
331        let indirect_call = false;
332        let main = false;
333        write_rust_function_shim_decl(out, &local_name, sig, in_class, indirect_call, main);
334        out.write_fmt(format_args!(";\n"));writeln!(out, ";");
335        if !method.doc.is_empty() {
336            out.next_section();
337        }
338    }
339
340    if operator_eq {
341        out.write_fmt(format_args!("  bool operator==({0} const &) const noexcept;\n",
        strct.name.cxx));writeln!(
342            out,
343            "  bool operator==({} const &) const noexcept;",
344            strct.name.cxx,
345        );
346        out.write_fmt(format_args!("  bool operator!=({0} const &) const noexcept;\n",
        strct.name.cxx));writeln!(
347            out,
348            "  bool operator!=({} const &) const noexcept;",
349            strct.name.cxx,
350        );
351    }
352
353    if operator_ord {
354        out.write_fmt(format_args!("  bool operator<({0} const &) const noexcept;\n",
        strct.name.cxx));writeln!(
355            out,
356            "  bool operator<({} const &) const noexcept;",
357            strct.name.cxx,
358        );
359        out.write_fmt(format_args!("  bool operator<=({0} const &) const noexcept;\n",
        strct.name.cxx));writeln!(
360            out,
361            "  bool operator<=({} const &) const noexcept;",
362            strct.name.cxx,
363        );
364        out.write_fmt(format_args!("  bool operator>({0} const &) const noexcept;\n",
        strct.name.cxx));writeln!(
365            out,
366            "  bool operator>({} const &) const noexcept;",
367            strct.name.cxx,
368        );
369        out.write_fmt(format_args!("  bool operator>=({0} const &) const noexcept;\n",
        strct.name.cxx));writeln!(
370            out,
371            "  bool operator>=({} const &) const noexcept;",
372            strct.name.cxx,
373        );
374    }
375
376    out.include.type_traits = true;
377    out.write_fmt(format_args!("  using IsRelocatable = ::std::true_type;\n"));writeln!(out, "  using IsRelocatable = ::std::true_type;");
378
379    out.write_fmt(format_args!("}};\n"));writeln!(out, "}};");
380    out.write_fmt(format_args!("#endif // {0}\n", guard));writeln!(out, "#endif // {}", guard);
381}
382
383fn write_struct_decl(out: &mut OutFile, ident: &Pair) {
384    out.write_fmt(format_args!("struct {0};\n", ident.cxx));writeln!(out, "struct {};", ident.cxx);
385}
386
387fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
388    out.write_fmt(format_args!("enum class {0} : ", enm.name.cxx));write!(out, "enum class {} : ", enm.name.cxx);
389    write_atom(out, enm.repr.atom);
390    out.write_fmt(format_args!(";\n"));writeln!(out, ";");
391}
392
393fn write_struct_using(out: &mut OutFile, ident: &Pair) {
394    out.write_fmt(format_args!("using {0} = {1};\n", ident.cxx,
        ident.to_fully_qualified()));writeln!(out, "using {} = {};", ident.cxx, ident.to_fully_qualified());
395}
396
397fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[&ExternFn]) {
398    out.set_namespace(&ety.name.namespace);
399    let guard = Guard::new(out, "CXXBRIDGE1_STRUCT", &ety.name);
400    out.write_fmt(format_args!("#ifndef {0}\n", guard));writeln!(out, "#ifndef {}", guard);
401    out.write_fmt(format_args!("#define {0}\n", guard));writeln!(out, "#define {}", guard);
402    write_doc(out, "", &ety.doc);
403
404    out.builtin.opaque = true;
405    out.write_fmt(format_args!("struct {0} final : public ::rust::Opaque {{\n",
        ety.name.cxx));writeln!(
406        out,
407        "struct {} final : public ::rust::Opaque {{",
408        ety.name.cxx,
409    );
410
411    for (i, method) in methods.iter().enumerate() {
412        if i > 0 && !method.doc.is_empty() {
413            out.next_section();
414        }
415        write_doc(out, "  ", &method.doc);
416        out.write_fmt(format_args!("  "));write!(out, "  ");
417        let local_name = method.name.cxx.to_string();
418        let sig = &method.sig;
419        let in_class = true;
420        let indirect_call = false;
421        let main = false;
422        write_rust_function_shim_decl(out, &local_name, sig, in_class, indirect_call, main);
423        out.write_fmt(format_args!(";\n"));writeln!(out, ";");
424        if !method.doc.is_empty() {
425            out.next_section();
426        }
427    }
428
429    out.write_fmt(format_args!("  ~{0}() = delete;\n", ety.name.cxx));writeln!(out, "  ~{}() = delete;", ety.name.cxx);
430    out.write_fmt(format_args!("\n"));writeln!(out);
431
432    out.builtin.layout = true;
433    out.include.cstddef = true;
434    out.write_fmt(format_args!("private:\n"));writeln!(out, "private:");
435    out.write_fmt(format_args!("  friend ::rust::layout;\n"));writeln!(out, "  friend ::rust::layout;");
436    out.write_fmt(format_args!("  struct layout {{\n"));writeln!(out, "  struct layout {{");
437    out.write_fmt(format_args!("    static ::std::size_t size() noexcept;\n"));writeln!(out, "    static ::std::size_t size() noexcept;");
438    out.write_fmt(format_args!("    static ::std::size_t align() noexcept;\n"));writeln!(out, "    static ::std::size_t align() noexcept;");
439    out.write_fmt(format_args!("  }};\n"));writeln!(out, "  }};");
440    out.write_fmt(format_args!("}};\n"));writeln!(out, "}};");
441    out.write_fmt(format_args!("#endif // {0}\n", guard));writeln!(out, "#endif // {}", guard);
442}
443
444fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
445    out.set_namespace(&enm.name.namespace);
446    let guard = Guard::new(out, "CXXBRIDGE1_ENUM", &enm.name);
447    out.write_fmt(format_args!("#ifndef {0}\n", guard));writeln!(out, "#ifndef {}", guard);
448    out.write_fmt(format_args!("#define {0}\n", guard));writeln!(out, "#define {}", guard);
449
450    write_doc(out, "", &enm.doc);
451    out.write_fmt(format_args!("enum class {0} : ", enm.name.cxx));write!(out, "enum class {} : ", enm.name.cxx);
452    write_atom(out, enm.repr.atom);
453    out.write_fmt(format_args!(" {{\n"));writeln!(out, " {{");
454    for variant in &enm.variants {
455        write_doc(out, "  ", &variant.doc);
456        out.write_fmt(format_args!("  {0} = ", variant.name.cxx));write!(out, "  {} = ", variant.name.cxx);
457        write_discriminant(out, enm.repr.atom, variant.discriminant);
458        out.write_fmt(format_args!(",\n"));writeln!(out, ",");
459    }
460    out.write_fmt(format_args!("}};\n"));writeln!(out, "}};");
461
462    if out.header {
463        write_enum_operators(out, enm);
464    }
465
466    out.write_fmt(format_args!("#endif // {0}\n", guard));writeln!(out, "#endif // {}", guard);
467}
468
469fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
470    out.set_namespace(&enm.name.namespace);
471    out.include.type_traits = true;
472    out.write_fmt(format_args!("static_assert(::std::is_enum<{0}>::value, \"expected enum\");\n",
        enm.name.cxx));writeln!(
473        out,
474        "static_assert(::std::is_enum<{}>::value, \"expected enum\");",
475        enm.name.cxx,
476    );
477    out.write_fmt(format_args!("static_assert(sizeof({0}) == sizeof(",
        enm.name.cxx));write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx);
478    write_atom(out, enm.repr.atom);
479    out.write_fmt(format_args!("), \"incorrect size\");\n"));writeln!(out, "), \"incorrect size\");");
480    for variant in &enm.variants {
481        out.write_fmt(format_args!("static_assert(static_cast<"));write!(out, "static_assert(static_cast<");
482        write_atom(out, enm.repr.atom);
483        out.write_fmt(format_args!(">({0}::{1}) == ", enm.name.cxx,
        variant.name.cxx));write!(out, ">({}::{}) == ", enm.name.cxx, variant.name.cxx);
484        write_discriminant(out, enm.repr.atom, variant.discriminant);
485        out.write_fmt(format_args!(", \"disagrees with the value in #[cxx::bridge]\");\n"));writeln!(out, ", \"disagrees with the value in #[cxx::bridge]\");");
486    }
487
488    if out.header
489        && (derive::contains(&enm.derives, Trait::BitAnd)
490            || derive::contains(&enm.derives, Trait::BitOr)
491            || derive::contains(&enm.derives, Trait::BitXor))
492    {
493        out.next_section();
494        let guard = Guard::new(out, "CXXBRIDGE1_ENUM", &enm.name);
495        out.write_fmt(format_args!("#ifndef {0}\n", guard));writeln!(out, "#ifndef {}", guard);
496        out.write_fmt(format_args!("#define {0}\n", guard));writeln!(out, "#define {}", guard);
497        out.suppress_next_section();
498        write_enum_operators(out, enm);
499        out.write_fmt(format_args!("#endif // {0}\n", guard));writeln!(out, "#endif // {}", guard);
500    }
501}
502
503fn write_discriminant(out: &mut OutFile, repr: Atom, discriminant: Discriminant) {
504    let limits = Limits::of(repr).unwrap();
505    if discriminant == limits.min && limits.min < Discriminant::zero() {
506        out.include.limits = true;
507        out.write_fmt(format_args!("::std::numeric_limits<"));write!(out, "::std::numeric_limits<");
508        write_atom(out, repr);
509        out.write_fmt(format_args!(">::min()"));write!(out, ">::min()");
510    } else {
511        out.write_fmt(format_args!("{0}", discriminant));write!(out, "{}", discriminant);
512    }
513}
514
515fn write_binary_bitwise_op(out: &mut OutFile, op: &str, enm: &Enum) {
516    let enum_name = &enm.name.cxx;
517    out.write_fmt(format_args!("inline {0} operator{1}({0} lhs, {0} rhs) {{\n",
        enum_name, op));writeln!(
518        out,
519        "inline {enum_name} operator{op}({enum_name} lhs, {enum_name} rhs) {{",
520    );
521    out.write_fmt(format_args!("  return static_cast<{0}>(static_cast<",
        enum_name));write!(out, "  return static_cast<{enum_name}>(static_cast<");
522    write_atom(out, enm.repr.atom);
523    out.write_fmt(format_args!(">(lhs) {0} static_cast<", op));write!(out, ">(lhs) {op} static_cast<");
524    write_atom(out, enm.repr.atom);
525    out.write_fmt(format_args!(">(rhs));\n"));writeln!(out, ">(rhs));");
526    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
527}
528
529fn write_enum_operators(out: &mut OutFile, enm: &Enum) {
530    if derive::contains(&enm.derives, Trait::BitAnd) {
531        out.next_section();
532        write_binary_bitwise_op(out, "&", enm);
533    }
534
535    if derive::contains(&enm.derives, Trait::BitOr) {
536        out.next_section();
537        write_binary_bitwise_op(out, "|", enm);
538    }
539
540    if derive::contains(&enm.derives, Trait::BitXor) {
541        out.next_section();
542        write_binary_bitwise_op(out, "^", enm);
543    }
544}
545
546fn check_trivial_extern_type(out: &mut OutFile, alias: &TypeAlias, reasons: &[TrivialReason]) {
547    // NOTE: The following static assertion is just nice-to-have and not
548    // necessary for soundness. That's because triviality is always declared by
549    // the user in the form of an unsafe impl of cxx::ExternType:
550    //
551    //     unsafe impl ExternType for MyType {
552    //         type Id = cxx::type_id!("...");
553    //         type Kind = cxx::kind::Trivial;
554    //     }
555    //
556    // Since the user went on the record with their unsafe impl to unsafely
557    // claim they KNOW that the type is trivial, it's fine for that to be on
558    // them if that were wrong. However, in practice correctly reasoning about
559    // the relocatability of C++ types is challenging, particularly if the type
560    // definition were to change over time, so for now we add this check.
561    //
562    // There may be legitimate reasons to opt out of this assertion for support
563    // of types that the programmer knows are soundly Rust-movable despite not
564    // being recognized as such by the C++ type system due to a move constructor
565    // or destructor. To opt out of the relocatability check, they need to do
566    // one of the following things in any header used by `include!` in their
567    // bridge.
568    //
569    //      --- if they define the type:
570    //      struct MyType {
571    //        ...
572    //    +   using IsRelocatable = std::true_type;
573    //      };
574    //
575    //      --- otherwise:
576    //    + template <>
577    //    + struct rust::IsRelocatable<MyType> : std::true_type {};
578    //
579
580    let id = alias.name.to_fully_qualified();
581    out.builtin.relocatable = true;
582
583    let mut rust_type_ok = true;
584    let mut array_ok = true;
585    for reason in reasons {
586        // Allow extern type that inherits from ::rust::Opaque in positions
587        // where an opaque Rust type would be allowed.
588        rust_type_ok &= match reason {
589            TrivialReason::BoxTarget { .. }
590            | TrivialReason::VecElement { .. }
591            | TrivialReason::SliceElement { .. } => true,
592            TrivialReason::StructField(_)
593            | TrivialReason::FunctionArgument(_)
594            | TrivialReason::FunctionReturn(_) => false,
595        };
596        // If the type is only used as a struct field or Vec element, not as
597        // by-value function argument or return value, then C array of trivially
598        // relocatable type is also permissible.
599        //
600        //     --- means something sane:
601        //     struct T { char buf[N]; };
602        //
603        //     --- means something totally different:
604        //     void f(char buf[N]);
605        //
606        array_ok &= match reason {
607            TrivialReason::StructField(_) | TrivialReason::VecElement { .. } => true,
608            TrivialReason::FunctionArgument(_)
609            | TrivialReason::FunctionReturn(_)
610            | TrivialReason::BoxTarget { .. }
611            | TrivialReason::SliceElement { .. } => false,
612        };
613    }
614
615    out.write_fmt(format_args!("static_assert(\n"));writeln!(out, "static_assert(");
616    out.write_fmt(format_args!("    "));write!(out, "    ");
617    if rust_type_ok {
618        out.include.type_traits = true;
619        out.builtin.opaque = true;
620        out.write_fmt(format_args!("::std::is_base_of<::rust::Opaque, {0}>::value || ",
        id));write!(out, "::std::is_base_of<::rust::Opaque, {}>::value || ", id);
621    }
622    if array_ok {
623        out.builtin.relocatable_or_array = true;
624        out.write_fmt(format_args!("::rust::IsRelocatableOrArray<{0}>::value,\n",
        id));writeln!(out, "::rust::IsRelocatableOrArray<{}>::value,", id);
625    } else {
626        out.write_fmt(format_args!("::rust::IsRelocatable<{0}>::value,\n", id));writeln!(out, "::rust::IsRelocatable<{}>::value,", id);
627    }
628    out.write_fmt(format_args!("    \"type {0} should be trivially move constructible and trivially destructible in C++ to be used as {1} in Rust\");\n",
        id.trim_start_matches("::"), trivial::as_what(&alias.name, reasons)));writeln!(
629        out,
630        "    \"type {} should be trivially move constructible and trivially destructible in C++ to be used as {} in Rust\");",
631        id.trim_start_matches("::"),
632        trivial::as_what(&alias.name, reasons),
633    );
634}
635
636fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
637    out.set_namespace(&strct.name.namespace);
638    out.begin_block(Block::ExternC);
639
640    if derive::contains(&strct.derives, Trait::PartialEq) {
641        out.pragma.dollar_in_identifier = true;
642        out.pragma.missing_declarations = true;
643        let link_name = mangle::operator(&strct.name, "eq");
644        out.write_fmt(format_args!("bool {0}({1} const &, {1} const &) noexcept;\n",
        link_name, strct.name.cxx));writeln!(
645            out,
646            "bool {}({1} const &, {1} const &) noexcept;",
647            link_name, strct.name.cxx,
648        );
649
650        if !derive::contains(&strct.derives, Trait::Eq) {
651            let link_name = mangle::operator(&strct.name, "ne");
652            out.write_fmt(format_args!("bool {0}({1} const &, {1} const &) noexcept;\n",
        link_name, strct.name.cxx));writeln!(
653                out,
654                "bool {}({1} const &, {1} const &) noexcept;",
655                link_name, strct.name.cxx,
656            );
657        }
658    }
659
660    if derive::contains(&strct.derives, Trait::PartialOrd) {
661        out.pragma.dollar_in_identifier = true;
662        out.pragma.missing_declarations = true;
663        let link_name = mangle::operator(&strct.name, "lt");
664        out.write_fmt(format_args!("bool {0}({1} const &, {1} const &) noexcept;\n",
        link_name, strct.name.cxx));writeln!(
665            out,
666            "bool {}({1} const &, {1} const &) noexcept;",
667            link_name, strct.name.cxx,
668        );
669
670        let link_name = mangle::operator(&strct.name, "le");
671        out.write_fmt(format_args!("bool {0}({1} const &, {1} const &) noexcept;\n",
        link_name, strct.name.cxx));writeln!(
672            out,
673            "bool {}({1} const &, {1} const &) noexcept;",
674            link_name, strct.name.cxx,
675        );
676
677        if !derive::contains(&strct.derives, Trait::Ord) {
678            let link_name = mangle::operator(&strct.name, "gt");
679            out.write_fmt(format_args!("bool {0}({1} const &, {1} const &) noexcept;\n",
        link_name, strct.name.cxx));writeln!(
680                out,
681                "bool {}({1} const &, {1} const &) noexcept;",
682                link_name, strct.name.cxx,
683            );
684
685            let link_name = mangle::operator(&strct.name, "ge");
686            out.write_fmt(format_args!("bool {0}({1} const &, {1} const &) noexcept;\n",
        link_name, strct.name.cxx));writeln!(
687                out,
688                "bool {}({1} const &, {1} const &) noexcept;",
689                link_name, strct.name.cxx,
690            );
691        }
692    }
693
694    if derive::contains(&strct.derives, Trait::Hash) {
695        out.include.cstddef = true;
696        out.pragma.dollar_in_identifier = true;
697        out.pragma.missing_declarations = true;
698        let link_name = mangle::operator(&strct.name, "hash");
699        out.write_fmt(format_args!("::std::size_t {0}({1} const &) noexcept;\n",
        link_name, strct.name.cxx));writeln!(
700            out,
701            "::std::size_t {}({} const &) noexcept;",
702            link_name, strct.name.cxx,
703        );
704    }
705
706    out.end_block(Block::ExternC);
707}
708
709fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
710    if out.header {
711        return;
712    }
713
714    out.set_namespace(&strct.name.namespace);
715
716    if derive::contains(&strct.derives, Trait::PartialEq) {
717        out.pragma.dollar_in_identifier = true;
718
719        out.next_section();
720        out.write_fmt(format_args!("bool {0}::operator==({0} const &rhs) const noexcept {{\n",
        strct.name.cxx));writeln!(
721            out,
722            "bool {0}::operator==({0} const &rhs) const noexcept {{",
723            strct.name.cxx,
724        );
725        let link_name = mangle::operator(&strct.name, "eq");
726        out.write_fmt(format_args!("  return {0}(*this, rhs);\n", link_name));writeln!(out, "  return {}(*this, rhs);", link_name);
727        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
728
729        out.next_section();
730        out.write_fmt(format_args!("bool {0}::operator!=({0} const &rhs) const noexcept {{\n",
        strct.name.cxx));writeln!(
731            out,
732            "bool {0}::operator!=({0} const &rhs) const noexcept {{",
733            strct.name.cxx,
734        );
735        if derive::contains(&strct.derives, Trait::Eq) {
736            out.write_fmt(format_args!("  return !(*this == rhs);\n"));writeln!(out, "  return !(*this == rhs);");
737        } else {
738            let link_name = mangle::operator(&strct.name, "ne");
739            out.write_fmt(format_args!("  return {0}(*this, rhs);\n", link_name));writeln!(out, "  return {}(*this, rhs);", link_name);
740        }
741        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
742    }
743
744    if derive::contains(&strct.derives, Trait::PartialOrd) {
745        out.pragma.dollar_in_identifier = true;
746
747        out.next_section();
748        out.write_fmt(format_args!("bool {0}::operator<({0} const &rhs) const noexcept {{\n",
        strct.name.cxx));writeln!(
749            out,
750            "bool {0}::operator<({0} const &rhs) const noexcept {{",
751            strct.name.cxx,
752        );
753        let link_name = mangle::operator(&strct.name, "lt");
754        out.write_fmt(format_args!("  return {0}(*this, rhs);\n", link_name));writeln!(out, "  return {}(*this, rhs);", link_name);
755        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
756
757        out.next_section();
758        out.write_fmt(format_args!("bool {0}::operator<=({0} const &rhs) const noexcept {{\n",
        strct.name.cxx));writeln!(
759            out,
760            "bool {0}::operator<=({0} const &rhs) const noexcept {{",
761            strct.name.cxx,
762        );
763        let link_name = mangle::operator(&strct.name, "le");
764        out.write_fmt(format_args!("  return {0}(*this, rhs);\n", link_name));writeln!(out, "  return {}(*this, rhs);", link_name);
765        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
766
767        out.next_section();
768        out.write_fmt(format_args!("bool {0}::operator>({0} const &rhs) const noexcept {{\n",
        strct.name.cxx));writeln!(
769            out,
770            "bool {0}::operator>({0} const &rhs) const noexcept {{",
771            strct.name.cxx,
772        );
773        if derive::contains(&strct.derives, Trait::Ord) {
774            out.write_fmt(format_args!("  return !(*this <= rhs);\n"));writeln!(out, "  return !(*this <= rhs);");
775        } else {
776            let link_name = mangle::operator(&strct.name, "gt");
777            out.write_fmt(format_args!("  return {0}(*this, rhs);\n", link_name));writeln!(out, "  return {}(*this, rhs);", link_name);
778        }
779        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
780
781        out.next_section();
782        out.write_fmt(format_args!("bool {0}::operator>=({0} const &rhs) const noexcept {{\n",
        strct.name.cxx));writeln!(
783            out,
784            "bool {0}::operator>=({0} const &rhs) const noexcept {{",
785            strct.name.cxx,
786        );
787        if derive::contains(&strct.derives, Trait::Ord) {
788            out.write_fmt(format_args!("  return !(*this < rhs);\n"));writeln!(out, "  return !(*this < rhs);");
789        } else {
790            let link_name = mangle::operator(&strct.name, "ge");
791            out.write_fmt(format_args!("  return {0}(*this, rhs);\n", link_name));writeln!(out, "  return {}(*this, rhs);", link_name);
792        }
793        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
794    }
795}
796
797fn write_opaque_type_layout_decls<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
798    out.set_namespace(&ety.name.namespace);
799    out.begin_block(Block::ExternC);
800    out.pragma.dollar_in_identifier = true;
801    out.pragma.missing_declarations = true;
802
803    let link_name = mangle::operator(&ety.name, "sizeof");
804    out.write_fmt(format_args!("::std::size_t {0}() noexcept;\n", link_name));writeln!(out, "::std::size_t {}() noexcept;", link_name);
805
806    let link_name = mangle::operator(&ety.name, "alignof");
807    out.write_fmt(format_args!("::std::size_t {0}() noexcept;\n", link_name));writeln!(out, "::std::size_t {}() noexcept;", link_name);
808
809    out.end_block(Block::ExternC);
810}
811
812fn write_opaque_type_layout<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
813    if out.header {
814        return;
815    }
816
817    out.set_namespace(&ety.name.namespace);
818    out.pragma.dollar_in_identifier = true;
819
820    out.next_section();
821    let link_name = mangle::operator(&ety.name, "sizeof");
822    out.write_fmt(format_args!("::std::size_t {0}::layout::size() noexcept {{\n",
        ety.name.cxx));writeln!(
823        out,
824        "::std::size_t {}::layout::size() noexcept {{",
825        ety.name.cxx,
826    );
827    out.write_fmt(format_args!("  return {0}();\n", link_name));writeln!(out, "  return {}();", link_name);
828    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
829
830    out.next_section();
831    let link_name = mangle::operator(&ety.name, "alignof");
832    out.write_fmt(format_args!("::std::size_t {0}::layout::align() noexcept {{\n",
        ety.name.cxx));writeln!(
833        out,
834        "::std::size_t {}::layout::align() noexcept {{",
835        ety.name.cxx,
836    );
837    out.write_fmt(format_args!("  return {0}();\n", link_name));writeln!(out, "  return {}();", link_name);
838    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
839}
840
841fn begin_function_definition(out: &mut OutFile) {
842    if let Some(annotation) = &out.opt.cxx_impl_annotations {
843        out.write_fmt(format_args!("{0} ", annotation));write!(out, "{} ", annotation);
844    }
845}
846
847fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
848    out.pragma.dollar_in_identifier = true;
849    out.pragma.missing_declarations = true;
850    out.next_section();
851    out.set_namespace(&efn.name.namespace);
852    out.begin_block(Block::ExternC);
853    begin_function_definition(out);
854    if efn.throws {
855        out.builtin.ptr_len = true;
856        out.write_fmt(format_args!("::rust::repr::PtrLen "));write!(out, "::rust::repr::PtrLen ");
857    } else {
858        write_extern_return_type_space(out, efn, efn.lang);
859    }
860    let mangled = mangle::extern_fn(efn, out.types);
861    out.write_fmt(format_args!("{0}(", mangled));write!(out, "{}(", mangled);
862    if let FnKind::Method(receiver) = &efn.kind {
863        out.write_fmt(format_args!("{0}",
        out.types.resolve(&receiver.ty).name.to_fully_qualified()));write!(
864            out,
865            "{}",
866            out.types.resolve(&receiver.ty).name.to_fully_qualified(),
867        );
868        if !receiver.mutable {
869            out.write_fmt(format_args!(" const"));write!(out, " const");
870        }
871        out.write_fmt(format_args!(" &self"));write!(out, " &self");
872    }
873    for (i, arg) in efn.args.iter().enumerate() {
874        if i > 0 || #[allow(non_exhaustive_omitted_patterns)] match efn.kind {
    FnKind::Method(_) => true,
    _ => false,
}matches!(efn.kind, FnKind::Method(_)) {
875            out.write_fmt(format_args!(", "));write!(out, ", ");
876        }
877        if arg.ty == RustString {
878            write_type_space(out, &arg.ty);
879            out.write_fmt(format_args!("const *{0}", arg.name.cxx));write!(out, "const *{}", arg.name.cxx);
880        } else if let Type::RustVec(_) = arg.ty {
881            write_type_space(out, &arg.ty);
882            out.write_fmt(format_args!("const *{0}", arg.name.cxx));write!(out, "const *{}", arg.name.cxx);
883        } else {
884            write_extern_arg(out, arg);
885        }
886    }
887    let indirect_return = indirect_return(efn, out.types, efn.lang);
888    if indirect_return {
889        if !efn.args.is_empty() || #[allow(non_exhaustive_omitted_patterns)] match efn.kind {
    FnKind::Method(_) => true,
    _ => false,
}matches!(efn.kind, FnKind::Method(_)) {
890            out.write_fmt(format_args!(", "));write!(out, ", ");
891        }
892        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
893        out.write_fmt(format_args!("*return$"));write!(out, "*return$");
894    }
895    out.write_fmt(format_args!(")"));write!(out, ")");
896    match efn.lang {
897        Lang::Cxx => out.write_fmt(format_args!(" noexcept"))write!(out, " noexcept"),
898        Lang::CxxUnwind => {}
899        Lang::Rust => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
900    }
901    out.write_fmt(format_args!(" {{\n"));writeln!(out, " {{");
902    out.write_fmt(format_args!("  "));write!(out, "  ");
903    write_return_type(out, &efn.ret);
904    match efn.receiver() {
905        None => out.write_fmt(format_args!("(*{0}$)(", efn.name.rust))write!(out, "(*{}$)(", efn.name.rust),
906        Some(receiver) => out.write_fmt(format_args!("({0}::*{1}$)(",
        out.types.resolve(&receiver.ty).name.to_fully_qualified(),
        efn.name.rust))write!(
907            out,
908            "({}::*{}$)(",
909            out.types.resolve(&receiver.ty).name.to_fully_qualified(),
910            efn.name.rust,
911        ),
912    }
913    for (i, arg) in efn.args.iter().enumerate() {
914        if i > 0 {
915            out.write_fmt(format_args!(", "));write!(out, ", ");
916        }
917        write_type(out, &arg.ty);
918    }
919    out.write_fmt(format_args!(")"));write!(out, ")");
920    if let Some(receiver) = efn.receiver()
921        && !receiver.mutable
922    {
923        out.write_fmt(format_args!(" const"));write!(out, " const");
924    }
925    out.write_fmt(format_args!(" = "));write!(out, " = ");
926    match efn.self_type() {
927        None => out.write_fmt(format_args!("{0}", efn.name.to_fully_qualified()))write!(out, "{}", efn.name.to_fully_qualified()),
928        Some(self_type) => out.write_fmt(format_args!("&{0}::{1}",
        out.types.resolve(self_type).name.to_fully_qualified(), efn.name.cxx))write!(
929            out,
930            "&{}::{}",
931            out.types.resolve(self_type).name.to_fully_qualified(),
932            efn.name.cxx,
933        ),
934    }
935    out.write_fmt(format_args!(";\n"));writeln!(out, ";");
936    out.write_fmt(format_args!("  "));write!(out, "  ");
937    if efn.throws {
938        out.builtin.ptr_len = true;
939        out.builtin.trycatch = true;
940        out.write_fmt(format_args!("::rust::repr::PtrLen throw$;\n"));writeln!(out, "::rust::repr::PtrLen throw$;");
941        out.write_fmt(format_args!("  ::rust::behavior::trycatch(\n"));writeln!(out, "  ::rust::behavior::trycatch(");
942        out.write_fmt(format_args!("      [&] {{\n"));writeln!(out, "      [&] {{");
943        out.write_fmt(format_args!("        "));write!(out, "        ");
944    }
945    if indirect_return {
946        out.include.new = true;
947        out.write_fmt(format_args!("new (return$) "));write!(out, "new (return$) ");
948        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
949        out.write_fmt(format_args!("("));write!(out, "(");
950    } else if efn.ret.is_some() {
951        out.write_fmt(format_args!("return "));write!(out, "return ");
952    }
953    match &efn.ret {
954        Some(Type::Ref(_)) => out.write_fmt(format_args!("&"))write!(out, "&"),
955        Some(Type::Str(_)) if !indirect_return => {
956            out.builtin.rust_str_repr = true;
957            out.write_fmt(format_args!("::rust::impl<::rust::Str>::repr("));write!(out, "::rust::impl<::rust::Str>::repr(");
958        }
959        Some(ty @ Type::SliceRef(_)) if !indirect_return => {
960            out.builtin.rust_slice_repr = true;
961            out.write_fmt(format_args!("::rust::impl<"));write!(out, "::rust::impl<");
962            write_type(out, ty);
963            out.write_fmt(format_args!(">::repr("));write!(out, ">::repr(");
964        }
965        _ => {}
966    }
967    match efn.receiver() {
968        None => out.write_fmt(format_args!("{0}$(", efn.name.rust))write!(out, "{}$(", efn.name.rust),
969        Some(_) => out.write_fmt(format_args!("(self.*{0}$)(", efn.name.rust))write!(out, "(self.*{}$)(", efn.name.rust),
970    }
971    for (i, arg) in efn.args.iter().enumerate() {
972        if i > 0 {
973            out.write_fmt(format_args!(", "));write!(out, ", ");
974        }
975        if let Type::RustBox(_) = &arg.ty {
976            write_type(out, &arg.ty);
977            out.write_fmt(format_args!("::from_raw({0})", arg.name.cxx));write!(out, "::from_raw({})", arg.name.cxx);
978        } else if let Type::UniquePtr(_) = &arg.ty {
979            write_type(out, &arg.ty);
980            out.write_fmt(format_args!("({0})", arg.name.cxx));write!(out, "({})", arg.name.cxx);
981        } else if arg.ty == RustString {
982            out.builtin.unsafe_bitcopy = true;
983            out.write_fmt(format_args!("::rust::String(::rust::unsafe_bitcopy, *{0})",
        arg.name.cxx));write!(
984                out,
985                "::rust::String(::rust::unsafe_bitcopy, *{})",
986                arg.name.cxx,
987            );
988        } else if let Type::RustVec(_) = arg.ty {
989            out.builtin.unsafe_bitcopy = true;
990            write_type(out, &arg.ty);
991            out.write_fmt(format_args!("(::rust::unsafe_bitcopy, *{0})", arg.name.cxx));write!(out, "(::rust::unsafe_bitcopy, *{})", arg.name.cxx);
992        } else if out.types.needs_indirect_abi(&arg.ty) {
993            out.include.utility = true;
994            out.write_fmt(format_args!("::std::move(*{0})", arg.name.cxx));write!(out, "::std::move(*{})", arg.name.cxx);
995        } else {
996            out.write_fmt(format_args!("{0}", arg.name.cxx));write!(out, "{}", arg.name.cxx);
997        }
998    }
999    out.write_fmt(format_args!(")"));write!(out, ")");
1000    match &efn.ret {
1001        Some(Type::RustBox(_)) => out.write_fmt(format_args!(".into_raw()"))write!(out, ".into_raw()"),
1002        Some(Type::UniquePtr(_)) => out.write_fmt(format_args!(".release()"))write!(out, ".release()"),
1003        Some(Type::Str(_) | Type::SliceRef(_)) if !indirect_return => out.write_fmt(format_args!(")"))write!(out, ")"),
1004        _ => {}
1005    }
1006    if indirect_return {
1007        out.write_fmt(format_args!(")"));write!(out, ")");
1008    }
1009    out.write_fmt(format_args!(";\n"));writeln!(out, ";");
1010    if efn.throws {
1011        out.write_fmt(format_args!("        throw$.ptr = nullptr;\n"));writeln!(out, "        throw$.ptr = nullptr;");
1012        out.write_fmt(format_args!("      }},\n"));writeln!(out, "      }},");
1013        out.write_fmt(format_args!("      ::rust::detail::Fail(throw$));\n"));writeln!(out, "      ::rust::detail::Fail(throw$));");
1014        out.write_fmt(format_args!("  return throw$;\n"));writeln!(out, "  return throw$;");
1015    }
1016    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1017    for arg in &efn.args {
1018        if let Type::Fn(f) = &arg.ty {
1019            let var = &arg.name;
1020            write_function_pointer_trampoline(out, efn, var, f);
1021        }
1022    }
1023    out.end_block(Block::ExternC);
1024}
1025
1026fn write_function_pointer_trampoline(out: &mut OutFile, efn: &ExternFn, var: &Pair, f: &Signature) {
1027    out.pragma.return_type_c_linkage = true;
1028
1029    let r_trampoline = mangle::r_trampoline(efn, var, out.types);
1030    let indirect_call = true;
1031    write_rust_function_decl_impl(out, &r_trampoline, f, indirect_call);
1032
1033    out.next_section();
1034    let c_trampoline = mangle::c_trampoline(efn, var, out.types).to_string();
1035    let doc = Doc::new();
1036    let main = false;
1037    write_rust_function_shim_impl(
1038        out,
1039        &c_trampoline,
1040        f,
1041        &doc,
1042        &r_trampoline,
1043        indirect_call,
1044        main,
1045    );
1046}
1047
1048fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
1049    out.set_namespace(&efn.name.namespace);
1050    out.begin_block(Block::ExternC);
1051    let link_name = mangle::extern_fn(efn, out.types);
1052    let indirect_call = false;
1053    write_rust_function_decl_impl(out, &link_name, efn, indirect_call);
1054    out.end_block(Block::ExternC);
1055}
1056
1057fn write_rust_function_decl_impl(
1058    out: &mut OutFile,
1059    link_name: &Symbol,
1060    sig: &Signature,
1061    indirect_call: bool,
1062) {
1063    out.next_section();
1064    out.pragma.dollar_in_identifier = true;
1065    if sig.throws {
1066        out.builtin.ptr_len = true;
1067        out.write_fmt(format_args!("::rust::repr::PtrLen "));write!(out, "::rust::repr::PtrLen ");
1068    } else {
1069        write_extern_return_type_space(out, sig, Lang::Rust);
1070    }
1071    out.write_fmt(format_args!("{0}(", link_name));write!(out, "{}(", link_name);
1072    let mut needs_comma = false;
1073    if let FnKind::Method(receiver) = &sig.kind {
1074        out.write_fmt(format_args!("{0}",
        out.types.resolve(&receiver.ty).name.to_fully_qualified()));write!(
1075            out,
1076            "{}",
1077            out.types.resolve(&receiver.ty).name.to_fully_qualified(),
1078        );
1079        if !receiver.mutable {
1080            out.write_fmt(format_args!(" const"));write!(out, " const");
1081        }
1082        out.write_fmt(format_args!(" &self"));write!(out, " &self");
1083        needs_comma = true;
1084    }
1085    for arg in &sig.args {
1086        if needs_comma {
1087            out.write_fmt(format_args!(", "));write!(out, ", ");
1088        }
1089        write_extern_arg(out, arg);
1090        needs_comma = true;
1091    }
1092    if indirect_return(sig, out.types, Lang::Rust) {
1093        if needs_comma {
1094            out.write_fmt(format_args!(", "));write!(out, ", ");
1095        }
1096        match sig.ret.as_ref().unwrap() {
1097            Type::Ref(ret) => {
1098                write_type_space(out, &ret.inner);
1099                if !ret.mutable {
1100                    out.write_fmt(format_args!("const "));write!(out, "const ");
1101                }
1102                out.write_fmt(format_args!("*"));write!(out, "*");
1103            }
1104            ret => write_type_space(out, ret),
1105        }
1106        out.write_fmt(format_args!("*return$"));write!(out, "*return$");
1107        needs_comma = true;
1108    }
1109    if indirect_call {
1110        if needs_comma {
1111            out.write_fmt(format_args!(", "));write!(out, ", ");
1112        }
1113        out.write_fmt(format_args!("void *"));write!(out, "void *");
1114    }
1115    out.write_fmt(format_args!(") noexcept;\n"));writeln!(out, ") noexcept;");
1116}
1117
1118fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
1119    out.set_namespace(&efn.name.namespace);
1120    let local_name = match efn.self_type() {
1121        None => efn.name.cxx.to_string(),
1122        Some(self_type) => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::{1}",
                out.types.resolve(self_type).name.cxx, efn.name.cxx))
    })format!(
1123            "{}::{}",
1124            out.types.resolve(self_type).name.cxx,
1125            efn.name.cxx,
1126        ),
1127    };
1128    let doc = &efn.doc;
1129    let invoke = mangle::extern_fn(efn, out.types);
1130    let indirect_call = false;
1131    let main = efn.name.cxx == *"main"
1132        && efn.name.namespace == Namespace::ROOT
1133        && efn.sig.asyncness.is_none()
1134        && #[allow(non_exhaustive_omitted_patterns)] match efn.kind {
    FnKind::Free => true,
    _ => false,
}matches!(efn.kind, FnKind::Free)
1135        && efn.sig.args.is_empty()
1136        && efn.sig.ret.is_none()
1137        && !efn.sig.throws;
1138    write_rust_function_shim_impl(out, &local_name, efn, doc, &invoke, indirect_call, main);
1139}
1140
1141fn write_rust_function_shim_decl(
1142    out: &mut OutFile,
1143    local_name: &str,
1144    sig: &Signature,
1145    in_class: bool,
1146    indirect_call: bool,
1147    main: bool,
1148) {
1149    begin_function_definition(out);
1150    if #[allow(non_exhaustive_omitted_patterns)] match sig.kind {
    FnKind::Assoc(_) => true,
    _ => false,
}matches!(sig.kind, FnKind::Assoc(_)) && in_class {
1151        out.write_fmt(format_args!("static "));write!(out, "static ");
1152    }
1153    if main {
1154        out.write_fmt(format_args!("int "));write!(out, "int ");
1155    } else {
1156        write_return_type(out, &sig.ret);
1157    }
1158    out.write_fmt(format_args!("{0}(", local_name));write!(out, "{}(", local_name);
1159    for (i, arg) in sig.args.iter().enumerate() {
1160        if i > 0 {
1161            out.write_fmt(format_args!(", "));write!(out, ", ");
1162        }
1163        write_type_space(out, &arg.ty);
1164        out.write_fmt(format_args!("{0}", arg.name.cxx));write!(out, "{}", arg.name.cxx);
1165    }
1166    if indirect_call {
1167        if !sig.args.is_empty() {
1168            out.write_fmt(format_args!(", "));write!(out, ", ");
1169        }
1170        out.write_fmt(format_args!("void *extern$"));write!(out, "void *extern$");
1171    }
1172    out.write_fmt(format_args!(")"));write!(out, ")");
1173    if let FnKind::Method(receiver) = &sig.kind
1174        && !receiver.mutable
1175    {
1176        out.write_fmt(format_args!(" const"));write!(out, " const");
1177    }
1178    if !sig.throws {
1179        out.write_fmt(format_args!(" noexcept"));write!(out, " noexcept");
1180    }
1181}
1182
1183fn write_rust_function_shim_impl(
1184    out: &mut OutFile,
1185    local_name: &str,
1186    sig: &Signature,
1187    doc: &Doc,
1188    invoke: &Symbol,
1189    indirect_call: bool,
1190    main: bool,
1191) {
1192    if match sig.kind {
1193        FnKind::Free => false,
1194        FnKind::Method(_) | FnKind::Assoc(_) => out.header,
1195    } {
1196        // We've already defined this inside the struct.
1197        return;
1198    }
1199    out.pragma.dollar_in_identifier = true;
1200    if #[allow(non_exhaustive_omitted_patterns)] match sig.kind {
    FnKind::Free => true,
    _ => false,
}matches!(sig.kind, FnKind::Free) {
1201        // Member functions already documented at their declaration.
1202        write_doc(out, "", doc);
1203    }
1204    let in_class = false;
1205    write_rust_function_shim_decl(out, local_name, sig, in_class, indirect_call, main);
1206    if out.header {
1207        out.write_fmt(format_args!(";\n"));writeln!(out, ";");
1208        return;
1209    }
1210    out.write_fmt(format_args!(" {{\n"));writeln!(out, " {{");
1211    for arg in &sig.args {
1212        if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
1213            out.include.utility = true;
1214            out.builtin.manually_drop = true;
1215            out.write_fmt(format_args!("  ::rust::ManuallyDrop<"));write!(out, "  ::rust::ManuallyDrop<");
1216            write_type(out, &arg.ty);
1217            out.write_fmt(format_args!("> {0}$(::std::move({0}));\n", arg.name.cxx));writeln!(out, "> {}$(::std::move({0}));", arg.name.cxx);
1218        }
1219    }
1220    out.write_fmt(format_args!("  "));write!(out, "  ");
1221    let indirect_return = indirect_return(sig, out.types, Lang::Rust);
1222    if indirect_return {
1223        out.builtin.maybe_uninit = true;
1224        out.write_fmt(format_args!("::rust::MaybeUninit<"));write!(out, "::rust::MaybeUninit<");
1225        match sig.ret.as_ref().unwrap() {
1226            Type::Ref(ret) => {
1227                write_type_space(out, &ret.inner);
1228                if !ret.mutable {
1229                    out.write_fmt(format_args!("const "));write!(out, "const ");
1230                }
1231                out.write_fmt(format_args!("*"));write!(out, "*");
1232            }
1233            ret => write_type(out, ret),
1234        }
1235        out.write_fmt(format_args!("> return$;\n"));writeln!(out, "> return$;");
1236        out.write_fmt(format_args!("  "));write!(out, "  ");
1237    } else if let Some(ret) = &sig.ret {
1238        out.write_fmt(format_args!("return "));write!(out, "return ");
1239        match ret {
1240            Type::RustBox(_) => {
1241                write_type(out, ret);
1242                out.write_fmt(format_args!("::from_raw("));write!(out, "::from_raw(");
1243            }
1244            Type::UniquePtr(_) => {
1245                write_type(out, ret);
1246                out.write_fmt(format_args!("("));write!(out, "(");
1247            }
1248            Type::Ref(_) => out.write_fmt(format_args!("*"))write!(out, "*"),
1249            Type::Str(_) => {
1250                out.builtin.rust_str_new_unchecked = true;
1251                out.write_fmt(format_args!("::rust::impl<::rust::Str>::new_unchecked("));write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
1252            }
1253            Type::SliceRef(_) => {
1254                out.builtin.rust_slice_new = true;
1255                out.write_fmt(format_args!("::rust::impl<"));write!(out, "::rust::impl<");
1256                write_type(out, ret);
1257                out.write_fmt(format_args!(">::slice("));write!(out, ">::slice(");
1258            }
1259            _ => {}
1260        }
1261    }
1262    if sig.throws {
1263        out.builtin.ptr_len = true;
1264        out.write_fmt(format_args!("::rust::repr::PtrLen error$ = "));write!(out, "::rust::repr::PtrLen error$ = ");
1265    }
1266    out.write_fmt(format_args!("{0}(", invoke));write!(out, "{}(", invoke);
1267    let mut needs_comma = false;
1268    if #[allow(non_exhaustive_omitted_patterns)] match sig.kind {
    FnKind::Method(_) => true,
    _ => false,
}matches!(sig.kind, FnKind::Method(_)) {
1269        out.write_fmt(format_args!("*this"));write!(out, "*this");
1270        needs_comma = true;
1271    }
1272    for arg in &sig.args {
1273        if needs_comma {
1274            out.write_fmt(format_args!(", "));write!(out, ", ");
1275        }
1276        if out.types.needs_indirect_abi(&arg.ty) {
1277            out.write_fmt(format_args!("&"));write!(out, "&");
1278        }
1279        out.write_fmt(format_args!("{0}", arg.name.cxx));write!(out, "{}", arg.name.cxx);
1280        match &arg.ty {
1281            Type::RustBox(_) => out.write_fmt(format_args!(".into_raw()"))write!(out, ".into_raw()"),
1282            Type::UniquePtr(_) => out.write_fmt(format_args!(".release()"))write!(out, ".release()"),
1283            ty if ty != RustString && out.types.needs_indirect_abi(ty) => out.write_fmt(format_args!("$.value"))write!(out, "$.value"),
1284            _ => {}
1285        }
1286        needs_comma = true;
1287    }
1288    if indirect_return {
1289        if needs_comma {
1290            out.write_fmt(format_args!(", "));write!(out, ", ");
1291        }
1292        out.write_fmt(format_args!("&return$.value"));write!(out, "&return$.value");
1293        needs_comma = true;
1294    }
1295    if indirect_call {
1296        if needs_comma {
1297            out.write_fmt(format_args!(", "));write!(out, ", ");
1298        }
1299        out.write_fmt(format_args!("extern$"));write!(out, "extern$");
1300    }
1301    out.write_fmt(format_args!(")"));write!(out, ")");
1302    if !indirect_return
1303        && let Some(Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_)) =
1304            &sig.ret
1305    {
1306        out.write_fmt(format_args!(")"));write!(out, ")");
1307    }
1308    out.write_fmt(format_args!(";\n"));writeln!(out, ";");
1309    if sig.throws {
1310        out.builtin.rust_error = true;
1311        out.write_fmt(format_args!("  if (error$.ptr) {{\n"));writeln!(out, "  if (error$.ptr) {{");
1312        out.write_fmt(format_args!("    throw ::rust::impl<::rust::Error>::error(error$);\n"));writeln!(out, "    throw ::rust::impl<::rust::Error>::error(error$);");
1313        out.write_fmt(format_args!("  }}\n"));writeln!(out, "  }}");
1314    }
1315    if indirect_return {
1316        out.write_fmt(format_args!("  return "));write!(out, "  return ");
1317        match sig.ret.as_ref().unwrap() {
1318            Type::Ref(_) => out.write_fmt(format_args!("*return$.value"))write!(out, "*return$.value"),
1319            _ => {
1320                out.include.utility = true;
1321                out.write_fmt(format_args!("::std::move(return$.value)"));write!(out, "::std::move(return$.value)");
1322            }
1323        }
1324        out.write_fmt(format_args!(";\n"));writeln!(out, ";");
1325    }
1326    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1327}
1328
1329fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
1330    match ty {
1331        None => out.write_fmt(format_args!("void "))write!(out, "void "),
1332        Some(ty) => write_type_space(out, ty),
1333    }
1334}
1335
1336fn indirect_return(sig: &Signature, types: &Types, lang: Lang) -> bool {
1337    sig.ret.as_ref().is_some_and(|ret| {
1338        sig.throws
1339            || types.needs_indirect_abi(ret)
1340            || match lang {
1341                Lang::Cxx | Lang::CxxUnwind => types.contains_elided_lifetime(ret),
1342                Lang::Rust => false,
1343            }
1344    })
1345}
1346
1347fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
1348    match ty {
1349        Type::RustBox(ty) | Type::UniquePtr(ty) => {
1350            write_type_space(out, &ty.inner);
1351            out.write_fmt(format_args!("*"));write!(out, "*");
1352        }
1353        Type::Ref(ty) => {
1354            write_type_space(out, &ty.inner);
1355            if !ty.mutable {
1356                out.write_fmt(format_args!("const "));write!(out, "const ");
1357            }
1358            out.write_fmt(format_args!("*"));write!(out, "*");
1359        }
1360        _ => write_type(out, ty),
1361    }
1362}
1363
1364fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
1365    write_indirect_return_type(out, ty);
1366    match ty {
1367        Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
1368        Type::Str(_) | Type::SliceRef(_) => out.write_fmt(format_args!(" "))write!(out, " "),
1369        _ => write_space_after_type(out, ty),
1370    }
1371}
1372
1373fn write_extern_return_type_space(out: &mut OutFile, sig: &Signature, lang: Lang) {
1374    match &sig.ret {
1375        Some(_) if indirect_return(sig, out.types, lang) => out.write_fmt(format_args!("void "))write!(out, "void "),
1376        Some(Type::RustBox(ty) | Type::UniquePtr(ty)) => {
1377            write_type_space(out, &ty.inner);
1378            out.write_fmt(format_args!("*"));write!(out, "*");
1379        }
1380        Some(Type::Ref(ty)) => {
1381            write_type_space(out, &ty.inner);
1382            if !ty.mutable {
1383                out.write_fmt(format_args!("const "));write!(out, "const ");
1384            }
1385            out.write_fmt(format_args!("*"));write!(out, "*");
1386        }
1387        Some(Type::Str(_) | Type::SliceRef(_)) => {
1388            out.builtin.repr_fat = true;
1389            out.write_fmt(format_args!("::rust::repr::Fat "));write!(out, "::rust::repr::Fat ");
1390        }
1391        ty => write_return_type(out, ty),
1392    }
1393}
1394
1395fn write_extern_arg(out: &mut OutFile, arg: &Var) {
1396    match &arg.ty {
1397        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
1398            write_type_space(out, &ty.inner);
1399            out.write_fmt(format_args!("*"));write!(out, "*");
1400        }
1401        _ => write_type_space(out, &arg.ty),
1402    }
1403    if out.types.needs_indirect_abi(&arg.ty) {
1404        out.write_fmt(format_args!("*"));write!(out, "*");
1405    }
1406    out.write_fmt(format_args!("{0}", arg.name.cxx));write!(out, "{}", arg.name.cxx);
1407}
1408
1409fn write_type(out: &mut OutFile, ty: &Type) {
1410    write_type_to_generic_writer(out, ty, out.types);
1411}
1412
1413fn stringify_type(ty: &Type, types: &Types) -> String {
1414    let mut s = String::new();
1415    write_type_to_generic_writer(&mut s, ty, types);
1416    s
1417}
1418
1419fn write_type_to_generic_writer(out: &mut impl InfallibleWrite, ty: &Type, types: &Types) {
1420    match ty {
1421        Type::Ident(ident) => match Atom::from(&ident.rust) {
1422            Some(atom) => write_atom(out, atom),
1423            None => out.write_fmt(format_args!("{0}",
        types.resolve(ident).name.to_fully_qualified()))write!(out, "{}", types.resolve(ident).name.to_fully_qualified()),
1424        },
1425        Type::RustBox(ty) => {
1426            out.write_fmt(format_args!("::rust::Box<"));write!(out, "::rust::Box<");
1427            write_type_to_generic_writer(out, &ty.inner, types);
1428            out.write_fmt(format_args!(">"));write!(out, ">");
1429        }
1430        Type::RustVec(ty) => {
1431            out.write_fmt(format_args!("::rust::Vec<"));write!(out, "::rust::Vec<");
1432            write_type_to_generic_writer(out, &ty.inner, types);
1433            out.write_fmt(format_args!(">"));write!(out, ">");
1434        }
1435        Type::UniquePtr(ptr) => {
1436            out.write_fmt(format_args!("::std::unique_ptr<"));write!(out, "::std::unique_ptr<");
1437            write_type_to_generic_writer(out, &ptr.inner, types);
1438            out.write_fmt(format_args!(">"));write!(out, ">");
1439        }
1440        Type::SharedPtr(ptr) => {
1441            out.write_fmt(format_args!("::std::shared_ptr<"));write!(out, "::std::shared_ptr<");
1442            write_type_to_generic_writer(out, &ptr.inner, types);
1443            out.write_fmt(format_args!(">"));write!(out, ">");
1444        }
1445        Type::WeakPtr(ptr) => {
1446            out.write_fmt(format_args!("::std::weak_ptr<"));write!(out, "::std::weak_ptr<");
1447            write_type_to_generic_writer(out, &ptr.inner, types);
1448            out.write_fmt(format_args!(">"));write!(out, ">");
1449        }
1450        Type::CxxVector(ty) => {
1451            out.write_fmt(format_args!("::std::vector<"));write!(out, "::std::vector<");
1452            write_type_to_generic_writer(out, &ty.inner, types);
1453            out.write_fmt(format_args!(">"));write!(out, ">");
1454        }
1455        Type::Ref(r) => {
1456            write_type_space_to_generic_writer(out, &r.inner, types);
1457            if !r.mutable {
1458                out.write_fmt(format_args!("const "));write!(out, "const ");
1459            }
1460            out.write_fmt(format_args!("&"));write!(out, "&");
1461        }
1462        Type::Ptr(p) => {
1463            write_type_space_to_generic_writer(out, &p.inner, types);
1464            if !p.mutable {
1465                out.write_fmt(format_args!("const "));write!(out, "const ");
1466            }
1467            out.write_fmt(format_args!("*"));write!(out, "*");
1468        }
1469        Type::Str(_) => {
1470            out.write_fmt(format_args!("::rust::Str"));write!(out, "::rust::Str");
1471        }
1472        Type::SliceRef(slice) => {
1473            out.write_fmt(format_args!("::rust::Slice<"));write!(out, "::rust::Slice<");
1474            write_type_space_to_generic_writer(out, &slice.inner, types);
1475            if slice.mutability.is_none() {
1476                out.write_fmt(format_args!("const"));write!(out, "const");
1477            }
1478            out.write_fmt(format_args!(">"));write!(out, ">");
1479        }
1480        Type::Fn(f) => {
1481            out.write_fmt(format_args!("::rust::Fn<"));write!(out, "::rust::Fn<");
1482            match &f.ret {
1483                Some(ret) => write_type_to_generic_writer(out, ret, types),
1484                None => out.write_fmt(format_args!("void"))write!(out, "void"),
1485            }
1486            out.write_fmt(format_args!("("));write!(out, "(");
1487            for (i, arg) in f.args.iter().enumerate() {
1488                if i > 0 {
1489                    out.write_fmt(format_args!(", "));write!(out, ", ");
1490                }
1491                write_type_to_generic_writer(out, &arg.ty, types);
1492            }
1493            out.write_fmt(format_args!(")>"));write!(out, ")>");
1494        }
1495        Type::Array(a) => {
1496            out.write_fmt(format_args!("::std::array<"));write!(out, "::std::array<");
1497            write_type_to_generic_writer(out, &a.inner, types);
1498            out.write_fmt(format_args!(", {0}>", a.len));write!(out, ", {}>", a.len);
1499        }
1500        Type::Void(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1501    }
1502}
1503
1504fn write_atom(out: &mut impl InfallibleWrite, atom: Atom) {
1505    match atom {
1506        Bool => out.write_fmt(format_args!("bool"))write!(out, "bool"),
1507        Char => out.write_fmt(format_args!("char"))write!(out, "char"),
1508        U8 => out.write_fmt(format_args!("::std::uint8_t"))write!(out, "::std::uint8_t"),
1509        U16 => out.write_fmt(format_args!("::std::uint16_t"))write!(out, "::std::uint16_t"),
1510        U32 => out.write_fmt(format_args!("::std::uint32_t"))write!(out, "::std::uint32_t"),
1511        U64 => out.write_fmt(format_args!("::std::uint64_t"))write!(out, "::std::uint64_t"),
1512        Usize => out.write_fmt(format_args!("::std::size_t"))write!(out, "::std::size_t"),
1513        I8 => out.write_fmt(format_args!("::std::int8_t"))write!(out, "::std::int8_t"),
1514        I16 => out.write_fmt(format_args!("::std::int16_t"))write!(out, "::std::int16_t"),
1515        I32 => out.write_fmt(format_args!("::std::int32_t"))write!(out, "::std::int32_t"),
1516        I64 => out.write_fmt(format_args!("::std::int64_t"))write!(out, "::std::int64_t"),
1517        Isize => out.write_fmt(format_args!("::rust::isize"))write!(out, "::rust::isize"),
1518        F32 => out.write_fmt(format_args!("float"))write!(out, "float"),
1519        F64 => out.write_fmt(format_args!("double"))write!(out, "double"),
1520        CxxString => out.write_fmt(format_args!("::std::string"))write!(out, "::std::string"),
1521        RustString => out.write_fmt(format_args!("::rust::String"))write!(out, "::rust::String"),
1522    }
1523}
1524
1525fn write_type_space(out: &mut OutFile, ty: &Type) {
1526    write_type_space_to_generic_writer(out, ty, out.types);
1527}
1528
1529fn write_type_space_to_generic_writer(out: &mut impl InfallibleWrite, ty: &Type, types: &Types) {
1530    write_type_to_generic_writer(out, ty, types);
1531    write_space_after_type(out, ty);
1532}
1533
1534fn write_space_after_type(out: &mut impl InfallibleWrite, ty: &Type) {
1535    match ty {
1536        Type::Ident(_)
1537        | Type::RustBox(_)
1538        | Type::UniquePtr(_)
1539        | Type::SharedPtr(_)
1540        | Type::WeakPtr(_)
1541        | Type::Str(_)
1542        | Type::CxxVector(_)
1543        | Type::RustVec(_)
1544        | Type::SliceRef(_)
1545        | Type::Fn(_)
1546        | Type::Array(_) => out.write_fmt(format_args!(" "))write!(out, " "),
1547        Type::Ref(_) | Type::Ptr(_) => {}
1548        Type::Void(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1549    }
1550}
1551
1552fn write_generic_instantiations(out: &mut OutFile) {
1553    if out.header {
1554        return;
1555    }
1556
1557    out.next_section();
1558    out.set_namespace(Default::default());
1559    out.begin_block(Block::ExternC);
1560    for impl_key in out.types.impls.keys() {
1561        out.next_section();
1562        match impl_key {
1563            ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
1564            ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
1565            ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
1566            ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident),
1567            ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident),
1568            ImplKey::CxxVector(ident) => write_cxx_vector(out, ident),
1569        }
1570    }
1571    out.end_block(Block::ExternC);
1572
1573    out.begin_block(Block::Namespace("rust"));
1574    out.begin_block(Block::InlineNamespace("cxxbridge1"));
1575    for impl_key in out.types.impls.keys() {
1576        match impl_key {
1577            ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
1578            ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
1579            _ => {}
1580        }
1581    }
1582    out.end_block(Block::InlineNamespace("cxxbridge1"));
1583    out.end_block(Block::Namespace("rust"));
1584}
1585
1586fn write_rust_box_extern(out: &mut OutFile, key: &NamedImplKey) {
1587    let inner = stringify_type(key.inner, out.types);
1588    let instance = &key.symbol;
1589
1590    out.pragma.dollar_in_identifier = true;
1591
1592    out.write_fmt(format_args!("{0} *cxxbridge1$box${1}$alloc() noexcept;\n",
        inner, instance));writeln!(
1593        out,
1594        "{} *cxxbridge1$box${}$alloc() noexcept;",
1595        inner, instance,
1596    );
1597    out.write_fmt(format_args!("void cxxbridge1$box${0}$dealloc({1} *) noexcept;\n",
        instance, inner));writeln!(
1598        out,
1599        "void cxxbridge1$box${}$dealloc({} *) noexcept;",
1600        instance, inner,
1601    );
1602    out.write_fmt(format_args!("void cxxbridge1$box${0}$drop(::rust::Box<{1}> *ptr) noexcept;\n",
        instance, inner));writeln!(
1603        out,
1604        "void cxxbridge1$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
1605        instance, inner,
1606    );
1607}
1608
1609fn write_rust_vec_extern(out: &mut OutFile, key: &NamedImplKey) {
1610    let inner = stringify_type(key.inner, out.types);
1611    let instance = &key.symbol;
1612
1613    out.include.cstddef = true;
1614    out.pragma.dollar_in_identifier = true;
1615
1616    out.write_fmt(format_args!("void cxxbridge1$rust_vec${0}$new(::rust::Vec<{1}> const *ptr) noexcept;\n",
        instance, inner));writeln!(
1617        out,
1618        "void cxxbridge1$rust_vec${}$new(::rust::Vec<{}> const *ptr) noexcept;",
1619        instance, inner,
1620    );
1621    out.write_fmt(format_args!("void cxxbridge1$rust_vec${0}$drop(::rust::Vec<{1}> *ptr) noexcept;\n",
        instance, inner));writeln!(
1622        out,
1623        "void cxxbridge1$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
1624        instance, inner,
1625    );
1626    out.write_fmt(format_args!("::std::size_t cxxbridge1$rust_vec${0}$len(::rust::Vec<{1}> const *ptr) noexcept;\n",
        instance, inner));writeln!(
1627        out,
1628        "::std::size_t cxxbridge1$rust_vec${}$len(::rust::Vec<{}> const *ptr) noexcept;",
1629        instance, inner,
1630    );
1631    out.write_fmt(format_args!("::std::size_t cxxbridge1$rust_vec${0}$capacity(::rust::Vec<{1}> const *ptr) noexcept;\n",
        instance, inner));writeln!(
1632        out,
1633        "::std::size_t cxxbridge1$rust_vec${}$capacity(::rust::Vec<{}> const *ptr) noexcept;",
1634        instance, inner,
1635    );
1636    out.write_fmt(format_args!("{0} const *cxxbridge1$rust_vec${1}$data(::rust::Vec<{0}> const *ptr) noexcept;\n",
        inner, instance));writeln!(
1637        out,
1638        "{} const *cxxbridge1$rust_vec${}$data(::rust::Vec<{0}> const *ptr) noexcept;",
1639        inner, instance,
1640    );
1641    out.write_fmt(format_args!("void cxxbridge1$rust_vec${0}$reserve_total(::rust::Vec<{1}> *ptr, ::std::size_t new_cap) noexcept;\n",
        instance, inner));writeln!(
1642        out,
1643        "void cxxbridge1$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, ::std::size_t new_cap) noexcept;",
1644        instance, inner,
1645    );
1646    out.write_fmt(format_args!("void cxxbridge1$rust_vec${0}$set_len(::rust::Vec<{1}> *ptr, ::std::size_t len) noexcept;\n",
        instance, inner));writeln!(
1647        out,
1648        "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
1649        instance, inner,
1650    );
1651    out.write_fmt(format_args!("void cxxbridge1$rust_vec${0}$truncate(::rust::Vec<{1}> *ptr, ::std::size_t len) noexcept;\n",
        instance, inner));writeln!(
1652        out,
1653        "void cxxbridge1$rust_vec${}$truncate(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
1654        instance, inner,
1655    );
1656}
1657
1658fn write_rust_box_impl(out: &mut OutFile, key: &NamedImplKey) {
1659    let inner = stringify_type(key.inner, out.types);
1660    let instance = &key.symbol;
1661
1662    out.pragma.dollar_in_identifier = true;
1663
1664    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1665    begin_function_definition(out);
1666    out.write_fmt(format_args!("{0} *Box<{1}>::allocation::alloc() noexcept {{\n",
        inner, inner));writeln!(
1667        out,
1668        "{} *Box<{}>::allocation::alloc() noexcept {{",
1669        inner, inner,
1670    );
1671    out.write_fmt(format_args!("  return cxxbridge1$box${0}$alloc();\n",
        instance));writeln!(out, "  return cxxbridge1$box${}$alloc();", instance);
1672    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1673
1674    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1675    begin_function_definition(out);
1676    out.write_fmt(format_args!("void Box<{0}>::allocation::dealloc({1} *ptr) noexcept {{\n",
        inner, inner));writeln!(
1677        out,
1678        "void Box<{}>::allocation::dealloc({} *ptr) noexcept {{",
1679        inner, inner,
1680    );
1681    out.write_fmt(format_args!("  cxxbridge1$box${0}$dealloc(ptr);\n", instance));writeln!(out, "  cxxbridge1$box${}$dealloc(ptr);", instance);
1682    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1683
1684    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1685    begin_function_definition(out);
1686    out.write_fmt(format_args!("void Box<{0}>::drop() noexcept {{\n", inner));writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
1687    out.write_fmt(format_args!("  cxxbridge1$box${0}$drop(this);\n", instance));writeln!(out, "  cxxbridge1$box${}$drop(this);", instance);
1688    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1689}
1690
1691fn write_rust_vec_impl(out: &mut OutFile, key: &NamedImplKey) {
1692    let inner = stringify_type(key.inner, out.types);
1693    let instance = &key.symbol;
1694
1695    out.include.cstddef = true;
1696    out.pragma.dollar_in_identifier = true;
1697
1698    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1699    begin_function_definition(out);
1700    out.write_fmt(format_args!("Vec<{0}>::Vec() noexcept {{\n", inner));writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
1701    out.write_fmt(format_args!("  cxxbridge1$rust_vec${0}$new(this);\n",
        instance));writeln!(out, "  cxxbridge1$rust_vec${}$new(this);", instance);
1702    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1703
1704    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1705    begin_function_definition(out);
1706    out.write_fmt(format_args!("void Vec<{0}>::drop() noexcept {{\n", inner));writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
1707    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$drop(this);\n",
        instance));writeln!(out, "  return cxxbridge1$rust_vec${}$drop(this);", instance);
1708    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1709
1710    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1711    begin_function_definition(out);
1712    out.write_fmt(format_args!("::std::size_t Vec<{0}>::size() const noexcept {{\n",
        inner));writeln!(
1713        out,
1714        "::std::size_t Vec<{}>::size() const noexcept {{",
1715        inner,
1716    );
1717    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$len(this);\n",
        instance));writeln!(out, "  return cxxbridge1$rust_vec${}$len(this);", instance);
1718    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1719
1720    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1721    begin_function_definition(out);
1722    out.write_fmt(format_args!("::std::size_t Vec<{0}>::capacity() const noexcept {{\n",
        inner));writeln!(
1723        out,
1724        "::std::size_t Vec<{}>::capacity() const noexcept {{",
1725        inner,
1726    );
1727    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$capacity(this);\n",
        instance));writeln!(
1728        out,
1729        "  return cxxbridge1$rust_vec${}$capacity(this);",
1730        instance,
1731    );
1732    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1733
1734    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1735    begin_function_definition(out);
1736    out.write_fmt(format_args!("{0} const *Vec<{0}>::data() const noexcept {{\n",
        inner));writeln!(out, "{} const *Vec<{0}>::data() const noexcept {{", inner);
1737    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$data(this);\n",
        instance));writeln!(out, "  return cxxbridge1$rust_vec${}$data(this);", instance);
1738    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1739
1740    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1741    begin_function_definition(out);
1742    out.write_fmt(format_args!("void Vec<{0}>::reserve_total(::std::size_t new_cap) noexcept {{\n",
        inner));writeln!(
1743        out,
1744        "void Vec<{}>::reserve_total(::std::size_t new_cap) noexcept {{",
1745        inner,
1746    );
1747    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$reserve_total(this, new_cap);\n",
        instance));writeln!(
1748        out,
1749        "  return cxxbridge1$rust_vec${}$reserve_total(this, new_cap);",
1750        instance,
1751    );
1752    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1753
1754    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1755    begin_function_definition(out);
1756    out.write_fmt(format_args!("void Vec<{0}>::set_len(::std::size_t len) noexcept {{\n",
        inner));writeln!(
1757        out,
1758        "void Vec<{}>::set_len(::std::size_t len) noexcept {{",
1759        inner,
1760    );
1761    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$set_len(this, len);\n",
        instance));writeln!(
1762        out,
1763        "  return cxxbridge1$rust_vec${}$set_len(this, len);",
1764        instance,
1765    );
1766    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1767
1768    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1769    begin_function_definition(out);
1770    out.write_fmt(format_args!("void Vec<{0}>::truncate(::std::size_t len) {{\n",
        inner));writeln!(out, "void Vec<{}>::truncate(::std::size_t len) {{", inner);
1771    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$truncate(this, len);\n",
        instance));writeln!(
1772        out,
1773        "  return cxxbridge1$rust_vec${}$truncate(this, len);",
1774        instance,
1775    );
1776    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1777}
1778
1779fn write_unique_ptr(out: &mut OutFile, key: &NamedImplKey) {
1780    write_unique_ptr_common(out, key.inner);
1781}
1782
1783// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
1784fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
1785    out.include.new = true;
1786    out.include.utility = true;
1787    out.pragma.dollar_in_identifier = true;
1788    out.pragma.missing_declarations = true;
1789
1790    let inner = stringify_type(ty, out.types);
1791    let instance = mangle::typename(ty, &out.types.resolutions)
1792        .expect("unexpected UniquePtr generic parameter allowed through by syntax/check.rs");
1793
1794    // Some aliases are to opaque types; some are to trivial types. We can't
1795    // know at code generation time, so we generate both C++ and Rust side
1796    // bindings for a "new" method anyway. But the Rust code can't be called for
1797    // Opaque types because the 'new' method is not implemented.
1798    let can_construct_from_value = out.types.is_maybe_trivial(ty);
1799
1800    out.builtin.is_complete = true;
1801    out.write_fmt(format_args!("static_assert(::rust::detail::is_complete<::std::remove_extent<{0}>::type>::value, \"definition of `{1}` is required\");\n",
        inner, inner));writeln!(
1802        out,
1803        "static_assert(::rust::detail::is_complete<::std::remove_extent<{}>::type>::value, \"definition of `{}` is required\");",
1804        inner, inner,
1805    );
1806    out.write_fmt(format_args!("static_assert(sizeof(::std::unique_ptr<{0}>) == sizeof(void *), \"\");\n",
        inner));writeln!(
1807        out,
1808        "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
1809        inner,
1810    );
1811    out.write_fmt(format_args!("static_assert(alignof(::std::unique_ptr<{0}>) == alignof(void *), \"\");\n",
        inner));writeln!(
1812        out,
1813        "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
1814        inner,
1815    );
1816
1817    begin_function_definition(out);
1818    out.write_fmt(format_args!("void cxxbridge1$unique_ptr${0}$null(::std::unique_ptr<{1}> *ptr) noexcept {{\n",
        instance, inner));writeln!(
1819        out,
1820        "void cxxbridge1$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
1821        instance, inner,
1822    );
1823    out.write_fmt(format_args!("  ::new (ptr) ::std::unique_ptr<{0}>();\n",
        inner));writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>();", inner);
1824    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1825
1826    if can_construct_from_value {
1827        out.builtin.maybe_uninit = true;
1828        out.pragma.mismatched_new_delete = true;
1829        begin_function_definition(out);
1830        out.write_fmt(format_args!("{0} *cxxbridge1$unique_ptr${1}$uninit(::std::unique_ptr<{2}> *ptr) noexcept {{\n",
        inner, instance, inner));writeln!(
1831            out,
1832            "{} *cxxbridge1$unique_ptr${}$uninit(::std::unique_ptr<{}> *ptr) noexcept {{",
1833            inner, instance, inner,
1834        );
1835        out.write_fmt(format_args!("  {0} *uninit = reinterpret_cast<{1} *>(new ::rust::MaybeUninit<{2}>);\n",
        inner, inner, inner));writeln!(
1836            out,
1837            "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
1838            inner, inner, inner,
1839        );
1840        out.write_fmt(format_args!("  ::new (ptr) ::std::unique_ptr<{0}>(uninit);\n",
        inner));writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>(uninit);", inner);
1841        out.write_fmt(format_args!("  return uninit;\n"));writeln!(out, "  return uninit;");
1842        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1843    }
1844
1845    begin_function_definition(out);
1846    out.write_fmt(format_args!("void cxxbridge1$unique_ptr${0}$raw(::std::unique_ptr<{1}> *ptr, ::std::unique_ptr<{2}>::pointer raw) noexcept {{\n",
        instance, inner, inner));writeln!(
1847        out,
1848        "void cxxbridge1$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, ::std::unique_ptr<{}>::pointer raw) noexcept {{",
1849        instance, inner, inner,
1850    );
1851    out.write_fmt(format_args!("  ::new (ptr) ::std::unique_ptr<{0}>(raw);\n",
        inner));writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>(raw);", inner);
1852    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1853
1854    begin_function_definition(out);
1855    out.write_fmt(format_args!("::std::unique_ptr<{0}>::element_type const *cxxbridge1$unique_ptr${1}$get(::std::unique_ptr<{2}> const &ptr) noexcept {{\n",
        inner, instance, inner));writeln!(
1856        out,
1857        "::std::unique_ptr<{}>::element_type const *cxxbridge1$unique_ptr${}$get(::std::unique_ptr<{}> const &ptr) noexcept {{",
1858        inner, instance, inner,
1859    );
1860    out.write_fmt(format_args!("  return ptr.get();\n"));writeln!(out, "  return ptr.get();");
1861    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1862
1863    begin_function_definition(out);
1864    out.write_fmt(format_args!("::std::unique_ptr<{0}>::pointer cxxbridge1$unique_ptr${1}$release(::std::unique_ptr<{2}> &ptr) noexcept {{\n",
        inner, instance, inner));writeln!(
1865        out,
1866        "::std::unique_ptr<{}>::pointer cxxbridge1$unique_ptr${}$release(::std::unique_ptr<{}> &ptr) noexcept {{",
1867        inner, instance, inner,
1868    );
1869    out.write_fmt(format_args!("  return ptr.release();\n"));writeln!(out, "  return ptr.release();");
1870    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1871
1872    begin_function_definition(out);
1873    out.write_fmt(format_args!("void cxxbridge1$unique_ptr${0}$drop(::std::unique_ptr<{1}> *ptr) noexcept {{\n",
        instance, inner));writeln!(
1874        out,
1875        "void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
1876        instance, inner,
1877    );
1878    out.builtin.deleter_if = true;
1879    out.write_fmt(format_args!("  ::rust::deleter_if<::rust::detail::is_complete<{0}>::value>{{}}(ptr);\n",
        inner));writeln!(
1880        out,
1881        "  ::rust::deleter_if<::rust::detail::is_complete<{}>::value>{{}}(ptr);",
1882        inner,
1883    );
1884    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1885}
1886
1887fn write_shared_ptr(out: &mut OutFile, key: &NamedImplKey) {
1888    let inner = stringify_type(key.inner, out.types);
1889    let instance = &key.symbol;
1890
1891    out.include.new = true;
1892    out.include.utility = true;
1893    out.pragma.dollar_in_identifier = true;
1894    out.pragma.missing_declarations = true;
1895
1896    // Some aliases are to opaque types; some are to trivial types. We can't
1897    // know at code generation time, so we generate both C++ and Rust side
1898    // bindings for a "new" method anyway. But the Rust code can't be called for
1899    // Opaque types because the 'new' method is not implemented.
1900    let can_construct_from_value = out.types.is_maybe_trivial(key.inner);
1901
1902    out.write_fmt(format_args!("static_assert(sizeof(::std::shared_ptr<{0}>) == 2 * sizeof(void *), \"\");\n",
        inner));writeln!(
1903        out,
1904        "static_assert(sizeof(::std::shared_ptr<{}>) == 2 * sizeof(void *), \"\");",
1905        inner,
1906    );
1907    out.write_fmt(format_args!("static_assert(alignof(::std::shared_ptr<{0}>) == alignof(void *), \"\");\n",
        inner));writeln!(
1908        out,
1909        "static_assert(alignof(::std::shared_ptr<{}>) == alignof(void *), \"\");",
1910        inner,
1911    );
1912
1913    begin_function_definition(out);
1914    out.write_fmt(format_args!("void cxxbridge1$shared_ptr${0}$null(::std::shared_ptr<{1}> *ptr) noexcept {{\n",
        instance, inner));writeln!(
1915        out,
1916        "void cxxbridge1$shared_ptr${}$null(::std::shared_ptr<{}> *ptr) noexcept {{",
1917        instance, inner,
1918    );
1919    out.write_fmt(format_args!("  ::new (ptr) ::std::shared_ptr<{0}>();\n",
        inner));writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>();", inner);
1920    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1921
1922    if can_construct_from_value {
1923        out.builtin.maybe_uninit = true;
1924        out.pragma.mismatched_new_delete = true;
1925        begin_function_definition(out);
1926        out.write_fmt(format_args!("{0} *cxxbridge1$shared_ptr${1}$uninit(::std::shared_ptr<{2}> *ptr) noexcept {{\n",
        inner, instance, inner));writeln!(
1927            out,
1928            "{} *cxxbridge1$shared_ptr${}$uninit(::std::shared_ptr<{}> *ptr) noexcept {{",
1929            inner, instance, inner,
1930        );
1931        out.write_fmt(format_args!("  {0} *uninit = reinterpret_cast<{1} *>(new ::rust::MaybeUninit<{2}>);\n",
        inner, inner, inner));writeln!(
1932            out,
1933            "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
1934            inner, inner, inner,
1935        );
1936        out.write_fmt(format_args!("  ::new (ptr) ::std::shared_ptr<{0}>(uninit);\n",
        inner));writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>(uninit);", inner);
1937        out.write_fmt(format_args!("  return uninit;\n"));writeln!(out, "  return uninit;");
1938        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1939    }
1940
1941    out.builtin.shared_ptr = true;
1942    begin_function_definition(out);
1943    out.write_fmt(format_args!("bool cxxbridge1$shared_ptr${0}$raw(::std::shared_ptr<{1}> *ptr, ::std::shared_ptr<{2}>::element_type *raw) noexcept {{\n",
        instance, inner, inner));writeln!(
1944        out,
1945        "bool cxxbridge1$shared_ptr${}$raw(::std::shared_ptr<{}> *ptr, ::std::shared_ptr<{}>::element_type *raw) noexcept {{",
1946        instance, inner, inner,
1947    );
1948    out.write_fmt(format_args!("  ::new (ptr) ::rust::shared_ptr_if_destructible<{0}>(raw);\n",
        inner));writeln!(
1949        out,
1950        "  ::new (ptr) ::rust::shared_ptr_if_destructible<{}>(raw);",
1951        inner,
1952    );
1953    out.write_fmt(format_args!("  return ::rust::is_destructible<{0}>::value;\n",
        inner));writeln!(out, "  return ::rust::is_destructible<{}>::value;", inner);
1954    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1955
1956    begin_function_definition(out);
1957    out.write_fmt(format_args!("void cxxbridge1$shared_ptr${0}$clone(::std::shared_ptr<{1}> const &self, ::std::shared_ptr<{2}> *ptr) noexcept {{\n",
        instance, inner, inner));writeln!(
1958        out,
1959        "void cxxbridge1$shared_ptr${}$clone(::std::shared_ptr<{}> const &self, ::std::shared_ptr<{}> *ptr) noexcept {{",
1960        instance, inner, inner,
1961    );
1962    out.write_fmt(format_args!("  ::new (ptr) ::std::shared_ptr<{0}>(self);\n",
        inner));writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>(self);", inner);
1963    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1964
1965    begin_function_definition(out);
1966    out.write_fmt(format_args!("::std::shared_ptr<{0}>::element_type const *cxxbridge1$shared_ptr${1}$get(::std::shared_ptr<{2}> const &self) noexcept {{\n",
        inner, instance, inner));writeln!(
1967        out,
1968        "::std::shared_ptr<{}>::element_type const *cxxbridge1$shared_ptr${}$get(::std::shared_ptr<{}> const &self) noexcept {{",
1969        inner, instance, inner,
1970    );
1971    out.write_fmt(format_args!("  return self.get();\n"));writeln!(out, "  return self.get();");
1972    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1973
1974    begin_function_definition(out);
1975    out.write_fmt(format_args!("void cxxbridge1$shared_ptr${0}$drop(::std::shared_ptr<{1}> *self) noexcept {{\n",
        instance, inner));writeln!(
1976        out,
1977        "void cxxbridge1$shared_ptr${}$drop(::std::shared_ptr<{}> *self) noexcept {{",
1978        instance, inner,
1979    );
1980    out.write_fmt(format_args!("  self->~shared_ptr();\n"));writeln!(out, "  self->~shared_ptr();");
1981    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1982}
1983
1984fn write_weak_ptr(out: &mut OutFile, key: &NamedImplKey) {
1985    let inner = stringify_type(key.inner, out.types);
1986    let instance = &key.symbol;
1987
1988    out.include.new = true;
1989    out.include.utility = true;
1990    out.pragma.dollar_in_identifier = true;
1991    out.pragma.missing_declarations = true;
1992
1993    out.write_fmt(format_args!("static_assert(sizeof(::std::weak_ptr<{0}>) == 2 * sizeof(void *), \"\");\n",
        inner));writeln!(
1994        out,
1995        "static_assert(sizeof(::std::weak_ptr<{}>) == 2 * sizeof(void *), \"\");",
1996        inner,
1997    );
1998    out.write_fmt(format_args!("static_assert(alignof(::std::weak_ptr<{0}>) == alignof(void *), \"\");\n",
        inner));writeln!(
1999        out,
2000        "static_assert(alignof(::std::weak_ptr<{}>) == alignof(void *), \"\");",
2001        inner,
2002    );
2003
2004    begin_function_definition(out);
2005    out.write_fmt(format_args!("void cxxbridge1$weak_ptr${0}$null(::std::weak_ptr<{1}> *ptr) noexcept {{\n",
        instance, inner));writeln!(
2006        out,
2007        "void cxxbridge1$weak_ptr${}$null(::std::weak_ptr<{}> *ptr) noexcept {{",
2008        instance, inner,
2009    );
2010    out.write_fmt(format_args!("  ::new (ptr) ::std::weak_ptr<{0}>();\n", inner));writeln!(out, "  ::new (ptr) ::std::weak_ptr<{}>();", inner);
2011    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2012
2013    begin_function_definition(out);
2014    out.write_fmt(format_args!("void cxxbridge1$weak_ptr${0}$clone(::std::weak_ptr<{1}> const &self, ::std::weak_ptr<{2}> *ptr) noexcept {{\n",
        instance, inner, inner));writeln!(
2015        out,
2016        "void cxxbridge1$weak_ptr${}$clone(::std::weak_ptr<{}> const &self, ::std::weak_ptr<{}> *ptr) noexcept {{",
2017        instance, inner, inner,
2018    );
2019    out.write_fmt(format_args!("  ::new (ptr) ::std::weak_ptr<{0}>(self);\n",
        inner));writeln!(out, "  ::new (ptr) ::std::weak_ptr<{}>(self);", inner);
2020    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2021
2022    begin_function_definition(out);
2023    out.write_fmt(format_args!("void cxxbridge1$weak_ptr${0}$downgrade(::std::shared_ptr<{1}> const &shared, ::std::weak_ptr<{2}> *weak) noexcept {{\n",
        instance, inner, inner));writeln!(
2024        out,
2025        "void cxxbridge1$weak_ptr${}$downgrade(::std::shared_ptr<{}> const &shared, ::std::weak_ptr<{}> *weak) noexcept {{",
2026        instance, inner, inner,
2027    );
2028    out.write_fmt(format_args!("  ::new (weak) ::std::weak_ptr<{0}>(shared);\n",
        inner));writeln!(out, "  ::new (weak) ::std::weak_ptr<{}>(shared);", inner);
2029    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2030
2031    begin_function_definition(out);
2032    out.write_fmt(format_args!("void cxxbridge1$weak_ptr${0}$upgrade(::std::weak_ptr<{1}> const &weak, ::std::shared_ptr<{2}> *shared) noexcept {{\n",
        instance, inner, inner));writeln!(
2033        out,
2034        "void cxxbridge1$weak_ptr${}$upgrade(::std::weak_ptr<{}> const &weak, ::std::shared_ptr<{}> *shared) noexcept {{",
2035        instance, inner, inner,
2036    );
2037    out.write_fmt(format_args!("  ::new (shared) ::std::shared_ptr<{0}>(weak.lock());\n",
        inner));writeln!(
2038        out,
2039        "  ::new (shared) ::std::shared_ptr<{}>(weak.lock());",
2040        inner,
2041    );
2042    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2043
2044    begin_function_definition(out);
2045    out.write_fmt(format_args!("void cxxbridge1$weak_ptr${0}$drop(::std::weak_ptr<{1}> *self) noexcept {{\n",
        instance, inner));writeln!(
2046        out,
2047        "void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{",
2048        instance, inner,
2049    );
2050    out.write_fmt(format_args!("  self->~weak_ptr();\n"));writeln!(out, "  self->~weak_ptr();");
2051    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2052}
2053
2054fn write_cxx_vector(out: &mut OutFile, key: &NamedImplKey) {
2055    let inner = stringify_type(key.inner, out.types);
2056    let instance = &key.symbol;
2057
2058    out.include.cstddef = true;
2059    out.include.utility = true;
2060    out.builtin.destroy = true;
2061    out.builtin.vector = true;
2062    out.pragma.dollar_in_identifier = true;
2063    out.pragma.missing_declarations = true;
2064
2065    begin_function_definition(out);
2066    out.write_fmt(format_args!("::std::vector<{0}> *cxxbridge1$std$vector${1}$new() noexcept {{\n",
        inner, instance));writeln!(
2067        out,
2068        "::std::vector<{}> *cxxbridge1$std$vector${}$new() noexcept {{",
2069        inner, instance,
2070    );
2071    out.write_fmt(format_args!("  return new ::std::vector<{0}>();\n", inner));writeln!(out, "  return new ::std::vector<{}>();", inner);
2072    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2073
2074    begin_function_definition(out);
2075    out.write_fmt(format_args!("::std::size_t cxxbridge1$std$vector${0}$size(::std::vector<{1}> const &s) noexcept {{\n",
        instance, inner));writeln!(
2076        out,
2077        "::std::size_t cxxbridge1$std$vector${}$size(::std::vector<{}> const &s) noexcept {{",
2078        instance, inner,
2079    );
2080    out.write_fmt(format_args!("  return s.size();\n"));writeln!(out, "  return s.size();");
2081    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2082
2083    begin_function_definition(out);
2084    out.write_fmt(format_args!("::std::size_t cxxbridge1$std$vector${0}$capacity(::std::vector<{1}> const &s) noexcept {{\n",
        instance, inner));writeln!(
2085        out,
2086        "::std::size_t cxxbridge1$std$vector${}$capacity(::std::vector<{}> const &s) noexcept {{",
2087        instance, inner,
2088    );
2089    out.write_fmt(format_args!("  return s.capacity();\n"));writeln!(out, "  return s.capacity();");
2090    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2091
2092    begin_function_definition(out);
2093    out.write_fmt(format_args!("{0} *cxxbridge1$std$vector${1}$get_unchecked(::std::vector<{2}> *s, ::std::size_t pos) noexcept {{\n",
        inner, instance, inner));writeln!(
2094        out,
2095        "{} *cxxbridge1$std$vector${}$get_unchecked(::std::vector<{}> *s, ::std::size_t pos) noexcept {{",
2096        inner, instance, inner,
2097    );
2098    out.write_fmt(format_args!("  return &(*s)[pos];\n"));writeln!(out, "  return &(*s)[pos];");
2099    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2100
2101    begin_function_definition(out);
2102    out.write_fmt(format_args!("bool cxxbridge1$std$vector${0}$reserve(::std::vector<{1}> *s, ::std::size_t new_cap) noexcept {{\n",
        instance, inner));writeln!(
2103        out,
2104        "bool cxxbridge1$std$vector${}$reserve(::std::vector<{}> *s, ::std::size_t new_cap) noexcept {{",
2105        instance, inner,
2106    );
2107    out.write_fmt(format_args!("  return ::rust::if_move_constructible<{0}>::reserve(*s, new_cap);\n",
        inner));writeln!(
2108        out,
2109        "  return ::rust::if_move_constructible<{}>::reserve(*s, new_cap);",
2110        inner,
2111    );
2112    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2113
2114    if out.types.is_maybe_trivial(key.inner) {
2115        begin_function_definition(out);
2116        out.write_fmt(format_args!("void cxxbridge1$std$vector${0}$push_back(::std::vector<{1}> *v, {2} *value) noexcept {{\n",
        instance, inner, inner));writeln!(
2117            out,
2118            "void cxxbridge1$std$vector${}$push_back(::std::vector<{}> *v, {} *value) noexcept {{",
2119            instance, inner, inner,
2120        );
2121        out.write_fmt(format_args!("  v->push_back(::std::move(*value));\n"));writeln!(out, "  v->push_back(::std::move(*value));");
2122        out.write_fmt(format_args!("  ::rust::destroy(value);\n"));writeln!(out, "  ::rust::destroy(value);");
2123        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2124
2125        begin_function_definition(out);
2126        out.write_fmt(format_args!("void cxxbridge1$std$vector${0}$pop_back(::std::vector<{1}> *v, {2} *out) noexcept {{\n",
        instance, inner, inner));writeln!(
2127            out,
2128            "void cxxbridge1$std$vector${}$pop_back(::std::vector<{}> *v, {} *out) noexcept {{",
2129            instance, inner, inner,
2130        );
2131        out.write_fmt(format_args!("  ::new (out) {0}(::std::move(v->back()));\n",
        inner));writeln!(out, "  ::new (out) {}(::std::move(v->back()));", inner);
2132        out.write_fmt(format_args!("  v->pop_back();\n"));writeln!(out, "  v->pop_back();");
2133        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2134    }
2135
2136    out.include.memory = true;
2137    write_unique_ptr_common(out, key.outer);
2138}