blob: 2fd0f704002bec5c47ce39f2fd705d77cc320994 [file] [log] [blame]
David Tolnay0c033e32020-11-01 15:15:48 -08001use crate::gen::block::Block;
David Tolnayf7b81fb2020-11-01 22:39:04 -08002use crate::gen::nested::NamespaceEntries;
David Tolnay8810a542020-10-31 21:39:22 -07003use crate::gen::out::OutFile;
David Tolnay942cffd2020-11-03 18:27:10 -08004use crate::gen::{builtin, include, Opt};
David Tolnay7db73692019-10-20 14:51:12 -04005use crate::syntax::atom::Atom::{self, *};
David Tolnay891061b2020-04-19 22:42:33 -07006use crate::syntax::symbol::Symbol;
Adrian Taylorc8713432020-10-21 18:20:55 -07007use crate::syntax::{
David Tolnayb960ed22020-11-27 14:34:30 -08008 derive, mangle, Api, Enum, ExternFn, ExternType, Pair, ResolvableName, Signature, Struct,
9 Trait, Type, Types, Var,
Adrian Taylorc8713432020-10-21 18:20:55 -070010};
David Tolnay7db73692019-10-20 14:51:12 -040011use proc_macro2::Ident;
David Tolnay5439fa12020-11-03 18:45:01 -080012use std::collections::{HashMap, HashSet};
David Tolnay7db73692019-10-20 14:51:12 -040013
David Tolnayac7188c2020-11-01 16:58:16 -080014pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u8> {
David Tolnaye1476af2020-11-01 13:47:25 -080015 let mut out_file = OutFile::new(header, opt, types);
David Tolnay7db73692019-10-20 14:51:12 -040016 let out = &mut out_file;
17
David Tolnaydfb82d72020-11-02 00:10:10 -080018 pick_includes_and_builtins(out, apis);
David Tolnay4aae7c02020-10-28 12:35:42 -070019 out.include.extend(&opt.include);
David Tolnay7db73692019-10-20 14:51:12 -040020
David Tolnay7b0e5102020-11-01 23:22:12 -080021 write_forward_declarations(out, apis);
David Tolnaye1109d92020-11-01 20:51:56 -080022 write_data_structures(out, apis);
23 write_functions(out, apis);
David Tolnay169bb472020-11-01 21:04:24 -080024 write_generic_instantiations(out);
David Tolnay7db73692019-10-20 14:51:12 -040025
David Tolnay3374d8d2020-10-31 22:18:45 -070026 builtin::write(out);
David Tolnay2f3e90b2020-10-31 22:16:51 -070027 include::write(out);
Adrian Taylorc8713432020-10-21 18:20:55 -070028
David Tolnayac7188c2020-11-01 16:58:16 -080029 out_file.content()
Adrian Taylorc8713432020-10-21 18:20:55 -070030}
31
David Tolnay7b0e5102020-11-01 23:22:12 -080032fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
33 let needs_forward_declaration = |api: &&Api| match api {
David Tolnay4bfca112020-11-01 23:59:11 -080034 Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true,
David Tolnay17a934c2020-11-02 00:40:04 -080035 Api::Enum(enm) => !out.types.cxx.contains(&enm.name.rust),
David Tolnay7b0e5102020-11-01 23:22:12 -080036 _ => false,
37 };
Adrian Taylorc8713432020-10-21 18:20:55 -070038
David Tolnay7b0e5102020-11-01 23:22:12 -080039 let apis_by_namespace =
40 NamespaceEntries::new(apis.iter().filter(needs_forward_declaration).collect());
41
David Tolnayd920be52020-11-01 23:34:30 -080042 write(out, &apis_by_namespace, 0);
David Tolnay7b0e5102020-11-01 23:22:12 -080043
David Tolnayd920be52020-11-01 23:34:30 -080044 fn write(out: &mut OutFile, ns_entries: &NamespaceEntries, indent: usize) {
David Tolnay7b0e5102020-11-01 23:22:12 -080045 let apis = ns_entries.direct_content();
46
47 for api in apis {
David Tolnayd920be52020-11-01 23:34:30 -080048 write!(out, "{:1$}", "", indent);
David Tolnay7b0e5102020-11-01 23:22:12 -080049 match api {
David Tolnay17a934c2020-11-02 00:40:04 -080050 Api::Struct(strct) => write_struct_decl(out, &strct.name.cxx),
David Tolnay0e3ee8e2020-11-01 23:46:52 -080051 Api::Enum(enm) => write_enum_decl(out, enm),
David Tolnay17a934c2020-11-02 00:40:04 -080052 Api::CxxType(ety) => write_struct_using(out, &ety.name),
53 Api::RustType(ety) => write_struct_decl(out, &ety.name.cxx),
David Tolnay7b0e5102020-11-01 23:22:12 -080054 _ => unreachable!(),
55 }
David Tolnay7db73692019-10-20 14:51:12 -040056 }
David Tolnay7db73692019-10-20 14:51:12 -040057
David Tolnay7b0e5102020-11-01 23:22:12 -080058 for (namespace, nested_ns_entries) in ns_entries.nested_content() {
David Tolnayd920be52020-11-01 23:34:30 -080059 writeln!(out, "{:2$}namespace {} {{", "", namespace, indent);
60 write(out, nested_ns_entries, indent + 2);
61 writeln!(out, "{:1$}}}", "", indent);
David Tolnay7b0e5102020-11-01 23:22:12 -080062 }
Adrian Taylorf9213622020-10-31 22:25:42 -070063 }
64}
65
David Tolnaye1109d92020-11-01 20:51:56 -080066fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
David Tolnayf94bef12020-04-17 14:46:42 -070067 let mut methods_for_type = HashMap::new();
David Tolnay630af882020-10-31 22:03:47 -070068 for api in apis {
David Tolnay102c7ea2020-11-08 18:58:09 -080069 if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
David Tolnayf94bef12020-04-17 14:46:42 -070070 if let Some(receiver) = &efn.sig.receiver {
71 methods_for_type
Adrian Taylorc8713432020-10-21 18:20:55 -070072 .entry(&receiver.ty.rust)
David Tolnayf94bef12020-04-17 14:46:42 -070073 .or_insert_with(Vec::new)
74 .push(efn);
75 }
76 }
77 }
Joel Galenson968738f2020-04-15 14:19:33 -070078
David Tolnay5439fa12020-11-03 18:45:01 -080079 let mut structs_written = HashSet::new();
80 let mut toposorted_structs = out.types.toposorted_structs.iter();
David Tolnay9622b462020-11-02 21:34:42 -080081 for api in apis {
Joel Galensonc1c4e7a2020-04-15 10:21:00 -070082 match api {
David Tolnay5439fa12020-11-03 18:45:01 -080083 Api::Struct(strct) if !structs_written.contains(&strct.name.rust) => {
84 for next in &mut toposorted_structs {
85 if !out.types.cxx.contains(&strct.name.rust) {
86 out.next_section();
David Tolnay102c7ea2020-11-08 18:58:09 -080087 let methods = methods_for_type
88 .get(&strct.name.rust)
89 .map(Vec::as_slice)
90 .unwrap_or_default();
91 write_struct(out, next, methods);
David Tolnay5439fa12020-11-03 18:45:01 -080092 }
93 structs_written.insert(&next.name.rust);
94 if next.name.rust == strct.name.rust {
95 break;
96 }
97 }
98 }
Joel Galensonc03402a2020-04-23 17:31:09 -070099 Api::Enum(enm) => {
100 out.next_section();
David Tolnay17a934c2020-11-02 00:40:04 -0800101 if out.types.cxx.contains(&enm.name.rust) {
Joel Galenson905eb2e2020-05-04 14:58:14 -0700102 check_enum(out, enm);
103 } else {
104 write_enum(out, enm);
105 }
Joel Galensonc03402a2020-04-23 17:31:09 -0700106 }
David Tolnayc1fe0052020-04-17 15:15:06 -0700107 Api::RustType(ety) => {
David Tolnay17a934c2020-11-02 00:40:04 -0800108 if let Some(methods) = methods_for_type.get(&ety.name.rust) {
David Tolnay46a54e72020-04-17 14:48:21 -0700109 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700110 write_struct_with_methods(out, ety, methods);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700111 }
David Tolnayc1fe0052020-04-17 15:15:06 -0700112 }
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700113 _ => {}
David Tolnay7db73692019-10-20 14:51:12 -0400114 }
115 }
116
David Tolnayfabca772020-10-03 21:25:41 -0700117 out.next_section();
118 for api in apis {
119 if let Api::TypeAlias(ety) = api {
David Tolnay17a934c2020-11-02 00:40:04 -0800120 if out.types.required_trivial.contains_key(&ety.name.rust) {
121 check_trivial_extern_type(out, &ety.name)
David Tolnayfabca772020-10-03 21:25:41 -0700122 }
123 }
124 }
David Tolnay1b0339c2020-11-01 20:37:50 -0800125}
126
David Tolnaye1109d92020-11-01 20:51:56 -0800127fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
David Tolnayce5a91f2020-10-31 22:42:08 -0700128 if !out.header {
David Tolnay7db73692019-10-20 14:51:12 -0400129 for api in apis {
David Tolnay04770742020-11-01 13:50:50 -0800130 match api {
David Tolnayb960ed22020-11-27 14:34:30 -0800131 Api::Struct(strct) => write_struct_operator_decls(out, strct),
David Tolnay04770742020-11-01 13:50:50 -0800132 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
133 Api::RustFunction(efn) => write_rust_function_decl(out, efn),
134 _ => {}
135 }
David Tolnay7db73692019-10-20 14:51:12 -0400136 }
David Tolnay7db73692019-10-20 14:51:12 -0400137 }
138
139 for api in apis {
David Tolnayb960ed22020-11-27 14:34:30 -0800140 match api {
141 Api::Struct(strct) => write_struct_operators(out, strct),
142 Api::RustFunction(efn) => {
143 out.next_section();
144 write_rust_function_shim(out, efn);
145 }
146 _ => {}
David Tolnay7db73692019-10-20 14:51:12 -0400147 }
148 }
David Tolnay7db73692019-10-20 14:51:12 -0400149}
150
David Tolnaydfb82d72020-11-02 00:10:10 -0800151fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
152 for api in apis {
153 if let Api::Include(include) = api {
154 out.include.insert(include);
155 }
156 }
157
David Tolnaya7c2ea12020-10-30 21:32:53 -0700158 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -0400159 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -0700160 Type::Ident(ident) => match Atom::from(&ident.rust) {
David Tolnay89e386d2020-10-03 19:02:19 -0700161 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
162 | Some(I64) => out.include.cstdint = true,
163 Some(Usize) => out.include.cstddef = true,
David Tolnaydcfa8e92020-11-02 09:50:06 -0800164 Some(Isize) => out.builtin.rust_isize = true,
David Tolnay89e386d2020-10-03 19:02:19 -0700165 Some(CxxString) => out.include.string = true,
David Tolnaydcfa8e92020-11-02 09:50:06 -0800166 Some(RustString) => out.builtin.rust_string = true,
David Tolnayb3873dc2020-11-25 19:47:49 -0800167 Some(Bool) | Some(Char) | Some(F32) | Some(F64) | None => {}
David Tolnay89e386d2020-10-03 19:02:19 -0700168 },
David Tolnaydcfa8e92020-11-02 09:50:06 -0800169 Type::RustBox(_) => out.builtin.rust_box = true,
170 Type::RustVec(_) => out.builtin.rust_vec = true,
David Tolnayb9da1462020-10-31 21:03:41 -0700171 Type::UniquePtr(_) => out.include.memory = true,
David Tolnaydcfa8e92020-11-02 09:50:06 -0800172 Type::Str(_) => out.builtin.rust_str = true,
David Tolnayb9da1462020-10-31 21:03:41 -0700173 Type::CxxVector(_) => out.include.vector = true,
David Tolnaydcfa8e92020-11-02 09:50:06 -0800174 Type::Fn(_) => out.builtin.rust_fn = true,
David Tolnay5515a9e2020-11-25 19:07:54 -0800175 Type::SliceRef(_) => out.builtin.rust_slice = true,
David Tolnaye8b1bb42020-11-24 20:37:37 -0800176 Type::Array(_) => out.include.array = true,
David Tolnay11bd7ff2020-11-01 19:44:58 -0800177 Type::Ref(_) | Type::Void(_) => {}
David Tolnay7db73692019-10-20 14:51:12 -0400178 }
179 }
David Tolnayec66d112020-10-31 21:00:26 -0700180}
David Tolnayf51447e2020-03-06 14:14:27 -0800181
David Tolnay102c7ea2020-11-08 18:58:09 -0800182fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
David Tolnayb960ed22020-11-27 14:34:30 -0800183 let operator_eq = derive::contains(&strct.derives, Trait::PartialEq);
David Tolnay84389352020-11-27 17:12:10 -0800184 let operator_ord = derive::contains(&strct.derives, Trait::PartialOrd);
David Tolnayb960ed22020-11-27 14:34:30 -0800185
David Tolnay17a934c2020-11-02 00:40:04 -0800186 out.set_namespace(&strct.name.namespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800187 let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700188 writeln!(out, "#ifndef {}", guard);
189 writeln!(out, "#define {}", guard);
David Tolnay7db73692019-10-20 14:51:12 -0400190 for line in strct.doc.to_string().lines() {
191 writeln!(out, "//{}", line);
192 }
David Tolnay17a934c2020-11-02 00:40:04 -0800193 writeln!(out, "struct {} final {{", strct.name.cxx);
David Tolnay84389352020-11-27 17:12:10 -0800194
David Tolnay7db73692019-10-20 14:51:12 -0400195 for field in &strct.fields {
196 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700197 write_type_space(out, &field.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400198 writeln!(out, "{};", field.ident);
199 }
David Tolnay84389352020-11-27 17:12:10 -0800200
201 if !methods.is_empty() || operator_eq || operator_ord {
David Tolnay102c7ea2020-11-08 18:58:09 -0800202 writeln!(out);
203 }
David Tolnay84389352020-11-27 17:12:10 -0800204
David Tolnay102c7ea2020-11-08 18:58:09 -0800205 for method in methods {
206 write!(out, " ");
207 let sig = &method.sig;
208 let local_name = method.name.cxx.to_string();
209 write_rust_function_shim_decl(out, &local_name, sig, false);
210 writeln!(out, ";");
211 }
David Tolnay84389352020-11-27 17:12:10 -0800212
David Tolnayb960ed22020-11-27 14:34:30 -0800213 if operator_eq {
214 writeln!(
215 out,
216 " bool operator==(const {} &) const noexcept;",
217 strct.name.cxx,
218 );
219 writeln!(
220 out,
221 " bool operator!=(const {} &) const noexcept;",
222 strct.name.cxx,
223 );
224 }
David Tolnay84389352020-11-27 17:12:10 -0800225
226 if operator_ord {
227 writeln!(
228 out,
229 " bool operator<(const {} &) const noexcept;",
230 strct.name.cxx,
231 );
232 writeln!(
233 out,
234 " bool operator<=(const {} &) const noexcept;",
235 strct.name.cxx,
236 );
237 writeln!(
238 out,
239 " bool operator>(const {} &) const noexcept;",
240 strct.name.cxx,
241 );
242 writeln!(
243 out,
244 " bool operator>=(const {} &) const noexcept;",
245 strct.name.cxx,
246 );
247 }
248
David Tolnay7db73692019-10-20 14:51:12 -0400249 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700250 writeln!(out, "#endif // {}", guard);
David Tolnay7db73692019-10-20 14:51:12 -0400251}
252
253fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
254 writeln!(out, "struct {};", ident);
255}
256
David Tolnay0e3ee8e2020-11-01 23:46:52 -0800257fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
David Tolnay17a934c2020-11-02 00:40:04 -0800258 write!(out, "enum class {} : ", enm.name.cxx);
David Tolnay0e3ee8e2020-11-01 23:46:52 -0800259 write_atom(out, enm.repr);
260 writeln!(out, ";");
261}
262
David Tolnay8faec772020-11-02 00:18:19 -0800263fn write_struct_using(out: &mut OutFile, ident: &Pair) {
264 writeln!(out, "using {} = {};", ident.cxx, ident.to_fully_qualified());
David Tolnay8861bee2020-01-20 18:39:24 -0800265}
266
David Tolnay0b9b9f82020-11-01 20:41:00 -0800267fn write_struct_with_methods<'a>(
268 out: &mut OutFile<'a>,
269 ety: &'a ExternType,
270 methods: &[&ExternFn],
271) {
David Tolnay17a934c2020-11-02 00:40:04 -0800272 out.set_namespace(&ety.name.namespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800273 let guard = format!("CXXBRIDGE1_STRUCT_{}", ety.name.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700274 writeln!(out, "#ifndef {}", guard);
275 writeln!(out, "#define {}", guard);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700276 for line in ety.doc.to_string().lines() {
277 writeln!(out, "//{}", line);
278 }
David Tolnay365fc7c2020-11-25 16:08:13 -0800279 out.builtin.opaque = true;
David Tolnay7c06b862020-11-25 16:59:09 -0800280 writeln!(
281 out,
282 "struct {} final : public ::rust::Opaque {{",
283 ety.name.cxx,
284 );
Joel Galenson968738f2020-04-15 14:19:33 -0700285 for method in methods {
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700286 write!(out, " ");
287 let sig = &method.sig;
David Tolnay17a934c2020-11-02 00:40:04 -0800288 let local_name = method.name.cxx.to_string();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700289 write_rust_function_shim_decl(out, &local_name, sig, false);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700290 writeln!(out, ";");
291 }
292 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700293 writeln!(out, "#endif // {}", guard);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700294}
295
David Tolnay0b9b9f82020-11-01 20:41:00 -0800296fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
David Tolnay17a934c2020-11-02 00:40:04 -0800297 out.set_namespace(&enm.name.namespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800298 let guard = format!("CXXBRIDGE1_ENUM_{}", enm.name.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700299 writeln!(out, "#ifndef {}", guard);
300 writeln!(out, "#define {}", guard);
Joel Galensonc03402a2020-04-23 17:31:09 -0700301 for line in enm.doc.to_string().lines() {
302 writeln!(out, "//{}", line);
303 }
David Tolnay17a934c2020-11-02 00:40:04 -0800304 write!(out, "enum class {} : ", enm.name.cxx);
David Tolnayf6a89f22020-05-10 23:39:27 -0700305 write_atom(out, enm.repr);
306 writeln!(out, " {{");
Joel Galensonc03402a2020-04-23 17:31:09 -0700307 for variant in &enm.variants {
Joel Galenson88547732020-05-05 08:23:42 -0700308 writeln!(out, " {} = {},", variant.ident, variant.discriminant);
Joel Galensonc03402a2020-04-23 17:31:09 -0700309 }
310 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700311 writeln!(out, "#endif // {}", guard);
Joel Galensonc03402a2020-04-23 17:31:09 -0700312}
313
David Tolnay0b9b9f82020-11-01 20:41:00 -0800314fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
David Tolnay17a934c2020-11-02 00:40:04 -0800315 out.set_namespace(&enm.name.namespace);
David Tolnay06711bc2020-11-19 19:25:14 -0800316 out.include.type_traits = true;
317 writeln!(
318 out,
319 "static_assert(::std::is_enum<{}>::value, \"expected enum\");",
320 enm.name.cxx,
321 );
David Tolnay17a934c2020-11-02 00:40:04 -0800322 write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx);
David Tolnayf6a89f22020-05-10 23:39:27 -0700323 write_atom(out, enm.repr);
324 writeln!(out, "), \"incorrect size\");");
Joel Galenson0f654ff2020-05-04 20:04:21 -0700325 for variant in &enm.variants {
David Tolnayf6a89f22020-05-10 23:39:27 -0700326 write!(out, "static_assert(static_cast<");
327 write_atom(out, enm.repr);
Joel Galenson0f654ff2020-05-04 20:04:21 -0700328 writeln!(
329 out,
David Tolnayf6a89f22020-05-10 23:39:27 -0700330 ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
David Tolnay17a934c2020-11-02 00:40:04 -0800331 enm.name.cxx, variant.ident, variant.discriminant,
Joel Galenson0f654ff2020-05-04 20:04:21 -0700332 );
Joel Galenson0f654ff2020-05-04 20:04:21 -0700333 }
Joel Galenson905eb2e2020-05-04 14:58:14 -0700334}
335
David Tolnay8faec772020-11-02 00:18:19 -0800336fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
David Tolnay174bd952020-11-02 09:23:12 -0800337 // NOTE: The following static assertion is just nice-to-have and not
David Tolnayfd0034e2020-10-04 13:15:34 -0700338 // necessary for soundness. That's because triviality is always declared by
339 // the user in the form of an unsafe impl of cxx::ExternType:
340 //
341 // unsafe impl ExternType for MyType {
342 // type Id = cxx::type_id!("...");
343 // type Kind = cxx::kind::Trivial;
344 // }
345 //
346 // Since the user went on the record with their unsafe impl to unsafely
347 // claim they KNOW that the type is trivial, it's fine for that to be on
David Tolnay174bd952020-11-02 09:23:12 -0800348 // them if that were wrong. However, in practice correctly reasoning about
349 // the relocatability of C++ types is challenging, particularly if the type
350 // definition were to change over time, so for now we add this check.
David Tolnayfd0034e2020-10-04 13:15:34 -0700351 //
David Tolnay174bd952020-11-02 09:23:12 -0800352 // There may be legitimate reasons to opt out of this assertion for support
353 // of types that the programmer knows are soundly Rust-movable despite not
354 // being recognized as such by the C++ type system due to a move constructor
355 // or destructor. To opt out of the relocatability check, they need to do
356 // one of the following things in any header used by `include!` in their
357 // bridge.
358 //
359 // --- if they define the type:
360 // struct MyType {
361 // ...
362 // + using IsRelocatable = std::true_type;
363 // };
364 //
365 // --- otherwise:
366 // + template <>
367 // + struct rust::IsRelocatable<MyType> : std::true_type {};
368 //
David Tolnayfd0034e2020-10-04 13:15:34 -0700369
David Tolnay174bd952020-11-02 09:23:12 -0800370 let id = id.to_fully_qualified();
371 out.builtin.relocatable = true;
David Tolnay7426cc12020-10-03 19:04:04 -0700372 writeln!(out, "static_assert(");
David Tolnay174bd952020-11-02 09:23:12 -0800373 writeln!(out, " ::rust::IsRelocatable<{}>::value,", id);
David Tolnay7426cc12020-10-03 19:04:04 -0700374 writeln!(
375 out,
David Tolnay174bd952020-11-02 09:23:12 -0800376 " \"type {} marked as Trivial in Rust is not trivially move constructible and trivially destructible in C++\");",
David Tolnay7426cc12020-10-03 19:04:04 -0700377 id,
378 );
Adrian Taylor405e8742020-09-25 14:01:25 -0700379}
380
David Tolnayb960ed22020-11-27 14:34:30 -0800381fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
382 out.set_namespace(&strct.name.namespace);
383 out.begin_block(Block::ExternC);
384
385 if derive::contains(&strct.derives, Trait::PartialEq) {
386 let link_name = mangle::operator(&strct.name, "__operator_eq");
387 writeln!(
388 out,
389 "bool {}(const {1} &, const {1} &) noexcept;",
390 link_name, strct.name.cxx,
391 );
David Tolnaya6f3b6f2020-11-27 16:47:30 -0800392
393 if !derive::contains(&strct.derives, Trait::Eq) {
394 let link_name = mangle::operator(&strct.name, "__operator_ne");
395 writeln!(
396 out,
397 "bool {}(const {1} &, const {1} &) noexcept;",
398 link_name, strct.name.cxx,
399 );
400 }
David Tolnayb960ed22020-11-27 14:34:30 -0800401 }
402
David Tolnay84389352020-11-27 17:12:10 -0800403 if derive::contains(&strct.derives, Trait::PartialOrd) {
404 let link_name = mangle::operator(&strct.name, "__operator_lt");
405 writeln!(
406 out,
407 "bool {}(const {1} &, const {1} &) noexcept;",
408 link_name, strct.name.cxx,
409 );
410
411 let link_name = mangle::operator(&strct.name, "__operator_le");
412 writeln!(
413 out,
414 "bool {}(const {1} &, const {1} &) noexcept;",
415 link_name, strct.name.cxx,
416 );
417
418 if !derive::contains(&strct.derives, Trait::Ord) {
419 let link_name = mangle::operator(&strct.name, "__operator_gt");
420 writeln!(
421 out,
422 "bool {}(const {1} &, const {1} &) noexcept;",
423 link_name, strct.name.cxx,
424 );
425
426 let link_name = mangle::operator(&strct.name, "__operator_ge");
427 writeln!(
428 out,
429 "bool {}(const {1} &, const {1} &) noexcept;",
430 link_name, strct.name.cxx,
431 );
432 }
433 }
434
David Tolnayb960ed22020-11-27 14:34:30 -0800435 out.end_block(Block::ExternC);
436}
437
438fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
439 if out.header {
440 return;
441 }
442
443 out.set_namespace(&strct.name.namespace);
444
445 if derive::contains(&strct.derives, Trait::PartialEq) {
David Tolnayb960ed22020-11-27 14:34:30 -0800446 out.next_section();
447 writeln!(
448 out,
449 "bool {0}::operator==(const {0} &rhs) const noexcept {{",
450 strct.name.cxx,
451 );
David Tolnaya6f3b6f2020-11-27 16:47:30 -0800452 let link_name = mangle::operator(&strct.name, "__operator_eq");
David Tolnayb960ed22020-11-27 14:34:30 -0800453 writeln!(out, " return {}(*this, rhs);", link_name);
454 writeln!(out, "}}");
David Tolnaya6f3b6f2020-11-27 16:47:30 -0800455
David Tolnayb960ed22020-11-27 14:34:30 -0800456 out.next_section();
457 writeln!(
458 out,
459 "bool {0}::operator!=(const {0} &rhs) const noexcept {{",
460 strct.name.cxx,
461 );
David Tolnaya6f3b6f2020-11-27 16:47:30 -0800462 if derive::contains(&strct.derives, Trait::Eq) {
463 writeln!(out, " return !(*this == rhs);");
464 } else {
465 let link_name = mangle::operator(&strct.name, "__operator_ne");
466 writeln!(out, " return {}(*this, rhs);", link_name);
467 }
David Tolnayb960ed22020-11-27 14:34:30 -0800468 writeln!(out, "}}");
469 }
David Tolnay84389352020-11-27 17:12:10 -0800470
471 if derive::contains(&strct.derives, Trait::PartialOrd) {
472 out.next_section();
473 writeln!(
474 out,
475 "bool {0}::operator<(const {0} &rhs) const noexcept {{",
476 strct.name.cxx,
477 );
478 let link_name = mangle::operator(&strct.name, "__operator_lt");
479 writeln!(out, " return {}(*this, rhs);", link_name);
480 writeln!(out, "}}");
481
482 out.next_section();
483 writeln!(
484 out,
485 "bool {0}::operator<=(const {0} &rhs) const noexcept {{",
486 strct.name.cxx,
487 );
488 let link_name = mangle::operator(&strct.name, "__operator_le");
489 writeln!(out, " return {}(*this, rhs);", link_name);
490 writeln!(out, "}}");
491
492 out.next_section();
493 writeln!(
494 out,
495 "bool {0}::operator>(const {0} &rhs) const noexcept {{",
496 strct.name.cxx,
497 );
498 if derive::contains(&strct.derives, Trait::Ord) {
499 writeln!(out, " return !(*this <= rhs);");
500 } else {
501 let link_name = mangle::operator(&strct.name, "__operator_gt");
502 writeln!(out, " return {}(*this, rhs);", link_name);
503 }
504 writeln!(out, "}}");
505
506 out.next_section();
507 writeln!(
508 out,
509 "bool {0}::operator>=(const {0} &rhs) const noexcept {{",
510 strct.name.cxx,
511 );
512 if derive::contains(&strct.derives, Trait::Ord) {
513 writeln!(out, " return !(*this < rhs);");
514 } else {
515 let link_name = mangle::operator(&strct.name, "__operator_ge");
516 writeln!(out, " return {}(*this, rhs);", link_name);
517 }
518 writeln!(out, "}}");
519 }
David Tolnayb960ed22020-11-27 14:34:30 -0800520}
521
David Tolnay0b9b9f82020-11-01 20:41:00 -0800522fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
David Tolnay04770742020-11-01 13:50:50 -0800523 out.next_section();
David Tolnay17a934c2020-11-02 00:40:04 -0800524 out.set_namespace(&efn.name.namespace);
David Tolnayca563ee2020-11-01 20:12:27 -0800525 out.begin_block(Block::ExternC);
David Tolnaye1476af2020-11-01 13:47:25 -0800526 if let Some(annotation) = &out.opt.cxx_impl_annotations {
David Tolnaycc1ae762020-10-31 15:53:50 -0700527 write!(out, "{} ", annotation);
Adrian Taylor21f0ff02020-07-21 16:21:48 -0700528 }
David Tolnayebef4a22020-03-17 15:33:47 -0700529 if efn.throws {
David Tolnay919085c2020-10-31 22:32:22 -0700530 out.builtin.ptr_len = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700531 write!(out, "::rust::repr::PtrLen ");
David Tolnayebef4a22020-03-17 15:33:47 -0700532 } else {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700533 write_extern_return_type_space(out, &efn.ret);
David Tolnayebef4a22020-03-17 15:33:47 -0700534 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700535 let mangled = mangle::extern_fn(efn, out.types);
David Tolnay3caa50a2020-04-19 21:25:34 -0700536 write!(out, "{}(", mangled);
David Tolnaye439c772020-04-20 00:23:55 -0700537 if let Some(receiver) = &efn.receiver {
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800538 if !receiver.mutable {
David Tolnay86710612020-04-20 00:30:32 -0700539 write!(out, "const ");
540 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700541 write!(
542 out,
543 "{} &self",
David Tolnay8faec772020-11-02 00:18:19 -0800544 out.types.resolve(&receiver.ty).to_fully_qualified(),
Adrian Taylorc8713432020-10-21 18:20:55 -0700545 );
Joel Galenson3d4f6122020-04-07 15:54:05 -0700546 }
David Tolnay7db73692019-10-20 14:51:12 -0400547 for (i, arg) in efn.args.iter().enumerate() {
Joel Galenson3d4f6122020-04-07 15:54:05 -0700548 if i > 0 || efn.receiver.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400549 write!(out, ", ");
550 }
David Tolnaya46a2372020-03-06 10:03:48 -0800551 if arg.ty == RustString {
552 write!(out, "const ");
David Tolnay313b10e2020-04-25 16:30:51 -0700553 } else if let Type::RustVec(_) = arg.ty {
554 write!(out, "const ");
David Tolnaya46a2372020-03-06 10:03:48 -0800555 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700556 write_extern_arg(out, arg);
David Tolnay7db73692019-10-20 14:51:12 -0400557 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700558 let indirect_return = indirect_return(efn, out.types);
David Tolnay7db73692019-10-20 14:51:12 -0400559 if indirect_return {
myronahne3b78ea2020-05-23 01:08:13 +0700560 if !efn.args.is_empty() || efn.receiver.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400561 write!(out, ", ");
562 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700563 write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
David Tolnay7db73692019-10-20 14:51:12 -0400564 write!(out, "*return$");
565 }
566 writeln!(out, ") noexcept {{");
567 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700568 write_return_type(out, &efn.ret);
Joel Galenson3d4f6122020-04-07 15:54:05 -0700569 match &efn.receiver {
David Tolnay17a934c2020-11-02 00:40:04 -0800570 None => write!(out, "(*{}$)(", efn.name.rust),
Adrian Taylorc8713432020-10-21 18:20:55 -0700571 Some(receiver) => write!(
572 out,
573 "({}::*{}$)(",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700574 out.types.resolve(&receiver.ty).to_fully_qualified(),
David Tolnay17a934c2020-11-02 00:40:04 -0800575 efn.name.rust,
Adrian Taylorc8713432020-10-21 18:20:55 -0700576 ),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700577 }
David Tolnay7db73692019-10-20 14:51:12 -0400578 for (i, arg) in efn.args.iter().enumerate() {
579 if i > 0 {
580 write!(out, ", ");
581 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700582 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400583 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700584 write!(out, ")");
David Tolnay4e7123f2020-04-19 21:11:37 -0700585 if let Some(receiver) = &efn.receiver {
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800586 if !receiver.mutable {
David Tolnay4e7123f2020-04-19 21:11:37 -0700587 write!(out, " const");
588 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700589 }
590 write!(out, " = ");
591 match &efn.receiver {
David Tolnay17a934c2020-11-02 00:40:04 -0800592 None => write!(out, "{}", efn.name.to_fully_qualified()),
Adrian Taylorc8713432020-10-21 18:20:55 -0700593 Some(receiver) => write!(
594 out,
595 "&{}::{}",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700596 out.types.resolve(&receiver.ty).to_fully_qualified(),
David Tolnay17a934c2020-11-02 00:40:04 -0800597 efn.name.cxx,
Adrian Taylorc8713432020-10-21 18:20:55 -0700598 ),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700599 }
600 writeln!(out, ";");
David Tolnay7db73692019-10-20 14:51:12 -0400601 write!(out, " ");
David Tolnayebef4a22020-03-17 15:33:47 -0700602 if efn.throws {
David Tolnay919085c2020-10-31 22:32:22 -0700603 out.builtin.ptr_len = true;
David Tolnay74d6d512020-10-31 22:22:03 -0700604 out.builtin.trycatch = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700605 writeln!(out, "::rust::repr::PtrLen throw$;");
David Tolnay3e3e0af2020-03-17 22:42:49 -0700606 writeln!(out, " ::rust::behavior::trycatch(");
David Tolnay5d121442020-03-17 22:14:40 -0700607 writeln!(out, " [&] {{");
608 write!(out, " ");
David Tolnayebef4a22020-03-17 15:33:47 -0700609 }
David Tolnay7db73692019-10-20 14:51:12 -0400610 if indirect_return {
David Tolnay0ecd05a2020-07-29 16:32:03 -0700611 out.include.new = true;
David Tolnay7db73692019-10-20 14:51:12 -0400612 write!(out, "new (return$) ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700613 write_indirect_return_type(out, efn.ret.as_ref().unwrap());
David Tolnay7db73692019-10-20 14:51:12 -0400614 write!(out, "(");
David Tolnay99642622020-03-25 13:07:35 -0700615 } else if efn.ret.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400616 write!(out, "return ");
David Tolnay99642622020-03-25 13:07:35 -0700617 }
618 match &efn.ret {
619 Some(Type::Ref(_)) => write!(out, "&"),
David Tolnay74d6d512020-10-31 22:22:03 -0700620 Some(Type::Str(_)) if !indirect_return => {
621 out.builtin.rust_str_repr = true;
622 write!(out, "::rust::impl<::rust::Str>::repr(");
623 }
David Tolnay73b72642020-11-25 17:44:05 -0800624 Some(ty @ Type::SliceRef(_)) if !indirect_return => {
David Tolnay36aa9e02020-10-31 23:08:21 -0700625 out.builtin.rust_slice_repr = true;
David Tolnayc5629f02020-11-23 18:32:46 -0800626 write!(out, "::rust::impl<");
627 write_type(out, ty);
628 write!(out, ">::repr(");
David Tolnayeb952ba2020-04-14 15:02:24 -0700629 }
David Tolnay99642622020-03-25 13:07:35 -0700630 _ => {}
David Tolnay7db73692019-10-20 14:51:12 -0400631 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700632 match &efn.receiver {
David Tolnay17a934c2020-11-02 00:40:04 -0800633 None => write!(out, "{}$(", efn.name.rust),
634 Some(_) => write!(out, "(self.*{}$)(", efn.name.rust),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700635 }
David Tolnay7db73692019-10-20 14:51:12 -0400636 for (i, arg) in efn.args.iter().enumerate() {
637 if i > 0 {
638 write!(out, ", ");
639 }
640 if let Type::RustBox(_) = &arg.ty {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700641 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400642 write!(out, "::from_raw({})", arg.ident);
643 } else if let Type::UniquePtr(_) = &arg.ty {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700644 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400645 write!(out, "({})", arg.ident);
David Tolnay0356d332020-10-31 19:46:41 -0700646 } else if let Type::Str(_) = arg.ty {
David Tolnay74d6d512020-10-31 22:22:03 -0700647 out.builtin.rust_str_new_unchecked = true;
David Tolnay0356d332020-10-31 19:46:41 -0700648 write!(
649 out,
650 "::rust::impl<::rust::Str>::new_unchecked({})",
651 arg.ident,
652 );
David Tolnaya46a2372020-03-06 10:03:48 -0800653 } else if arg.ty == RustString {
David Tolnay74d6d512020-10-31 22:22:03 -0700654 out.builtin.unsafe_bitcopy = true;
David Tolnaycc3767f2020-03-06 10:41:51 -0800655 write!(
656 out,
657 "::rust::String(::rust::unsafe_bitcopy, *{})",
658 arg.ident,
659 );
David Tolnay313b10e2020-04-25 16:30:51 -0700660 } else if let Type::RustVec(_) = arg.ty {
David Tolnay74d6d512020-10-31 22:22:03 -0700661 out.builtin.unsafe_bitcopy = true;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700662 write_type(out, &arg.ty);
David Tolnay313b10e2020-04-25 16:30:51 -0700663 write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
David Tolnay73b72642020-11-25 17:44:05 -0800664 } else if let Type::SliceRef(slice) = &arg.ty {
David Tolnayc5629f02020-11-23 18:32:46 -0800665 write_type(out, &arg.ty);
666 write!(out, "(static_cast<");
667 if slice.mutability.is_none() {
668 write!(out, "const ");
669 }
David Tolnay5515a9e2020-11-25 19:07:54 -0800670 write_type_space(out, &slice.inner);
671 write!(out, "*>({0}.ptr), {0}.len)", arg.ident);
David Tolnaya7c2ea12020-10-30 21:32:53 -0700672 } else if out.types.needs_indirect_abi(&arg.ty) {
David Tolnay4791f1c2020-03-17 21:53:16 -0700673 out.include.utility = true;
David Tolnay7e219b82020-03-01 13:14:51 -0800674 write!(out, "::std::move(*{})", arg.ident);
David Tolnay7db73692019-10-20 14:51:12 -0400675 } else {
676 write!(out, "{}", arg.ident);
677 }
678 }
679 write!(out, ")");
680 match &efn.ret {
681 Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
682 Some(Type::UniquePtr(_)) => write!(out, ".release()"),
David Tolnay73b72642020-11-25 17:44:05 -0800683 Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
David Tolnay7db73692019-10-20 14:51:12 -0400684 _ => {}
685 }
686 if indirect_return {
687 write!(out, ")");
688 }
689 writeln!(out, ";");
David Tolnayebef4a22020-03-17 15:33:47 -0700690 if efn.throws {
691 out.include.cstring = true;
David Tolnay1f010c62020-11-01 20:27:46 -0800692 out.builtin.exception = true;
David Tolnay5d121442020-03-17 22:14:40 -0700693 writeln!(out, " throw$.ptr = nullptr;");
694 writeln!(out, " }},");
David Tolnay82c16172020-03-17 22:54:12 -0700695 writeln!(out, " [&](const char *catch$) noexcept {{");
David Tolnay5d121442020-03-17 22:14:40 -0700696 writeln!(out, " throw$.len = ::std::strlen(catch$);");
David Tolnayebef4a22020-03-17 15:33:47 -0700697 writeln!(
698 out,
David Tolnayc5629f02020-11-23 18:32:46 -0800699 " throw$.ptr = const_cast<char *>(::cxxbridge1$exception(catch$, throw$.len));",
David Tolnayebef4a22020-03-17 15:33:47 -0700700 );
David Tolnay5d121442020-03-17 22:14:40 -0700701 writeln!(out, " }});");
David Tolnayebef4a22020-03-17 15:33:47 -0700702 writeln!(out, " return throw$;");
703 }
David Tolnay7db73692019-10-20 14:51:12 -0400704 writeln!(out, "}}");
David Tolnay75dca2e2020-03-25 20:17:52 -0700705 for arg in &efn.args {
706 if let Type::Fn(f) = &arg.ty {
707 let var = &arg.ident;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700708 write_function_pointer_trampoline(out, efn, var, f);
David Tolnay75dca2e2020-03-25 20:17:52 -0700709 }
710 }
David Tolnayca563ee2020-11-01 20:12:27 -0800711 out.end_block(Block::ExternC);
David Tolnay75dca2e2020-03-25 20:17:52 -0700712}
713
714fn write_function_pointer_trampoline(
715 out: &mut OutFile,
716 efn: &ExternFn,
717 var: &Ident,
718 f: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700719) {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700720 let r_trampoline = mangle::r_trampoline(efn, var, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700721 let indirect_call = true;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700722 write_rust_function_decl_impl(out, &r_trampoline, f, indirect_call);
David Tolnay75dca2e2020-03-25 20:17:52 -0700723
724 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700725 let c_trampoline = mangle::c_trampoline(efn, var, out.types).to_string();
726 write_rust_function_shim_impl(out, &c_trampoline, f, &r_trampoline, indirect_call);
David Tolnay7db73692019-10-20 14:51:12 -0400727}
728
David Tolnay0b9b9f82020-11-01 20:41:00 -0800729fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
David Tolnay17a934c2020-11-02 00:40:04 -0800730 out.set_namespace(&efn.name.namespace);
David Tolnayca563ee2020-11-01 20:12:27 -0800731 out.begin_block(Block::ExternC);
David Tolnaya7c2ea12020-10-30 21:32:53 -0700732 let link_name = mangle::extern_fn(efn, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700733 let indirect_call = false;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700734 write_rust_function_decl_impl(out, &link_name, efn, indirect_call);
David Tolnayca563ee2020-11-01 20:12:27 -0800735 out.end_block(Block::ExternC);
David Tolnay75dca2e2020-03-25 20:17:52 -0700736}
737
738fn write_rust_function_decl_impl(
739 out: &mut OutFile,
David Tolnay891061b2020-04-19 22:42:33 -0700740 link_name: &Symbol,
David Tolnay75dca2e2020-03-25 20:17:52 -0700741 sig: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700742 indirect_call: bool,
743) {
David Tolnay04770742020-11-01 13:50:50 -0800744 out.next_section();
David Tolnay75dca2e2020-03-25 20:17:52 -0700745 if sig.throws {
David Tolnay919085c2020-10-31 22:32:22 -0700746 out.builtin.ptr_len = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700747 write!(out, "::rust::repr::PtrLen ");
David Tolnay1e548172020-03-16 13:37:09 -0700748 } else {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700749 write_extern_return_type_space(out, &sig.ret);
David Tolnay1e548172020-03-16 13:37:09 -0700750 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700751 write!(out, "{}(", link_name);
752 let mut needs_comma = false;
David Tolnaye439c772020-04-20 00:23:55 -0700753 if let Some(receiver) = &sig.receiver {
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800754 if !receiver.mutable {
David Tolnay86710612020-04-20 00:30:32 -0700755 write!(out, "const ");
756 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700757 write!(
758 out,
759 "{} &self",
David Tolnay8faec772020-11-02 00:18:19 -0800760 out.types.resolve(&receiver.ty).to_fully_qualified(),
Adrian Taylorc8713432020-10-21 18:20:55 -0700761 );
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700762 needs_comma = true;
763 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700764 for arg in &sig.args {
765 if needs_comma {
David Tolnay7db73692019-10-20 14:51:12 -0400766 write!(out, ", ");
767 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700768 write_extern_arg(out, arg);
David Tolnay75dca2e2020-03-25 20:17:52 -0700769 needs_comma = true;
David Tolnay7db73692019-10-20 14:51:12 -0400770 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700771 if indirect_return(sig, out.types) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700772 if needs_comma {
David Tolnay7db73692019-10-20 14:51:12 -0400773 write!(out, ", ");
774 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700775 write_return_type(out, &sig.ret);
David Tolnay7db73692019-10-20 14:51:12 -0400776 write!(out, "*return$");
David Tolnay75dca2e2020-03-25 20:17:52 -0700777 needs_comma = true;
778 }
779 if indirect_call {
780 if needs_comma {
781 write!(out, ", ");
782 }
783 write!(out, "void *");
David Tolnay7db73692019-10-20 14:51:12 -0400784 }
785 writeln!(out, ") noexcept;");
786}
787
David Tolnay0b9b9f82020-11-01 20:41:00 -0800788fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
David Tolnay17a934c2020-11-02 00:40:04 -0800789 out.set_namespace(&efn.name.namespace);
David Tolnay7db73692019-10-20 14:51:12 -0400790 for line in efn.doc.to_string().lines() {
791 writeln!(out, "//{}", line);
792 }
David Tolnaya73853b2020-04-20 01:19:56 -0700793 let local_name = match &efn.sig.receiver {
David Tolnay17a934c2020-11-02 00:40:04 -0800794 None => efn.name.cxx.to_string(),
795 Some(receiver) => format!("{}::{}", out.types.resolve(&receiver.ty).cxx, efn.name.cxx),
David Tolnaya73853b2020-04-20 01:19:56 -0700796 };
David Tolnaya7c2ea12020-10-30 21:32:53 -0700797 let invoke = mangle::extern_fn(efn, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700798 let indirect_call = false;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700799 write_rust_function_shim_impl(out, &local_name, efn, &invoke, indirect_call);
David Tolnay75dca2e2020-03-25 20:17:52 -0700800}
801
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700802fn write_rust_function_shim_decl(
David Tolnay75dca2e2020-03-25 20:17:52 -0700803 out: &mut OutFile,
David Tolnaya73853b2020-04-20 01:19:56 -0700804 local_name: &str,
David Tolnay75dca2e2020-03-25 20:17:52 -0700805 sig: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700806 indirect_call: bool,
807) {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700808 write_return_type(out, &sig.ret);
David Tolnay75dca2e2020-03-25 20:17:52 -0700809 write!(out, "{}(", local_name);
810 for (i, arg) in sig.args.iter().enumerate() {
David Tolnay7db73692019-10-20 14:51:12 -0400811 if i > 0 {
812 write!(out, ", ");
813 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700814 write_type_space(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400815 write!(out, "{}", arg.ident);
816 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700817 if indirect_call {
818 if !sig.args.is_empty() {
819 write!(out, ", ");
820 }
821 write!(out, "void *extern$");
822 }
David Tolnay1e548172020-03-16 13:37:09 -0700823 write!(out, ")");
David Tolnay86710612020-04-20 00:30:32 -0700824 if let Some(receiver) = &sig.receiver {
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800825 if !receiver.mutable {
David Tolnay86710612020-04-20 00:30:32 -0700826 write!(out, " const");
827 }
828 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700829 if !sig.throws {
David Tolnay1e548172020-03-16 13:37:09 -0700830 write!(out, " noexcept");
831 }
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700832}
833
834fn write_rust_function_shim_impl(
835 out: &mut OutFile,
David Tolnaya73853b2020-04-20 01:19:56 -0700836 local_name: &str,
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700837 sig: &Signature,
David Tolnay891061b2020-04-19 22:42:33 -0700838 invoke: &Symbol,
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700839 indirect_call: bool,
840) {
841 if out.header && sig.receiver.is_some() {
842 // We've already defined this inside the struct.
843 return;
844 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700845 write_rust_function_shim_decl(out, local_name, sig, indirect_call);
David Tolnay7db73692019-10-20 14:51:12 -0400846 if out.header {
847 writeln!(out, ";");
David Tolnay439cde22020-04-20 00:46:25 -0700848 return;
David Tolnay7db73692019-10-20 14:51:12 -0400849 }
David Tolnay439cde22020-04-20 00:46:25 -0700850 writeln!(out, " {{");
851 for arg in &sig.args {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700852 if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
David Tolnay439cde22020-04-20 00:46:25 -0700853 out.include.utility = true;
David Tolnay74d6d512020-10-31 22:22:03 -0700854 out.builtin.manually_drop = true;
David Tolnay439cde22020-04-20 00:46:25 -0700855 write!(out, " ::rust::ManuallyDrop<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700856 write_type(out, &arg.ty);
David Tolnay439cde22020-04-20 00:46:25 -0700857 writeln!(out, "> {}$(::std::move({0}));", arg.ident);
858 }
859 }
860 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700861 let indirect_return = indirect_return(sig, out.types);
David Tolnay439cde22020-04-20 00:46:25 -0700862 if indirect_return {
David Tolnay74d6d512020-10-31 22:22:03 -0700863 out.builtin.maybe_uninit = true;
David Tolnay439cde22020-04-20 00:46:25 -0700864 write!(out, "::rust::MaybeUninit<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700865 write_type(out, sig.ret.as_ref().unwrap());
David Tolnay439cde22020-04-20 00:46:25 -0700866 writeln!(out, "> return$;");
867 write!(out, " ");
868 } else if let Some(ret) = &sig.ret {
869 write!(out, "return ");
870 match ret {
871 Type::RustBox(_) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700872 write_type(out, ret);
David Tolnay439cde22020-04-20 00:46:25 -0700873 write!(out, "::from_raw(");
874 }
875 Type::UniquePtr(_) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700876 write_type(out, ret);
David Tolnay439cde22020-04-20 00:46:25 -0700877 write!(out, "(");
878 }
879 Type::Ref(_) => write!(out, "*"),
David Tolnay74d6d512020-10-31 22:22:03 -0700880 Type::Str(_) => {
881 out.builtin.rust_str_new_unchecked = true;
882 write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
883 }
David Tolnay73b72642020-11-25 17:44:05 -0800884 Type::SliceRef(_) => {
David Tolnay36aa9e02020-10-31 23:08:21 -0700885 out.builtin.rust_slice_new = true;
David Tolnayc5629f02020-11-23 18:32:46 -0800886 write!(out, "::rust::impl<");
887 write_type(out, ret);
888 write!(out, ">::slice(");
David Tolnay36aa9e02020-10-31 23:08:21 -0700889 }
David Tolnay439cde22020-04-20 00:46:25 -0700890 _ => {}
891 }
892 }
893 if sig.throws {
David Tolnay919085c2020-10-31 22:32:22 -0700894 out.builtin.ptr_len = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700895 write!(out, "::rust::repr::PtrLen error$ = ");
David Tolnay439cde22020-04-20 00:46:25 -0700896 }
897 write!(out, "{}(", invoke);
David Tolnay9d840362020-11-10 08:50:40 -0800898 let mut needs_comma = false;
David Tolnay439cde22020-04-20 00:46:25 -0700899 if sig.receiver.is_some() {
900 write!(out, "*this");
David Tolnay9d840362020-11-10 08:50:40 -0800901 needs_comma = true;
David Tolnay439cde22020-04-20 00:46:25 -0700902 }
David Tolnay9d840362020-11-10 08:50:40 -0800903 for arg in &sig.args {
904 if needs_comma {
David Tolnay439cde22020-04-20 00:46:25 -0700905 write!(out, ", ");
906 }
907 match &arg.ty {
David Tolnay74d6d512020-10-31 22:22:03 -0700908 Type::Str(_) => {
909 out.builtin.rust_str_repr = true;
910 write!(out, "::rust::impl<::rust::Str>::repr(");
911 }
David Tolnay73b72642020-11-25 17:44:05 -0800912 Type::SliceRef(_) => {
David Tolnay36aa9e02020-10-31 23:08:21 -0700913 out.builtin.rust_slice_repr = true;
David Tolnayc5629f02020-11-23 18:32:46 -0800914 write!(out, "::rust::impl<");
915 write_type(out, &arg.ty);
916 write!(out, ">::repr(");
David Tolnay36aa9e02020-10-31 23:08:21 -0700917 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700918 ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
David Tolnay439cde22020-04-20 00:46:25 -0700919 _ => {}
920 }
921 write!(out, "{}", arg.ident);
922 match &arg.ty {
923 Type::RustBox(_) => write!(out, ".into_raw()"),
924 Type::UniquePtr(_) => write!(out, ".release()"),
David Tolnay73b72642020-11-25 17:44:05 -0800925 Type::Str(_) | Type::SliceRef(_) => write!(out, ")"),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700926 ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
David Tolnay439cde22020-04-20 00:46:25 -0700927 _ => {}
928 }
David Tolnay9d840362020-11-10 08:50:40 -0800929 needs_comma = true;
David Tolnay439cde22020-04-20 00:46:25 -0700930 }
931 if indirect_return {
David Tolnay9d840362020-11-10 08:50:40 -0800932 if needs_comma {
David Tolnay439cde22020-04-20 00:46:25 -0700933 write!(out, ", ");
934 }
935 write!(out, "&return$.value");
David Tolnay9d840362020-11-10 08:50:40 -0800936 needs_comma = true;
David Tolnay439cde22020-04-20 00:46:25 -0700937 }
938 if indirect_call {
David Tolnay9d840362020-11-10 08:50:40 -0800939 if needs_comma {
David Tolnay439cde22020-04-20 00:46:25 -0700940 write!(out, ", ");
941 }
942 write!(out, "extern$");
943 }
944 write!(out, ")");
David Tolnay22602b42020-09-21 18:04:05 -0400945 if !indirect_return {
946 if let Some(ret) = &sig.ret {
David Tolnay73b72642020-11-25 17:44:05 -0800947 if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_) = ret {
David Tolnay22602b42020-09-21 18:04:05 -0400948 write!(out, ")");
949 }
David Tolnay439cde22020-04-20 00:46:25 -0700950 }
951 }
952 writeln!(out, ";");
953 if sig.throws {
David Tolnay74d6d512020-10-31 22:22:03 -0700954 out.builtin.rust_error = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700955 writeln!(out, " if (error$.ptr) {{");
David Tolnay84ddf9e2020-10-31 15:36:48 -0700956 writeln!(out, " throw ::rust::impl<::rust::Error>::error(error$);");
David Tolnay439cde22020-04-20 00:46:25 -0700957 writeln!(out, " }}");
958 }
959 if indirect_return {
960 out.include.utility = true;
961 writeln!(out, " return ::std::move(return$.value);");
962 }
963 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -0400964}
965
David Tolnaya7c2ea12020-10-30 21:32:53 -0700966fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
David Tolnay7db73692019-10-20 14:51:12 -0400967 match ty {
968 None => write!(out, "void "),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700969 Some(ty) => write_type_space(out, ty),
David Tolnay7db73692019-10-20 14:51:12 -0400970 }
971}
972
David Tolnay75dca2e2020-03-25 20:17:52 -0700973fn indirect_return(sig: &Signature, types: &Types) -> bool {
974 sig.ret
David Tolnay277e3cc2020-03-17 00:11:01 -0700975 .as_ref()
David Tolnay75dca2e2020-03-25 20:17:52 -0700976 .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
David Tolnay277e3cc2020-03-17 00:11:01 -0700977}
978
David Tolnaya7c2ea12020-10-30 21:32:53 -0700979fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
David Tolnay99642622020-03-25 13:07:35 -0700980 match ty {
981 Type::RustBox(ty) | Type::UniquePtr(ty) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700982 write_type_space(out, &ty.inner);
David Tolnay99642622020-03-25 13:07:35 -0700983 write!(out, "*");
984 }
985 Type::Ref(ty) => {
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800986 if !ty.mutable {
David Tolnay99642622020-03-25 13:07:35 -0700987 write!(out, "const ");
988 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700989 write_type(out, &ty.inner);
David Tolnay99642622020-03-25 13:07:35 -0700990 write!(out, " *");
991 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700992 _ => write_type(out, ty),
David Tolnay99642622020-03-25 13:07:35 -0700993 }
994}
995
David Tolnaya7c2ea12020-10-30 21:32:53 -0700996fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
997 write_indirect_return_type(out, ty);
David Tolnay99642622020-03-25 13:07:35 -0700998 match ty {
999 Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
David Tolnay73b72642020-11-25 17:44:05 -08001000 Type::Str(_) | Type::SliceRef(_) => write!(out, " "),
David Tolnay99642622020-03-25 13:07:35 -07001001 _ => write_space_after_type(out, ty),
1002 }
1003}
1004
David Tolnaya7c2ea12020-10-30 21:32:53 -07001005fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
David Tolnay7db73692019-10-20 14:51:12 -04001006 match ty {
1007 Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001008 write_type_space(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -04001009 write!(out, "*");
1010 }
David Tolnay4a441222020-01-25 16:24:27 -08001011 Some(Type::Ref(ty)) => {
David Tolnay9c4ac2e2020-11-15 21:14:03 -08001012 if !ty.mutable {
David Tolnay4a441222020-01-25 16:24:27 -08001013 write!(out, "const ");
1014 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001015 write_type(out, &ty.inner);
David Tolnay4a441222020-01-25 16:24:27 -08001016 write!(out, " *");
1017 }
David Tolnay73b72642020-11-25 17:44:05 -08001018 Some(Type::Str(_)) | Some(Type::SliceRef(_)) => {
David Tolnay919085c2020-10-31 22:32:22 -07001019 out.builtin.ptr_len = true;
1020 write!(out, "::rust::repr::PtrLen ");
1021 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001022 Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
1023 _ => write_return_type(out, ty),
David Tolnay7db73692019-10-20 14:51:12 -04001024 }
1025}
1026
David Tolnaya7c2ea12020-10-30 21:32:53 -07001027fn write_extern_arg(out: &mut OutFile, arg: &Var) {
David Tolnay7db73692019-10-20 14:51:12 -04001028 match &arg.ty {
David Tolnay4377a9e2020-04-24 15:20:26 -07001029 Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001030 write_type_space(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -04001031 write!(out, "*");
1032 }
David Tolnay73b72642020-11-25 17:44:05 -08001033 Type::Str(_) | Type::SliceRef(_) => {
David Tolnay919085c2020-10-31 22:32:22 -07001034 out.builtin.ptr_len = true;
1035 write!(out, "::rust::repr::PtrLen ");
1036 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001037 _ => write_type_space(out, &arg.ty),
David Tolnay7db73692019-10-20 14:51:12 -04001038 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001039 if out.types.needs_indirect_abi(&arg.ty) {
David Tolnay7db73692019-10-20 14:51:12 -04001040 write!(out, "*");
1041 }
1042 write!(out, "{}", arg.ident);
1043}
1044
David Tolnaya7c2ea12020-10-30 21:32:53 -07001045fn write_type(out: &mut OutFile, ty: &Type) {
David Tolnay7db73692019-10-20 14:51:12 -04001046 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -07001047 Type::Ident(ident) => match Atom::from(&ident.rust) {
David Tolnayf6a89f22020-05-10 23:39:27 -07001048 Some(atom) => write_atom(out, atom),
David Tolnaya7c2ea12020-10-30 21:32:53 -07001049 None => write!(out, "{}", out.types.resolve(ident).to_fully_qualified()),
David Tolnay7db73692019-10-20 14:51:12 -04001050 },
1051 Type::RustBox(ty) => {
David Tolnay750755e2020-03-01 13:04:08 -08001052 write!(out, "::rust::Box<");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001053 write_type(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -04001054 write!(out, ">");
1055 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001056 Type::RustVec(ty) => {
1057 write!(out, "::rust::Vec<");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001058 write_type(out, &ty.inner);
Myron Ahneba35cf2020-02-05 19:41:51 +07001059 write!(out, ">");
1060 }
David Tolnay7db73692019-10-20 14:51:12 -04001061 Type::UniquePtr(ptr) => {
David Tolnay7e219b82020-03-01 13:14:51 -08001062 write!(out, "::std::unique_ptr<");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001063 write_type(out, &ptr.inner);
David Tolnay7db73692019-10-20 14:51:12 -04001064 write!(out, ">");
1065 }
David Tolnay4377a9e2020-04-24 15:20:26 -07001066 Type::CxxVector(ty) => {
Myron Ahneba35cf2020-02-05 19:41:51 +07001067 write!(out, "::std::vector<");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001068 write_type(out, &ty.inner);
Myron Ahneba35cf2020-02-05 19:41:51 +07001069 write!(out, ">");
1070 }
David Tolnay7db73692019-10-20 14:51:12 -04001071 Type::Ref(r) => {
David Tolnay9c4ac2e2020-11-15 21:14:03 -08001072 if !r.mutable {
David Tolnay7db73692019-10-20 14:51:12 -04001073 write!(out, "const ");
1074 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001075 write_type(out, &r.inner);
David Tolnay7db73692019-10-20 14:51:12 -04001076 write!(out, " &");
1077 }
1078 Type::Str(_) => {
David Tolnay750755e2020-03-01 13:04:08 -08001079 write!(out, "::rust::Str");
David Tolnay7db73692019-10-20 14:51:12 -04001080 }
David Tolnay5515a9e2020-11-25 19:07:54 -08001081 Type::SliceRef(slice) => {
David Tolnayc5629f02020-11-23 18:32:46 -08001082 write!(out, "::rust::Slice<");
David Tolnay5515a9e2020-11-25 19:07:54 -08001083 if slice.mutability.is_none() {
David Tolnayc5629f02020-11-23 18:32:46 -08001084 write!(out, "const ");
1085 }
David Tolnay5515a9e2020-11-25 19:07:54 -08001086 write_type(out, &slice.inner);
1087 write!(out, ">");
Adrian Taylorf5dd5522020-04-13 16:50:14 -07001088 }
David Tolnay75dca2e2020-03-25 20:17:52 -07001089 Type::Fn(f) => {
1090 write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
1091 match &f.ret {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001092 Some(ret) => write_type(out, ret),
David Tolnay75dca2e2020-03-25 20:17:52 -07001093 None => write!(out, "void"),
1094 }
1095 write!(out, "(");
1096 for (i, arg) in f.args.iter().enumerate() {
1097 if i > 0 {
1098 write!(out, ", ");
1099 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001100 write_type(out, &arg.ty);
David Tolnay75dca2e2020-03-25 20:17:52 -07001101 }
1102 write!(out, ")>");
1103 }
Xiangpeng Hao78762352020-11-12 10:24:18 +08001104 Type::Array(a) => {
1105 write!(out, "::std::array<");
1106 write_type(out, &a.inner);
1107 write!(out, ", {}>", &a.len);
1108 }
David Tolnay2fb14e92020-03-15 23:11:38 -07001109 Type::Void(_) => unreachable!(),
David Tolnay7db73692019-10-20 14:51:12 -04001110 }
1111}
1112
David Tolnayf6a89f22020-05-10 23:39:27 -07001113fn write_atom(out: &mut OutFile, atom: Atom) {
1114 match atom {
1115 Bool => write!(out, "bool"),
David Tolnayb3873dc2020-11-25 19:47:49 -08001116 Char => write!(out, "char"),
David Tolnayf6a89f22020-05-10 23:39:27 -07001117 U8 => write!(out, "uint8_t"),
1118 U16 => write!(out, "uint16_t"),
1119 U32 => write!(out, "uint32_t"),
1120 U64 => write!(out, "uint64_t"),
1121 Usize => write!(out, "size_t"),
1122 I8 => write!(out, "int8_t"),
1123 I16 => write!(out, "int16_t"),
1124 I32 => write!(out, "int32_t"),
1125 I64 => write!(out, "int64_t"),
1126 Isize => write!(out, "::rust::isize"),
1127 F32 => write!(out, "float"),
1128 F64 => write!(out, "double"),
1129 CxxString => write!(out, "::std::string"),
1130 RustString => write!(out, "::rust::String"),
1131 }
1132}
1133
David Tolnaya7c2ea12020-10-30 21:32:53 -07001134fn write_type_space(out: &mut OutFile, ty: &Type) {
1135 write_type(out, ty);
David Tolnay99642622020-03-25 13:07:35 -07001136 write_space_after_type(out, ty);
1137}
1138
1139fn write_space_after_type(out: &mut OutFile, ty: &Type) {
David Tolnay7db73692019-10-20 14:51:12 -04001140 match ty {
David Tolnayeb952ba2020-04-14 15:02:24 -07001141 Type::Ident(_)
1142 | Type::RustBox(_)
1143 | Type::UniquePtr(_)
1144 | Type::Str(_)
David Tolnay4377a9e2020-04-24 15:20:26 -07001145 | Type::CxxVector(_)
Myron Ahneba35cf2020-02-05 19:41:51 +07001146 | Type::RustVec(_)
David Tolnay73b72642020-11-25 17:44:05 -08001147 | Type::SliceRef(_)
Xiangpeng Hao78762352020-11-12 10:24:18 +08001148 | Type::Fn(_)
1149 | Type::Array(_) => write!(out, " "),
David Tolnay7db73692019-10-20 14:51:12 -04001150 Type::Ref(_) => {}
David Tolnaye0dca7b2020-11-25 17:18:57 -08001151 Type::Void(_) => unreachable!(),
David Tolnay7db73692019-10-20 14:51:12 -04001152 }
1153}
1154
David Tolnay1bdb4712020-11-25 07:27:54 -08001155#[derive(Copy, Clone)]
1156enum UniquePtr<'a> {
1157 Ident(&'a ResolvableName),
1158 CxxVector(&'a ResolvableName),
1159}
1160
1161trait ToTypename {
1162 fn to_typename(&self, types: &Types) -> String;
1163}
1164
1165impl ToTypename for ResolvableName {
1166 fn to_typename(&self, types: &Types) -> String {
1167 types.resolve(self).to_fully_qualified()
David Tolnay2eca4a02020-04-24 19:50:51 -07001168 }
1169}
1170
David Tolnay1bdb4712020-11-25 07:27:54 -08001171impl<'a> ToTypename for UniquePtr<'a> {
1172 fn to_typename(&self, types: &Types) -> String {
1173 match self {
1174 UniquePtr::Ident(ident) => ident.to_typename(types),
1175 UniquePtr::CxxVector(element) => {
1176 format!("::std::vector<{}>", element.to_typename(types))
1177 }
1178 }
1179 }
1180}
1181
1182trait ToMangled {
1183 fn to_mangled(&self, types: &Types) -> Symbol;
1184}
1185
1186impl ToMangled for ResolvableName {
1187 fn to_mangled(&self, types: &Types) -> Symbol {
1188 self.to_symbol(types)
1189 }
1190}
1191
1192impl<'a> ToMangled for UniquePtr<'a> {
1193 fn to_mangled(&self, types: &Types) -> Symbol {
1194 match self {
1195 UniquePtr::Ident(ident) => ident.to_mangled(types),
1196 UniquePtr::CxxVector(element) => element.to_mangled(types).prefix_with("std$vector$"),
1197 }
David Tolnaybae50ef2020-04-25 12:38:41 -07001198 }
1199}
1200
David Tolnaya7c2ea12020-10-30 21:32:53 -07001201fn write_generic_instantiations(out: &mut OutFile) {
David Tolnay169bb472020-11-01 21:04:24 -08001202 if out.header {
1203 return;
1204 }
1205
1206 out.next_section();
David Tolnay078c90f2020-11-01 13:31:08 -08001207 out.set_namespace(Default::default());
David Tolnay0c033e32020-11-01 15:15:48 -08001208 out.begin_block(Block::ExternC);
David Tolnaya7c2ea12020-10-30 21:32:53 -07001209 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -04001210 if let Type::RustBox(ty) = ty {
1211 if let Type::Ident(inner) = &ty.inner {
1212 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -07001213 write_rust_box_extern(out, &out.types.resolve(&inner));
David Tolnay7db73692019-10-20 14:51:12 -04001214 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001215 } else if let Type::RustVec(ty) = ty {
David Tolnay6787be62020-04-25 11:01:02 -07001216 if let Type::Ident(inner) = &ty.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001217 if Atom::from(&inner.rust).is_none() {
David Tolnay6787be62020-04-25 11:01:02 -07001218 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -07001219 write_rust_vec_extern(out, inner);
David Tolnay6787be62020-04-25 11:01:02 -07001220 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001221 }
David Tolnay7db73692019-10-20 14:51:12 -04001222 } else if let Type::UniquePtr(ptr) = ty {
1223 if let Type::Ident(inner) = &ptr.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001224 if Atom::from(&inner.rust).is_none()
David Tolnaya7c2ea12020-10-30 21:32:53 -07001225 && (!out.types.aliases.contains_key(&inner.rust)
1226 || out.types.explicit_impls.contains(ty))
David Tolnay7e69f892020-10-03 22:20:22 -07001227 {
David Tolnay7db73692019-10-20 14:51:12 -04001228 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -07001229 write_unique_ptr(out, inner);
Myron Ahneba35cf2020-02-05 19:41:51 +07001230 }
1231 }
David Tolnay4377a9e2020-04-24 15:20:26 -07001232 } else if let Type::CxxVector(ptr) = ty {
Myron Ahneba35cf2020-02-05 19:41:51 +07001233 if let Type::Ident(inner) = &ptr.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001234 if Atom::from(&inner.rust).is_none()
David Tolnaya7c2ea12020-10-30 21:32:53 -07001235 && (!out.types.aliases.contains_key(&inner.rust)
1236 || out.types.explicit_impls.contains(ty))
David Tolnay7e69f892020-10-03 22:20:22 -07001237 {
Myron Ahneba35cf2020-02-05 19:41:51 +07001238 out.next_section();
David Tolnay1bdb4712020-11-25 07:27:54 -08001239 write_cxx_vector(out, inner);
David Tolnay7db73692019-10-20 14:51:12 -04001240 }
1241 }
1242 }
1243 }
David Tolnay0c033e32020-11-01 15:15:48 -08001244 out.end_block(Block::ExternC);
David Tolnay7db73692019-10-20 14:51:12 -04001245
David Tolnay0c033e32020-11-01 15:15:48 -08001246 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -08001247 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnaya7c2ea12020-10-30 21:32:53 -07001248 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -04001249 if let Type::RustBox(ty) = ty {
1250 if let Type::Ident(inner) = &ty.inner {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001251 write_rust_box_impl(out, &out.types.resolve(&inner));
David Tolnay7db73692019-10-20 14:51:12 -04001252 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001253 } else if let Type::RustVec(ty) = ty {
David Tolnay6787be62020-04-25 11:01:02 -07001254 if let Type::Ident(inner) = &ty.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001255 if Atom::from(&inner.rust).is_none() {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001256 write_rust_vec_impl(out, inner);
David Tolnay6787be62020-04-25 11:01:02 -07001257 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001258 }
David Tolnay7db73692019-10-20 14:51:12 -04001259 }
1260 }
David Tolnay0f0162f2020-11-16 23:43:37 -08001261 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay0c033e32020-11-01 15:15:48 -08001262 out.end_block(Block::Namespace("rust"));
David Tolnay7db73692019-10-20 14:51:12 -04001263}
1264
David Tolnay8faec772020-11-02 00:18:19 -08001265fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
Adrian Taylorc8713432020-10-21 18:20:55 -07001266 let inner = ident.to_fully_qualified();
1267 let instance = ident.to_symbol();
David Tolnay7db73692019-10-20 14:51:12 -04001268
David Tolnay0f0162f2020-11-16 23:43:37 -08001269 writeln!(out, "#ifndef CXXBRIDGE1_RUST_BOX_{}", instance);
1270 writeln!(out, "#define CXXBRIDGE1_RUST_BOX_{}", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001271 writeln!(
1272 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001273 "void cxxbridge1$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
David Tolnay7db73692019-10-20 14:51:12 -04001274 instance, inner,
1275 );
1276 writeln!(
1277 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001278 "void cxxbridge1$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
David Tolnay7db73692019-10-20 14:51:12 -04001279 instance, inner,
1280 );
David Tolnay0f0162f2020-11-16 23:43:37 -08001281 writeln!(out, "#endif // CXXBRIDGE1_RUST_BOX_{}", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001282}
1283
David Tolnaya7c2ea12020-10-30 21:32:53 -07001284fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
David Tolnay1bdb4712020-11-25 07:27:54 -08001285 let inner = element.to_typename(out.types);
1286 let instance = element.to_mangled(out.types);
Myron Ahneba35cf2020-02-05 19:41:51 +07001287
David Tolnay0f0162f2020-11-16 23:43:37 -08001288 writeln!(out, "#ifndef CXXBRIDGE1_RUST_VEC_{}", instance);
1289 writeln!(out, "#define CXXBRIDGE1_RUST_VEC_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001290 writeln!(
1291 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001292 "void cxxbridge1$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
David Tolnayf97c2d52020-04-25 16:37:48 -07001293 instance, inner,
1294 );
1295 writeln!(
1296 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001297 "void cxxbridge1$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
Myron Ahneba35cf2020-02-05 19:41:51 +07001298 instance, inner,
1299 );
1300 writeln!(
1301 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001302 "size_t cxxbridge1$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
Myron Ahneba35cf2020-02-05 19:41:51 +07001303 instance, inner,
1304 );
David Tolnay219c0792020-04-24 20:31:37 -07001305 writeln!(
1306 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001307 "const {} *cxxbridge1$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
David Tolnay219c0792020-04-24 20:31:37 -07001308 inner, instance,
1309 );
David Tolnay503d0192020-04-24 22:18:56 -07001310 writeln!(
1311 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001312 "void cxxbridge1$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, size_t cap) noexcept;",
David Tolnayfb6b73c2020-11-10 14:32:16 -08001313 instance, inner,
1314 );
1315 writeln!(
1316 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001317 "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, size_t len) noexcept;",
David Tolnayfb6b73c2020-11-10 14:32:16 -08001318 instance, inner,
1319 );
1320 writeln!(
1321 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001322 "size_t cxxbridge1$rust_vec${}$stride() noexcept;",
David Tolnay503d0192020-04-24 22:18:56 -07001323 instance,
1324 );
David Tolnay0f0162f2020-11-16 23:43:37 -08001325 writeln!(out, "#endif // CXXBRIDGE1_RUST_VEC_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001326}
1327
David Tolnay8faec772020-11-02 00:18:19 -08001328fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
Adrian Taylorc8713432020-10-21 18:20:55 -07001329 let inner = ident.to_fully_qualified();
1330 let instance = ident.to_symbol();
David Tolnay7db73692019-10-20 14:51:12 -04001331
1332 writeln!(out, "template <>");
David Tolnay324437a2020-03-01 13:02:24 -08001333 writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
David Tolnay0f0162f2020-11-16 23:43:37 -08001334 writeln!(out, " cxxbridge1$box${}$uninit(this);", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001335 writeln!(out, "}}");
1336
1337 writeln!(out, "template <>");
David Tolnay324437a2020-03-01 13:02:24 -08001338 writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
David Tolnay0f0162f2020-11-16 23:43:37 -08001339 writeln!(out, " cxxbridge1$box${}$drop(this);", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001340 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -04001341}
1342
David Tolnaya7c2ea12020-10-30 21:32:53 -07001343fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
David Tolnay1bdb4712020-11-25 07:27:54 -08001344 let inner = element.to_typename(out.types);
1345 let instance = element.to_mangled(out.types);
David Tolnay4791f1c2020-03-17 21:53:16 -07001346
Myron Ahneba35cf2020-02-05 19:41:51 +07001347 writeln!(out, "template <>");
David Tolnayf97c2d52020-04-25 16:37:48 -07001348 writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
David Tolnay0f0162f2020-11-16 23:43:37 -08001349 writeln!(out, " cxxbridge1$rust_vec${}$new(this);", instance);
David Tolnayf97c2d52020-04-25 16:37:48 -07001350 writeln!(out, "}}");
1351
1352 writeln!(out, "template <>");
Myron Ahneba35cf2020-02-05 19:41:51 +07001353 writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
David Tolnay0f0162f2020-11-16 23:43:37 -08001354 writeln!(out, " return cxxbridge1$rust_vec${}$drop(this);", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001355 writeln!(out, "}}");
1356
1357 writeln!(out, "template <>");
1358 writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
David Tolnay0f0162f2020-11-16 23:43:37 -08001359 writeln!(out, " return cxxbridge1$rust_vec${}$len(this);", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001360 writeln!(out, "}}");
David Tolnay219c0792020-04-24 20:31:37 -07001361
1362 writeln!(out, "template <>");
1363 writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
David Tolnay0f0162f2020-11-16 23:43:37 -08001364 writeln!(out, " return cxxbridge1$rust_vec${}$data(this);", instance);
David Tolnay219c0792020-04-24 20:31:37 -07001365 writeln!(out, "}}");
David Tolnay503d0192020-04-24 22:18:56 -07001366
1367 writeln!(out, "template <>");
David Tolnayfb6b73c2020-11-10 14:32:16 -08001368 writeln!(
1369 out,
1370 "void Vec<{}>::reserve_total(size_t cap) noexcept {{",
1371 inner,
1372 );
1373 writeln!(
1374 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001375 " return cxxbridge1$rust_vec${}$reserve_total(this, cap);",
David Tolnayfb6b73c2020-11-10 14:32:16 -08001376 instance,
1377 );
1378 writeln!(out, "}}");
1379
1380 writeln!(out, "template <>");
1381 writeln!(out, "void Vec<{}>::set_len(size_t len) noexcept {{", inner);
1382 writeln!(
1383 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001384 " return cxxbridge1$rust_vec${}$set_len(this, len);",
David Tolnayfb6b73c2020-11-10 14:32:16 -08001385 instance,
1386 );
1387 writeln!(out, "}}");
1388
1389 writeln!(out, "template <>");
David Tolnay503d0192020-04-24 22:18:56 -07001390 writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
David Tolnay0f0162f2020-11-16 23:43:37 -08001391 writeln!(out, " return cxxbridge1$rust_vec${}$stride();", instance);
David Tolnay503d0192020-04-24 22:18:56 -07001392 writeln!(out, "}}");
Myron Ahneba35cf2020-02-05 19:41:51 +07001393}
1394
David Tolnaya7c2ea12020-10-30 21:32:53 -07001395fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName) {
David Tolnay1bdb4712020-11-25 07:27:54 -08001396 let ty = UniquePtr::Ident(ident);
1397 let instance = ty.to_mangled(out.types);
David Tolnay63da4d32020-04-25 09:41:12 -07001398
David Tolnay0f0162f2020-11-16 23:43:37 -08001399 writeln!(out, "#ifndef CXXBRIDGE1_UNIQUE_PTR_{}", instance);
1400 writeln!(out, "#define CXXBRIDGE1_UNIQUE_PTR_{}", instance);
David Tolnay63da4d32020-04-25 09:41:12 -07001401
David Tolnay1bdb4712020-11-25 07:27:54 -08001402 write_unique_ptr_common(out, ty);
David Tolnay63da4d32020-04-25 09:41:12 -07001403
David Tolnay0f0162f2020-11-16 23:43:37 -08001404 writeln!(out, "#endif // CXXBRIDGE1_UNIQUE_PTR_{}", instance);
David Tolnay63da4d32020-04-25 09:41:12 -07001405}
1406
1407// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
David Tolnay1bdb4712020-11-25 07:27:54 -08001408fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
David Tolnay0ecd05a2020-07-29 16:32:03 -07001409 out.include.new = true;
Myron Ahneba35cf2020-02-05 19:41:51 +07001410 out.include.utility = true;
David Tolnay1bdb4712020-11-25 07:27:54 -08001411 let inner = ty.to_typename(out.types);
1412 let instance = ty.to_mangled(out.types);
David Tolnay7db73692019-10-20 14:51:12 -04001413
David Tolnay63da4d32020-04-25 09:41:12 -07001414 let can_construct_from_value = match ty {
David Tolnayca0f9da2020-10-16 13:16:17 -07001415 // Some aliases are to opaque types; some are to trivial types. We can't
1416 // know at code generation time, so we generate both C++ and Rust side
1417 // bindings for a "new" method anyway. But the Rust code can't be called
1418 // for Opaque types because the 'new' method is not implemented.
David Tolnay1bdb4712020-11-25 07:27:54 -08001419 UniquePtr::Ident(ident) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001420 out.types.structs.contains_key(&ident.rust)
David Tolnay15609ab2020-11-25 07:14:12 -08001421 || out.types.enums.contains_key(&ident.rust)
David Tolnaya7c2ea12020-10-30 21:32:53 -07001422 || out.types.aliases.contains_key(&ident.rust)
David Tolnayca0f9da2020-10-16 13:16:17 -07001423 }
David Tolnay1bdb4712020-11-25 07:27:54 -08001424 UniquePtr::CxxVector(_) => false,
David Tolnay63da4d32020-04-25 09:41:12 -07001425 };
1426
David Tolnay53462762020-11-25 07:08:10 -08001427 let conditional_delete = match ty {
1428 UniquePtr::Ident(ident) => {
1429 !out.types.structs.contains_key(&ident.rust)
1430 && !out.types.enums.contains_key(&ident.rust)
1431 }
1432 UniquePtr::CxxVector(_) => false,
1433 };
1434
1435 if conditional_delete {
1436 out.builtin.is_complete = true;
1437 let definition = match ty {
1438 UniquePtr::Ident(ty) => &out.types.resolve(ty).cxx,
1439 UniquePtr::CxxVector(_) => unreachable!(),
1440 };
1441 writeln!(
1442 out,
1443 "static_assert(::rust::is_complete<{}>::value, \"definition of {} is required\");",
1444 inner, definition,
1445 );
1446 }
David Tolnay7db73692019-10-20 14:51:12 -04001447 writeln!(
1448 out,
David Tolnay7e219b82020-03-01 13:14:51 -08001449 "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
David Tolnay7db73692019-10-20 14:51:12 -04001450 inner,
1451 );
1452 writeln!(
1453 out,
David Tolnay7e219b82020-03-01 13:14:51 -08001454 "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
David Tolnay7db73692019-10-20 14:51:12 -04001455 inner,
1456 );
1457 writeln!(
1458 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001459 "void cxxbridge1$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001460 instance, inner,
1461 );
David Tolnay7e219b82020-03-01 13:14:51 -08001462 writeln!(out, " new (ptr) ::std::unique_ptr<{}>();", inner);
David Tolnay7db73692019-10-20 14:51:12 -04001463 writeln!(out, "}}");
David Tolnay63da4d32020-04-25 09:41:12 -07001464 if can_construct_from_value {
1465 writeln!(
David Tolnay53838912020-04-09 20:56:44 -07001466 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001467 "void cxxbridge1$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
David Tolnay53838912020-04-09 20:56:44 -07001468 instance, inner, inner,
1469 );
David Tolnay63da4d32020-04-25 09:41:12 -07001470 writeln!(
1471 out,
1472 " new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
1473 inner, inner,
1474 );
1475 writeln!(out, "}}");
David Tolnay53838912020-04-09 20:56:44 -07001476 }
David Tolnay7db73692019-10-20 14:51:12 -04001477 writeln!(
1478 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001479 "void cxxbridge1$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001480 instance, inner, inner,
1481 );
David Tolnay7e219b82020-03-01 13:14:51 -08001482 writeln!(out, " new (ptr) ::std::unique_ptr<{}>(raw);", inner);
David Tolnay7db73692019-10-20 14:51:12 -04001483 writeln!(out, "}}");
1484 writeln!(
1485 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001486 "const {} *cxxbridge1$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001487 inner, instance, inner,
1488 );
1489 writeln!(out, " return ptr.get();");
1490 writeln!(out, "}}");
1491 writeln!(
1492 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001493 "{} *cxxbridge1$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001494 inner, instance, inner,
1495 );
1496 writeln!(out, " return ptr.release();");
1497 writeln!(out, "}}");
1498 writeln!(
1499 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001500 "void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001501 instance, inner,
1502 );
David Tolnay53462762020-11-25 07:08:10 -08001503 if conditional_delete {
1504 out.builtin.deleter_if = true;
1505 writeln!(
1506 out,
1507 " ::rust::deleter_if<::rust::is_complete<{}>::value>{{}}(ptr);",
1508 inner,
1509 );
1510 } else {
1511 writeln!(out, " ptr->~unique_ptr();");
1512 }
David Tolnay7db73692019-10-20 14:51:12 -04001513 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -04001514}
Myron Ahneba35cf2020-02-05 19:41:51 +07001515
David Tolnay1bdb4712020-11-25 07:27:54 -08001516fn write_cxx_vector(out: &mut OutFile, element: &ResolvableName) {
1517 let inner = element.to_typename(out.types);
1518 let instance = element.to_mangled(out.types);
Myron Ahneba35cf2020-02-05 19:41:51 +07001519
David Tolnay0f0162f2020-11-16 23:43:37 -08001520 writeln!(out, "#ifndef CXXBRIDGE1_VECTOR_{}", instance);
1521 writeln!(out, "#define CXXBRIDGE1_VECTOR_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001522 writeln!(
1523 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001524 "size_t cxxbridge1$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
Myron Ahneba35cf2020-02-05 19:41:51 +07001525 instance, inner,
1526 );
1527 writeln!(out, " return s.size();");
1528 writeln!(out, "}}");
Myron Ahneba35cf2020-02-05 19:41:51 +07001529 writeln!(
1530 out,
David Tolnay0f0162f2020-11-16 23:43:37 -08001531 "const {} *cxxbridge1$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
Myron Ahneba35cf2020-02-05 19:41:51 +07001532 inner, instance, inner,
1533 );
David Tolnayb3fcf7b2020-04-30 22:58:28 -07001534 writeln!(out, " return &s[pos];");
Myron Ahneba35cf2020-02-05 19:41:51 +07001535 writeln!(out, "}}");
David Tolnay63da4d32020-04-25 09:41:12 -07001536
David Tolnay1bdb4712020-11-25 07:27:54 -08001537 write_unique_ptr_common(out, UniquePtr::CxxVector(element));
David Tolnay63da4d32020-04-25 09:41:12 -07001538
David Tolnay0f0162f2020-11-16 23:43:37 -08001539 writeln!(out, "#endif // CXXBRIDGE1_VECTOR_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001540}