Fix remaining "C-linkage specified, but returns UDT" warnings on macOS
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 65cd703..5248a20 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -21,6 +21,10 @@
     pub trycatch: bool,
     pub ptr_len: bool,
     pub repr_fat: bool,
+    pub rust_str_new_unchecked: bool,
+    pub rust_str_repr: bool,
+    pub rust_slice_new: bool,
+    pub rust_slice_repr: bool,
     pub exception: bool,
     pub relocatable: bool,
     pub friend_impl: bool,
@@ -162,6 +166,20 @@
     ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
     ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
+    if builtin.rust_str_new_unchecked {
+        out.next_section();
+        writeln!(out, "class Str::uninit {{}};");
+        writeln!(out, "inline Str::Str(uninit) noexcept {{}}");
+    }
+
+    if builtin.rust_slice_new {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "class Slice<T>::uninit {{}};");
+        writeln!(out, "template <typename T>");
+        writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}");
+    }
+
     out.begin_block(Block::Namespace("detail"));
 
     if builtin.maybe_uninit {
@@ -221,8 +239,18 @@
 
     out.begin_block(Block::AnonymousNamespace);
 
+    if builtin.repr_fat {
+        include.array = true;
+        include.cstdint = true;
+        out.next_section();
+        out.begin_block(Block::Namespace("repr"));
+        writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;");
+        out.end_block(Block::Namespace("repr"));
+    }
+
     if builtin.ptr_len {
         include.cstddef = true;
+        out.next_section();
         out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  void *ptr;");
@@ -231,15 +259,47 @@
         out.end_block(Block::Namespace("repr"));
     }
 
-    if builtin.repr_fat {
-        include.array = true;
-        include.cstdint = true;
-        out.begin_block(Block::Namespace("repr"));
-        writeln!(out, "template <typename T>");
-        writeln!(out, "struct Fat final {{");
-        writeln!(out, "  T repr;");
+    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
+        out.next_section();
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Str> final {{");
+        writeln!(out, "public:");
+        if builtin.rust_str_new_unchecked {
+            writeln!(
+                out,
+                "  static Str new_unchecked(repr::Fat repr) noexcept {{",
+            );
+            writeln!(out, "    Str str = Str::uninit{{}};");
+            writeln!(out, "    str.repr = repr;");
+            writeln!(out, "    return str;");
+            writeln!(out, "  }}");
+        }
+        if builtin.rust_str_repr {
+            writeln!(out, "  static repr::Fat repr(Str str) noexcept {{");
+            writeln!(out, "    return str.repr;");
+            writeln!(out, "  }}");
+        }
         writeln!(out, "}};");
-        out.end_block(Block::Namespace("repr"));
+    }
+
+    if builtin.rust_slice_new || builtin.rust_slice_repr {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "class impl<Slice<T>> final {{");
+        writeln!(out, "public:");
+        if builtin.rust_slice_new {
+            writeln!(out, "  static Slice<T> slice(repr::Fat repr) noexcept {{");
+            writeln!(out, "    Slice<T> slice = typename Slice<T>::uninit{{}};");
+            writeln!(out, "    slice.repr = repr;");
+            writeln!(out, "    return slice;");
+            writeln!(out, "  }}");
+        }
+        if builtin.rust_slice_repr {
+            writeln!(out, "  static repr::Fat repr(Slice<T> slice) noexcept {{");
+            writeln!(out, "    return slice.repr;");
+            writeln!(out, "  }}");
+        }
+        writeln!(out, "}};");
     }
 
     if builtin.rust_error {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index c6331f4..2404f9c 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::{OrderedSet, UnorderedSet};
+use crate::syntax::set::UnorderedSet;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
@@ -125,25 +125,6 @@
 
     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 return type. Instead we instantiate explicitly.
-    // See https://stackoverflow.com/a/57429504/6086311.
-    out.next_section();
-    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::Str(_)) | Some(ty @ Type::SliceRef(_)) = &efn.ret {
-                slice_in_return_position.insert(ty);
-            }
-        }
-    }
-    for ty in &slice_in_return_position {
-        write!(out, "template class ::rust::repr::Fat<");
-        write_type(out, ty);
-        writeln!(out, ">;");
-    }
-
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
@@ -757,7 +738,16 @@
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, "{{"),
+        Some(Type::Str(_)) if !indirect_return => {
+            out.builtin.rust_str_repr = true;
+            write!(out, "::rust::impl<::rust::Str>::repr(");
+        }
+        Some(ty @ Type::SliceRef(_)) if !indirect_return => {
+            out.builtin.rust_slice_repr = true;
+            write!(out, "::rust::impl<");
+            write_type(out, ty);
+            write!(out, ">::repr(");
+        }
         _ => {}
     }
     match &efn.receiver {
@@ -796,7 +786,7 @@
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, "}}"),
+        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -995,6 +985,16 @@
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
+            Type::Str(_) => {
+                out.builtin.rust_str_new_unchecked = true;
+                write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
+            }
+            Type::SliceRef(_) => {
+                out.builtin.rust_slice_new = true;
+                write!(out, "::rust::impl<");
+                write_type(out, ret);
+                write!(out, ">::slice(");
+            }
             _ => {}
         }
     }
@@ -1040,10 +1040,8 @@
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            match ret {
-                Type::RustBox(_) | Type::UniquePtr(_) => write!(out, ")"),
-                Type::Str(_) | Type::SliceRef(_) => write!(out, ".repr"),
-                _ => {}
+            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_) = ret {
+                write!(out, ")");
             }
         }
     }
@@ -1113,11 +1111,9 @@
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(ty @ Type::Str(_)) | Some(ty @ Type::SliceRef(_)) => {
+        Some(Type::Str(_)) | Some(Type::SliceRef(_)) => {
             out.builtin.repr_fat = true;
-            write!(out, "::rust::repr::Fat<");
-            write_type(out, ty);
-            write!(out, "> ");
+            write!(out, "::rust::repr::Fat ");
         }
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),