Restrict MSVC instantiation workaround to return positions only
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 489d85a..97610a4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,7 +5,7 @@
use crate::syntax::atom::Atom::{self, *};
use crate::syntax::instantiate::ImplKey;
use crate::syntax::map::UnorderedMap as Map;
-use crate::syntax::set::UnorderedSet;
+use crate::syntax::set::{OrderedSet, UnorderedSet};
use crate::syntax::symbol::Symbol;
use crate::syntax::trivial::{self, TrivialReason};
use crate::syntax::{
@@ -121,19 +121,24 @@
out.set_namespace(Default::default());
+ // MSVC workaround for "C linkage function cannot return C++ class" error.
+ // Apparently the compiler fails to perform implicit instantiations as part
+ // of an extern declaration. Instead we instantiate explicitly.
+ // See https://stackoverflow.com/a/57429504/6086311.
out.next_section();
- for ty in out.types {
- // MSVC workaround for "C linkage function cannot return C++ class"
- // error. Apparently the compiler fails to perform implicit
- // instantiations as part of an extern declaration. Instead we
- // instantiate explicitly.
- // See https://stackoverflow.com/a/57429504/6086311.
- if let Type::SliceRef(_) = ty {
- write!(out, "template struct ");
- write_type(out, ty);
- writeln!(out, ";");
+ let mut slice_in_return_position = OrderedSet::new();
+ for api in apis {
+ if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
+ if let Some(ty @ Type::SliceRef(_)) = &efn.ret {
+ slice_in_return_position.insert(ty);
+ }
}
}
+ for ty in &slice_in_return_position {
+ write!(out, "template struct ");
+ write_type(out, ty);
+ writeln!(out, ";");
+ }
out.next_section();
for api in apis {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 3841cb2..f043d81 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -828,6 +828,10 @@
// > definition) of each of its non-inherited non-template members that has not
// > been previously explicitly specialized in the translation unit.
template struct rust::Box<tests::Shared>;
+template struct rust::Slice<const tests::Shared>;
+template struct rust::Slice<tests::Shared>;
+template struct rust::Slice<const tests::R>;
+template struct rust::Slice<tests::R>;
template struct rust::Vec<uint8_t>;
template struct rust::Vec<rust::String>;
template struct rust::Vec<tests::Shared>;