cxx_build/gen/
write.rs

1use crate::gen::block::Block;
2use crate::gen::guard::Guard;
3use crate::gen::nested::NamespaceEntries;
4use crate::gen::out::{InfallibleWrite, OutFile};
5use crate::gen::{builtin, include, pragma, Opt};
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    derive, mangle, Api, Doc, Enum, ExternFn, ExternType, FnKind, Lang, Pair, Signature, Struct,
17    Trait, Type, TypeAlias, Types, Var,
18};
19
20pub(super) fn gen(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            if !out.types.cxx.contains(&strct.name.rust) {
45                for field in &strct.fields {
46                    needs_default_value |= primitive::kind(&field.ty).is_some();
47                }
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            if let Some(self_type) = efn.self_type() {
102                methods_for_type
103                    .entry(self_type)
104                    .or_insert_with(Vec::new)
105                    .push(efn);
106            }
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            if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
160                check_trivial_extern_type(out, ety, reasons);
161            }
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            if derive::contains(&strct.derives, Trait::Hash) {
201                out.next_section();
202                out.include.cstddef = true;
203                out.include.functional = true;
204                out.pragma.dollar_in_identifier = true;
205                let qualified = strct.name.to_fully_qualified();
206                out.write_fmt(format_args!("template <> struct hash<{0}> {{\n", qualified));writeln!(out, "template <> struct hash<{}> {{", qualified);
207                out.write_fmt(format_args!("  ::std::size_t operator()({0} const &self) const noexcept {{\n",
        qualified));writeln!(
208                    out,
209                    "  ::std::size_t operator()({} const &self) const noexcept {{",
210                    qualified,
211                );
212                let link_name = mangle::operator(&strct.name, "hash");
213                out.write_fmt(format_args!("    return ::"));write!(out, "    return ::");
214                for name in &strct.name.namespace {
215                    out.write_fmt(format_args!("{0}::", name));write!(out, "{}::", name);
216                }
217                out.write_fmt(format_args!("{0}(self);\n", link_name));writeln!(out, "{}(self);", link_name);
218                out.write_fmt(format_args!("  }}\n"));writeln!(out, "  }}");
219                out.write_fmt(format_args!("}};\n"));writeln!(out, "}};");
220            }
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}) == \n", enm.name.cxx,
        variant.name.cxx));writeln!(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        if !receiver.mutable {
922            out.write_fmt(format_args!(" const"));write!(out, " const");
923        }
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        if !receiver.mutable {
1175            out.write_fmt(format_args!(" const"));write!(out, " const");
1176        }
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        if let Some(Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_)) =
1304            &sig.ret
1305        {
1306            out.write_fmt(format_args!(")"));write!(out, ")");
1307        }
1308    }
1309    out.write_fmt(format_args!(";\n"));writeln!(out, ";");
1310    if sig.throws {
1311        out.builtin.rust_error = true;
1312        out.write_fmt(format_args!("  if (error$.ptr) {{\n"));writeln!(out, "  if (error$.ptr) {{");
1313        out.write_fmt(format_args!("    throw ::rust::impl<::rust::Error>::error(error$);\n"));writeln!(out, "    throw ::rust::impl<::rust::Error>::error(error$);");
1314        out.write_fmt(format_args!("  }}\n"));writeln!(out, "  }}");
1315    }
1316    if indirect_return {
1317        out.write_fmt(format_args!("  return "));write!(out, "  return ");
1318        match sig.ret.as_ref().unwrap() {
1319            Type::Ref(_) => out.write_fmt(format_args!("*return$.value"))write!(out, "*return$.value"),
1320            _ => {
1321                out.include.utility = true;
1322                out.write_fmt(format_args!("::std::move(return$.value)"));write!(out, "::std::move(return$.value)");
1323            }
1324        }
1325        out.write_fmt(format_args!(";\n"));writeln!(out, ";");
1326    }
1327    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1328}
1329
1330fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
1331    match ty {
1332        None => out.write_fmt(format_args!("void "))write!(out, "void "),
1333        Some(ty) => write_type_space(out, ty),
1334    }
1335}
1336
1337fn indirect_return(sig: &Signature, types: &Types, lang: Lang) -> bool {
1338    sig.ret.as_ref().is_some_and(|ret| {
1339        sig.throws
1340            || types.needs_indirect_abi(ret)
1341            || match lang {
1342                Lang::Cxx | Lang::CxxUnwind => types.contains_elided_lifetime(ret),
1343                Lang::Rust => false,
1344            }
1345    })
1346}
1347
1348fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
1349    match ty {
1350        Type::RustBox(ty) | Type::UniquePtr(ty) => {
1351            write_type_space(out, &ty.inner);
1352            out.write_fmt(format_args!("*"));write!(out, "*");
1353        }
1354        Type::Ref(ty) => {
1355            write_type_space(out, &ty.inner);
1356            if !ty.mutable {
1357                out.write_fmt(format_args!("const "));write!(out, "const ");
1358            }
1359            out.write_fmt(format_args!("*"));write!(out, "*");
1360        }
1361        _ => write_type(out, ty),
1362    }
1363}
1364
1365fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
1366    write_indirect_return_type(out, ty);
1367    match ty {
1368        Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
1369        Type::Str(_) | Type::SliceRef(_) => out.write_fmt(format_args!(" "))write!(out, " "),
1370        _ => write_space_after_type(out, ty),
1371    }
1372}
1373
1374fn write_extern_return_type_space(out: &mut OutFile, sig: &Signature, lang: Lang) {
1375    match &sig.ret {
1376        Some(_) if indirect_return(sig, out.types, lang) => out.write_fmt(format_args!("void "))write!(out, "void "),
1377        Some(Type::RustBox(ty) | Type::UniquePtr(ty)) => {
1378            write_type_space(out, &ty.inner);
1379            out.write_fmt(format_args!("*"));write!(out, "*");
1380        }
1381        Some(Type::Ref(ty)) => {
1382            write_type_space(out, &ty.inner);
1383            if !ty.mutable {
1384                out.write_fmt(format_args!("const "));write!(out, "const ");
1385            }
1386            out.write_fmt(format_args!("*"));write!(out, "*");
1387        }
1388        Some(Type::Str(_) | Type::SliceRef(_)) => {
1389            out.builtin.repr_fat = true;
1390            out.write_fmt(format_args!("::rust::repr::Fat "));write!(out, "::rust::repr::Fat ");
1391        }
1392        ty => write_return_type(out, ty),
1393    }
1394}
1395
1396fn write_extern_arg(out: &mut OutFile, arg: &Var) {
1397    match &arg.ty {
1398        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
1399            write_type_space(out, &ty.inner);
1400            out.write_fmt(format_args!("*"));write!(out, "*");
1401        }
1402        _ => write_type_space(out, &arg.ty),
1403    }
1404    if out.types.needs_indirect_abi(&arg.ty) {
1405        out.write_fmt(format_args!("*"));write!(out, "*");
1406    }
1407    out.write_fmt(format_args!("{0}", arg.name.cxx));write!(out, "{}", arg.name.cxx);
1408}
1409
1410fn write_type(out: &mut OutFile, ty: &Type) {
1411    write_type_to_generic_writer(out, ty, out.types);
1412}
1413
1414fn stringify_type(ty: &Type, types: &Types) -> String {
1415    let mut s = String::new();
1416    write_type_to_generic_writer(&mut s, ty, types);
1417    s
1418}
1419
1420fn write_type_to_generic_writer(out: &mut impl InfallibleWrite, ty: &Type, types: &Types) {
1421    match ty {
1422        Type::Ident(ident) => match Atom::from(&ident.rust) {
1423            Some(atom) => write_atom(out, atom),
1424            None => out.write_fmt(format_args!("{0}",
        types.resolve(ident).name.to_fully_qualified()))write!(out, "{}", types.resolve(ident).name.to_fully_qualified()),
1425        },
1426        Type::RustBox(ty) => {
1427            out.write_fmt(format_args!("::rust::Box<"));write!(out, "::rust::Box<");
1428            write_type_to_generic_writer(out, &ty.inner, types);
1429            out.write_fmt(format_args!(">"));write!(out, ">");
1430        }
1431        Type::RustVec(ty) => {
1432            out.write_fmt(format_args!("::rust::Vec<"));write!(out, "::rust::Vec<");
1433            write_type_to_generic_writer(out, &ty.inner, types);
1434            out.write_fmt(format_args!(">"));write!(out, ">");
1435        }
1436        Type::UniquePtr(ptr) => {
1437            out.write_fmt(format_args!("::std::unique_ptr<"));write!(out, "::std::unique_ptr<");
1438            write_type_to_generic_writer(out, &ptr.inner, types);
1439            out.write_fmt(format_args!(">"));write!(out, ">");
1440        }
1441        Type::SharedPtr(ptr) => {
1442            out.write_fmt(format_args!("::std::shared_ptr<"));write!(out, "::std::shared_ptr<");
1443            write_type_to_generic_writer(out, &ptr.inner, types);
1444            out.write_fmt(format_args!(">"));write!(out, ">");
1445        }
1446        Type::WeakPtr(ptr) => {
1447            out.write_fmt(format_args!("::std::weak_ptr<"));write!(out, "::std::weak_ptr<");
1448            write_type_to_generic_writer(out, &ptr.inner, types);
1449            out.write_fmt(format_args!(">"));write!(out, ">");
1450        }
1451        Type::CxxVector(ty) => {
1452            out.write_fmt(format_args!("::std::vector<"));write!(out, "::std::vector<");
1453            write_type_to_generic_writer(out, &ty.inner, types);
1454            out.write_fmt(format_args!(">"));write!(out, ">");
1455        }
1456        Type::Ref(r) => {
1457            write_type_space_to_generic_writer(out, &r.inner, types);
1458            if !r.mutable {
1459                out.write_fmt(format_args!("const "));write!(out, "const ");
1460            }
1461            out.write_fmt(format_args!("&"));write!(out, "&");
1462        }
1463        Type::Ptr(p) => {
1464            write_type_space_to_generic_writer(out, &p.inner, types);
1465            if !p.mutable {
1466                out.write_fmt(format_args!("const "));write!(out, "const ");
1467            }
1468            out.write_fmt(format_args!("*"));write!(out, "*");
1469        }
1470        Type::Str(_) => {
1471            out.write_fmt(format_args!("::rust::Str"));write!(out, "::rust::Str");
1472        }
1473        Type::SliceRef(slice) => {
1474            out.write_fmt(format_args!("::rust::Slice<"));write!(out, "::rust::Slice<");
1475            write_type_space_to_generic_writer(out, &slice.inner, types);
1476            if slice.mutability.is_none() {
1477                out.write_fmt(format_args!("const"));write!(out, "const");
1478            }
1479            out.write_fmt(format_args!(">"));write!(out, ">");
1480        }
1481        Type::Fn(f) => {
1482            out.write_fmt(format_args!("::rust::Fn<"));write!(out, "::rust::Fn<");
1483            match &f.ret {
1484                Some(ret) => write_type_to_generic_writer(out, ret, types),
1485                None => out.write_fmt(format_args!("void"))write!(out, "void"),
1486            }
1487            out.write_fmt(format_args!("("));write!(out, "(");
1488            for (i, arg) in f.args.iter().enumerate() {
1489                if i > 0 {
1490                    out.write_fmt(format_args!(", "));write!(out, ", ");
1491                }
1492                write_type_to_generic_writer(out, &arg.ty, types);
1493            }
1494            out.write_fmt(format_args!(")>"));write!(out, ")>");
1495        }
1496        Type::Array(a) => {
1497            out.write_fmt(format_args!("::std::array<"));write!(out, "::std::array<");
1498            write_type_to_generic_writer(out, &a.inner, types);
1499            out.write_fmt(format_args!(", {0}>", &a.len));write!(out, ", {}>", &a.len);
1500        }
1501        Type::Void(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1502    }
1503}
1504
1505fn write_atom(out: &mut impl InfallibleWrite, atom: Atom) {
1506    match atom {
1507        Bool => out.write_fmt(format_args!("bool"))write!(out, "bool"),
1508        Char => out.write_fmt(format_args!("char"))write!(out, "char"),
1509        U8 => out.write_fmt(format_args!("::std::uint8_t"))write!(out, "::std::uint8_t"),
1510        U16 => out.write_fmt(format_args!("::std::uint16_t"))write!(out, "::std::uint16_t"),
1511        U32 => out.write_fmt(format_args!("::std::uint32_t"))write!(out, "::std::uint32_t"),
1512        U64 => out.write_fmt(format_args!("::std::uint64_t"))write!(out, "::std::uint64_t"),
1513        Usize => out.write_fmt(format_args!("::std::size_t"))write!(out, "::std::size_t"),
1514        I8 => out.write_fmt(format_args!("::std::int8_t"))write!(out, "::std::int8_t"),
1515        I16 => out.write_fmt(format_args!("::std::int16_t"))write!(out, "::std::int16_t"),
1516        I32 => out.write_fmt(format_args!("::std::int32_t"))write!(out, "::std::int32_t"),
1517        I64 => out.write_fmt(format_args!("::std::int64_t"))write!(out, "::std::int64_t"),
1518        Isize => out.write_fmt(format_args!("::rust::isize"))write!(out, "::rust::isize"),
1519        F32 => out.write_fmt(format_args!("float"))write!(out, "float"),
1520        F64 => out.write_fmt(format_args!("double"))write!(out, "double"),
1521        CxxString => out.write_fmt(format_args!("::std::string"))write!(out, "::std::string"),
1522        RustString => out.write_fmt(format_args!("::rust::String"))write!(out, "::rust::String"),
1523    }
1524}
1525
1526fn write_type_space(out: &mut OutFile, ty: &Type) {
1527    write_type_space_to_generic_writer(out, ty, out.types);
1528}
1529
1530fn write_type_space_to_generic_writer(out: &mut impl InfallibleWrite, ty: &Type, types: &Types) {
1531    write_type_to_generic_writer(out, ty, types);
1532    write_space_after_type(out, ty);
1533}
1534
1535fn write_space_after_type(out: &mut impl InfallibleWrite, ty: &Type) {
1536    match ty {
1537        Type::Ident(_)
1538        | Type::RustBox(_)
1539        | Type::UniquePtr(_)
1540        | Type::SharedPtr(_)
1541        | Type::WeakPtr(_)
1542        | Type::Str(_)
1543        | Type::CxxVector(_)
1544        | Type::RustVec(_)
1545        | Type::SliceRef(_)
1546        | Type::Fn(_)
1547        | Type::Array(_) => out.write_fmt(format_args!(" "))write!(out, " "),
1548        Type::Ref(_) | Type::Ptr(_) => {}
1549        Type::Void(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1550    }
1551}
1552
1553fn write_generic_instantiations(out: &mut OutFile) {
1554    if out.header {
1555        return;
1556    }
1557
1558    out.next_section();
1559    out.set_namespace(Default::default());
1560    out.begin_block(Block::ExternC);
1561    for impl_key in out.types.impls.keys() {
1562        out.next_section();
1563        match impl_key {
1564            ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
1565            ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
1566            ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
1567            ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident),
1568            ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident),
1569            ImplKey::CxxVector(ident) => write_cxx_vector(out, ident),
1570        }
1571    }
1572    out.end_block(Block::ExternC);
1573
1574    out.begin_block(Block::Namespace("rust"));
1575    out.begin_block(Block::InlineNamespace("cxxbridge1"));
1576    for impl_key in out.types.impls.keys() {
1577        match impl_key {
1578            ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
1579            ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
1580            _ => {}
1581        }
1582    }
1583    out.end_block(Block::InlineNamespace("cxxbridge1"));
1584    out.end_block(Block::Namespace("rust"));
1585}
1586
1587fn write_rust_box_extern(out: &mut OutFile, key: &NamedImplKey) {
1588    let inner = stringify_type(key.inner, out.types);
1589    let instance = &key.symbol;
1590
1591    out.pragma.dollar_in_identifier = true;
1592
1593    out.write_fmt(format_args!("{0} *cxxbridge1$box${1}$alloc() noexcept;\n",
        inner, instance));writeln!(
1594        out,
1595        "{} *cxxbridge1$box${}$alloc() noexcept;",
1596        inner, instance,
1597    );
1598    out.write_fmt(format_args!("void cxxbridge1$box${0}$dealloc({1} *) noexcept;\n",
        instance, inner));writeln!(
1599        out,
1600        "void cxxbridge1$box${}$dealloc({} *) noexcept;",
1601        instance, inner,
1602    );
1603    out.write_fmt(format_args!("void cxxbridge1$box${0}$drop(::rust::Box<{1}> *ptr) noexcept;\n",
        instance, inner));writeln!(
1604        out,
1605        "void cxxbridge1$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
1606        instance, inner,
1607    );
1608}
1609
1610fn write_rust_vec_extern(out: &mut OutFile, key: &NamedImplKey) {
1611    let inner = stringify_type(key.inner, out.types);
1612    let instance = &key.symbol;
1613
1614    out.include.cstddef = true;
1615    out.pragma.dollar_in_identifier = true;
1616
1617    out.write_fmt(format_args!("void cxxbridge1$rust_vec${0}$new(::rust::Vec<{1}> const *ptr) noexcept;\n",
        instance, inner));writeln!(
1618        out,
1619        "void cxxbridge1$rust_vec${}$new(::rust::Vec<{}> const *ptr) noexcept;",
1620        instance, inner,
1621    );
1622    out.write_fmt(format_args!("void cxxbridge1$rust_vec${0}$drop(::rust::Vec<{1}> *ptr) noexcept;\n",
        instance, inner));writeln!(
1623        out,
1624        "void cxxbridge1$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
1625        instance, inner,
1626    );
1627    out.write_fmt(format_args!("::std::size_t cxxbridge1$rust_vec${0}$len(::rust::Vec<{1}> const *ptr) noexcept;\n",
        instance, inner));writeln!(
1628        out,
1629        "::std::size_t cxxbridge1$rust_vec${}$len(::rust::Vec<{}> const *ptr) noexcept;",
1630        instance, inner,
1631    );
1632    out.write_fmt(format_args!("::std::size_t cxxbridge1$rust_vec${0}$capacity(::rust::Vec<{1}> const *ptr) noexcept;\n",
        instance, inner));writeln!(
1633        out,
1634        "::std::size_t cxxbridge1$rust_vec${}$capacity(::rust::Vec<{}> const *ptr) noexcept;",
1635        instance, inner,
1636    );
1637    out.write_fmt(format_args!("{0} const *cxxbridge1$rust_vec${1}$data(::rust::Vec<{0}> const *ptr) noexcept;\n",
        inner, instance));writeln!(
1638        out,
1639        "{} const *cxxbridge1$rust_vec${}$data(::rust::Vec<{0}> const *ptr) noexcept;",
1640        inner, instance,
1641    );
1642    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!(
1643        out,
1644        "void cxxbridge1$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, ::std::size_t new_cap) noexcept;",
1645        instance, inner,
1646    );
1647    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!(
1648        out,
1649        "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
1650        instance, inner,
1651    );
1652    out.write_fmt(format_args!("void cxxbridge1$rust_vec${0}$truncate(::rust::Vec<{1}> *ptr, ::std::size_t len) noexcept;\n",
        instance, inner));writeln!(
1653        out,
1654        "void cxxbridge1$rust_vec${}$truncate(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
1655        instance, inner,
1656    );
1657}
1658
1659fn write_rust_box_impl(out: &mut OutFile, key: &NamedImplKey) {
1660    let inner = stringify_type(key.inner, out.types);
1661    let instance = &key.symbol;
1662
1663    out.pragma.dollar_in_identifier = true;
1664
1665    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1666    begin_function_definition(out);
1667    out.write_fmt(format_args!("{0} *Box<{1}>::allocation::alloc() noexcept {{\n",
        inner, inner));writeln!(
1668        out,
1669        "{} *Box<{}>::allocation::alloc() noexcept {{",
1670        inner, inner,
1671    );
1672    out.write_fmt(format_args!("  return cxxbridge1$box${0}$alloc();\n",
        instance));writeln!(out, "  return cxxbridge1$box${}$alloc();", instance);
1673    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1674
1675    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1676    begin_function_definition(out);
1677    out.write_fmt(format_args!("void Box<{0}>::allocation::dealloc({1} *ptr) noexcept {{\n",
        inner, inner));writeln!(
1678        out,
1679        "void Box<{}>::allocation::dealloc({} *ptr) noexcept {{",
1680        inner, inner,
1681    );
1682    out.write_fmt(format_args!("  cxxbridge1$box${0}$dealloc(ptr);\n", instance));writeln!(out, "  cxxbridge1$box${}$dealloc(ptr);", instance);
1683    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1684
1685    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1686    begin_function_definition(out);
1687    out.write_fmt(format_args!("void Box<{0}>::drop() noexcept {{\n", inner));writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
1688    out.write_fmt(format_args!("  cxxbridge1$box${0}$drop(this);\n", instance));writeln!(out, "  cxxbridge1$box${}$drop(this);", instance);
1689    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1690}
1691
1692fn write_rust_vec_impl(out: &mut OutFile, key: &NamedImplKey) {
1693    let inner = stringify_type(key.inner, out.types);
1694    let instance = &key.symbol;
1695
1696    out.include.cstddef = true;
1697    out.pragma.dollar_in_identifier = true;
1698
1699    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1700    begin_function_definition(out);
1701    out.write_fmt(format_args!("Vec<{0}>::Vec() noexcept {{\n", inner));writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
1702    out.write_fmt(format_args!("  cxxbridge1$rust_vec${0}$new(this);\n",
        instance));writeln!(out, "  cxxbridge1$rust_vec${}$new(this);", instance);
1703    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1704
1705    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1706    begin_function_definition(out);
1707    out.write_fmt(format_args!("void Vec<{0}>::drop() noexcept {{\n", inner));writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
1708    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$drop(this);\n",
        instance));writeln!(out, "  return cxxbridge1$rust_vec${}$drop(this);", instance);
1709    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1710
1711    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1712    begin_function_definition(out);
1713    out.write_fmt(format_args!("::std::size_t Vec<{0}>::size() const noexcept {{\n",
        inner));writeln!(
1714        out,
1715        "::std::size_t Vec<{}>::size() const noexcept {{",
1716        inner,
1717    );
1718    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$len(this);\n",
        instance));writeln!(out, "  return cxxbridge1$rust_vec${}$len(this);", instance);
1719    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1720
1721    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1722    begin_function_definition(out);
1723    out.write_fmt(format_args!("::std::size_t Vec<{0}>::capacity() const noexcept {{\n",
        inner));writeln!(
1724        out,
1725        "::std::size_t Vec<{}>::capacity() const noexcept {{",
1726        inner,
1727    );
1728    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$capacity(this);\n",
        instance));writeln!(
1729        out,
1730        "  return cxxbridge1$rust_vec${}$capacity(this);",
1731        instance,
1732    );
1733    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1734
1735    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1736    begin_function_definition(out);
1737    out.write_fmt(format_args!("{0} const *Vec<{0}>::data() const noexcept {{\n",
        inner));writeln!(out, "{} const *Vec<{0}>::data() const noexcept {{", inner);
1738    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$data(this);\n",
        instance));writeln!(out, "  return cxxbridge1$rust_vec${}$data(this);", instance);
1739    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1740
1741    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1742    begin_function_definition(out);
1743    out.write_fmt(format_args!("void Vec<{0}>::reserve_total(::std::size_t new_cap) noexcept {{\n",
        inner));writeln!(
1744        out,
1745        "void Vec<{}>::reserve_total(::std::size_t new_cap) noexcept {{",
1746        inner,
1747    );
1748    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$reserve_total(this, new_cap);\n",
        instance));writeln!(
1749        out,
1750        "  return cxxbridge1$rust_vec${}$reserve_total(this, new_cap);",
1751        instance,
1752    );
1753    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1754
1755    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1756    begin_function_definition(out);
1757    out.write_fmt(format_args!("void Vec<{0}>::set_len(::std::size_t len) noexcept {{\n",
        inner));writeln!(
1758        out,
1759        "void Vec<{}>::set_len(::std::size_t len) noexcept {{",
1760        inner,
1761    );
1762    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$set_len(this, len);\n",
        instance));writeln!(
1763        out,
1764        "  return cxxbridge1$rust_vec${}$set_len(this, len);",
1765        instance,
1766    );
1767    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1768
1769    out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
1770    begin_function_definition(out);
1771    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);
1772    out.write_fmt(format_args!("  return cxxbridge1$rust_vec${0}$truncate(this, len);\n",
        instance));writeln!(
1773        out,
1774        "  return cxxbridge1$rust_vec${}$truncate(this, len);",
1775        instance,
1776    );
1777    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1778}
1779
1780fn write_unique_ptr(out: &mut OutFile, key: &NamedImplKey) {
1781    write_unique_ptr_common(out, key.inner);
1782}
1783
1784// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
1785fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
1786    out.include.new = true;
1787    out.include.utility = true;
1788    out.pragma.dollar_in_identifier = true;
1789    out.pragma.missing_declarations = true;
1790
1791    let inner = stringify_type(ty, out.types);
1792    let instance = mangle::typename(ty, &out.types.resolutions)
1793        .expect("unexpected UniquePtr generic parameter allowed through by syntax/check.rs");
1794
1795    // Some aliases are to opaque types; some are to trivial types. We can't
1796    // know at code generation time, so we generate both C++ and Rust side
1797    // bindings for a "new" method anyway. But the Rust code can't be called for
1798    // Opaque types because the 'new' method is not implemented.
1799    let can_construct_from_value = out.types.is_maybe_trivial(ty);
1800
1801    out.builtin.is_complete = true;
1802    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!(
1803        out,
1804        "static_assert(::rust::detail::is_complete<::std::remove_extent<{}>::type>::value, \"definition of `{}` is required\");",
1805        inner, inner,
1806    );
1807    out.write_fmt(format_args!("static_assert(sizeof(::std::unique_ptr<{0}>) == sizeof(void *), \"\");\n",
        inner));writeln!(
1808        out,
1809        "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
1810        inner,
1811    );
1812    out.write_fmt(format_args!("static_assert(alignof(::std::unique_ptr<{0}>) == alignof(void *), \"\");\n",
        inner));writeln!(
1813        out,
1814        "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
1815        inner,
1816    );
1817
1818    begin_function_definition(out);
1819    out.write_fmt(format_args!("void cxxbridge1$unique_ptr${0}$null(::std::unique_ptr<{1}> *ptr) noexcept {{\n",
        instance, inner));writeln!(
1820        out,
1821        "void cxxbridge1$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
1822        instance, inner,
1823    );
1824    out.write_fmt(format_args!("  ::new (ptr) ::std::unique_ptr<{0}>();\n",
        inner));writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>();", inner);
1825    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1826
1827    if can_construct_from_value {
1828        out.builtin.maybe_uninit = 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        begin_function_definition(out);
1925        out.write_fmt(format_args!("{0} *cxxbridge1$shared_ptr${1}$uninit(::std::shared_ptr<{2}> *ptr) noexcept {{\n",
        inner, instance, inner));writeln!(
1926            out,
1927            "{} *cxxbridge1$shared_ptr${}$uninit(::std::shared_ptr<{}> *ptr) noexcept {{",
1928            inner, instance, inner,
1929        );
1930        out.write_fmt(format_args!("  {0} *uninit = reinterpret_cast<{1} *>(new ::rust::MaybeUninit<{2}>);\n",
        inner, inner, inner));writeln!(
1931            out,
1932            "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
1933            inner, inner, inner,
1934        );
1935        out.write_fmt(format_args!("  ::new (ptr) ::std::shared_ptr<{0}>(uninit);\n",
        inner));writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>(uninit);", inner);
1936        out.write_fmt(format_args!("  return uninit;\n"));writeln!(out, "  return uninit;");
1937        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1938    }
1939
1940    out.builtin.shared_ptr = true;
1941    begin_function_definition(out);
1942    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!(
1943        out,
1944        "bool cxxbridge1$shared_ptr${}$raw(::std::shared_ptr<{}> *ptr, ::std::shared_ptr<{}>::element_type *raw) noexcept {{",
1945        instance, inner, inner,
1946    );
1947    out.write_fmt(format_args!("  ::new (ptr) ::rust::shared_ptr_if_destructible<{0}>(raw);\n",
        inner));writeln!(
1948        out,
1949        "  ::new (ptr) ::rust::shared_ptr_if_destructible<{}>(raw);",
1950        inner,
1951    );
1952    out.write_fmt(format_args!("  return ::rust::is_destructible<{0}>::value;\n",
        inner));writeln!(out, "  return ::rust::is_destructible<{}>::value;", inner);
1953    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1954
1955    begin_function_definition(out);
1956    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!(
1957        out,
1958        "void cxxbridge1$shared_ptr${}$clone(::std::shared_ptr<{}> const &self, ::std::shared_ptr<{}> *ptr) noexcept {{",
1959        instance, inner, inner,
1960    );
1961    out.write_fmt(format_args!("  ::new (ptr) ::std::shared_ptr<{0}>(self);\n",
        inner));writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>(self);", inner);
1962    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1963
1964    begin_function_definition(out);
1965    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!(
1966        out,
1967        "::std::shared_ptr<{}>::element_type const *cxxbridge1$shared_ptr${}$get(::std::shared_ptr<{}> const &self) noexcept {{",
1968        inner, instance, inner,
1969    );
1970    out.write_fmt(format_args!("  return self.get();\n"));writeln!(out, "  return self.get();");
1971    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1972
1973    begin_function_definition(out);
1974    out.write_fmt(format_args!("void cxxbridge1$shared_ptr${0}$drop(::std::shared_ptr<{1}> *self) noexcept {{\n",
        instance, inner));writeln!(
1975        out,
1976        "void cxxbridge1$shared_ptr${}$drop(::std::shared_ptr<{}> *self) noexcept {{",
1977        instance, inner,
1978    );
1979    out.write_fmt(format_args!("  self->~shared_ptr();\n"));writeln!(out, "  self->~shared_ptr();");
1980    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
1981}
1982
1983fn write_weak_ptr(out: &mut OutFile, key: &NamedImplKey) {
1984    let inner = stringify_type(key.inner, out.types);
1985    let instance = &key.symbol;
1986
1987    out.include.new = true;
1988    out.include.utility = true;
1989    out.pragma.dollar_in_identifier = true;
1990    out.pragma.missing_declarations = true;
1991
1992    out.write_fmt(format_args!("static_assert(sizeof(::std::weak_ptr<{0}>) == 2 * sizeof(void *), \"\");\n",
        inner));writeln!(
1993        out,
1994        "static_assert(sizeof(::std::weak_ptr<{}>) == 2 * sizeof(void *), \"\");",
1995        inner,
1996    );
1997    out.write_fmt(format_args!("static_assert(alignof(::std::weak_ptr<{0}>) == alignof(void *), \"\");\n",
        inner));writeln!(
1998        out,
1999        "static_assert(alignof(::std::weak_ptr<{}>) == alignof(void *), \"\");",
2000        inner,
2001    );
2002
2003    begin_function_definition(out);
2004    out.write_fmt(format_args!("void cxxbridge1$weak_ptr${0}$null(::std::weak_ptr<{1}> *ptr) noexcept {{\n",
        instance, inner));writeln!(
2005        out,
2006        "void cxxbridge1$weak_ptr${}$null(::std::weak_ptr<{}> *ptr) noexcept {{",
2007        instance, inner,
2008    );
2009    out.write_fmt(format_args!("  ::new (ptr) ::std::weak_ptr<{0}>();\n", inner));writeln!(out, "  ::new (ptr) ::std::weak_ptr<{}>();", inner);
2010    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2011
2012    begin_function_definition(out);
2013    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!(
2014        out,
2015        "void cxxbridge1$weak_ptr${}$clone(::std::weak_ptr<{}> const &self, ::std::weak_ptr<{}> *ptr) noexcept {{",
2016        instance, inner, inner,
2017    );
2018    out.write_fmt(format_args!("  ::new (ptr) ::std::weak_ptr<{0}>(self);\n",
        inner));writeln!(out, "  ::new (ptr) ::std::weak_ptr<{}>(self);", inner);
2019    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2020
2021    begin_function_definition(out);
2022    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!(
2023        out,
2024        "void cxxbridge1$weak_ptr${}$downgrade(::std::shared_ptr<{}> const &shared, ::std::weak_ptr<{}> *weak) noexcept {{",
2025        instance, inner, inner,
2026    );
2027    out.write_fmt(format_args!("  ::new (weak) ::std::weak_ptr<{0}>(shared);\n",
        inner));writeln!(out, "  ::new (weak) ::std::weak_ptr<{}>(shared);", inner);
2028    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2029
2030    begin_function_definition(out);
2031    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!(
2032        out,
2033        "void cxxbridge1$weak_ptr${}$upgrade(::std::weak_ptr<{}> const &weak, ::std::shared_ptr<{}> *shared) noexcept {{",
2034        instance, inner, inner,
2035    );
2036    out.write_fmt(format_args!("  ::new (shared) ::std::shared_ptr<{0}>(weak.lock());\n",
        inner));writeln!(
2037        out,
2038        "  ::new (shared) ::std::shared_ptr<{}>(weak.lock());",
2039        inner,
2040    );
2041    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2042
2043    begin_function_definition(out);
2044    out.write_fmt(format_args!("void cxxbridge1$weak_ptr${0}$drop(::std::weak_ptr<{1}> *self) noexcept {{\n",
        instance, inner));writeln!(
2045        out,
2046        "void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{",
2047        instance, inner,
2048    );
2049    out.write_fmt(format_args!("  self->~weak_ptr();\n"));writeln!(out, "  self->~weak_ptr();");
2050    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2051}
2052
2053fn write_cxx_vector(out: &mut OutFile, key: &NamedImplKey) {
2054    let inner = stringify_type(key.inner, out.types);
2055    let instance = &key.symbol;
2056
2057    out.include.cstddef = true;
2058    out.include.utility = true;
2059    out.builtin.destroy = true;
2060    out.builtin.vector = true;
2061    out.pragma.dollar_in_identifier = true;
2062    out.pragma.missing_declarations = true;
2063
2064    begin_function_definition(out);
2065    out.write_fmt(format_args!("::std::vector<{0}> *cxxbridge1$std$vector${1}$new() noexcept {{\n",
        inner, instance));writeln!(
2066        out,
2067        "::std::vector<{}> *cxxbridge1$std$vector${}$new() noexcept {{",
2068        inner, instance,
2069    );
2070    out.write_fmt(format_args!("  return new ::std::vector<{0}>();\n", inner));writeln!(out, "  return new ::std::vector<{}>();", inner);
2071    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2072
2073    begin_function_definition(out);
2074    out.write_fmt(format_args!("::std::size_t cxxbridge1$std$vector${0}$size(::std::vector<{1}> const &s) noexcept {{\n",
        instance, inner));writeln!(
2075        out,
2076        "::std::size_t cxxbridge1$std$vector${}$size(::std::vector<{}> const &s) noexcept {{",
2077        instance, inner,
2078    );
2079    out.write_fmt(format_args!("  return s.size();\n"));writeln!(out, "  return s.size();");
2080    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2081
2082    begin_function_definition(out);
2083    out.write_fmt(format_args!("::std::size_t cxxbridge1$std$vector${0}$capacity(::std::vector<{1}> const &s) noexcept {{\n",
        instance, inner));writeln!(
2084        out,
2085        "::std::size_t cxxbridge1$std$vector${}$capacity(::std::vector<{}> const &s) noexcept {{",
2086        instance, inner,
2087    );
2088    out.write_fmt(format_args!("  return s.capacity();\n"));writeln!(out, "  return s.capacity();");
2089    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2090
2091    begin_function_definition(out);
2092    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!(
2093        out,
2094        "{} *cxxbridge1$std$vector${}$get_unchecked(::std::vector<{}> *s, ::std::size_t pos) noexcept {{",
2095        inner, instance, inner,
2096    );
2097    out.write_fmt(format_args!("  return &(*s)[pos];\n"));writeln!(out, "  return &(*s)[pos];");
2098    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2099
2100    begin_function_definition(out);
2101    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!(
2102        out,
2103        "bool cxxbridge1$std$vector${}$reserve(::std::vector<{}> *s, ::std::size_t new_cap) noexcept {{",
2104        instance, inner,
2105    );
2106    out.write_fmt(format_args!("  return ::rust::if_move_constructible<{0}>::reserve(*s, new_cap);\n",
        inner));writeln!(
2107        out,
2108        "  return ::rust::if_move_constructible<{}>::reserve(*s, new_cap);",
2109        inner,
2110    );
2111    out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2112
2113    if out.types.is_maybe_trivial(key.inner) {
2114        begin_function_definition(out);
2115        out.write_fmt(format_args!("void cxxbridge1$std$vector${0}$push_back(::std::vector<{1}> *v, {2} *value) noexcept {{\n",
        instance, inner, inner));writeln!(
2116            out,
2117            "void cxxbridge1$std$vector${}$push_back(::std::vector<{}> *v, {} *value) noexcept {{",
2118            instance, inner, inner,
2119        );
2120        out.write_fmt(format_args!("  v->push_back(::std::move(*value));\n"));writeln!(out, "  v->push_back(::std::move(*value));");
2121        out.write_fmt(format_args!("  ::rust::destroy(value);\n"));writeln!(out, "  ::rust::destroy(value);");
2122        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2123
2124        begin_function_definition(out);
2125        out.write_fmt(format_args!("void cxxbridge1$std$vector${0}$pop_back(::std::vector<{1}> *v, {2} *out) noexcept {{\n",
        instance, inner, inner));writeln!(
2126            out,
2127            "void cxxbridge1$std$vector${}$pop_back(::std::vector<{}> *v, {} *out) noexcept {{",
2128            instance, inner, inner,
2129        );
2130        out.write_fmt(format_args!("  ::new (out) {0}(::std::move(v->back()));\n",
        inner));writeln!(out, "  ::new (out) {}(::std::move(v->back()));", inner);
2131        out.write_fmt(format_args!("  v->pop_back();\n"));writeln!(out, "  v->pop_back();");
2132        out.write_fmt(format_args!("}}\n"));writeln!(out, "}}");
2133    }
2134
2135    out.include.memory = true;
2136    write_unique_ptr_common(out, key.outer);
2137}