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 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 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 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 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 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 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
1784fn 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 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 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}