Repository: dtolnay/cxx
Pull request #542 (2020-12-05 02:36:40)

Respect explicit impls on Vec and Box


Patch:
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 419e46c0..6881e4c3 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1255,14 +1255,22 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
     for ty in out.types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                out.next_section();
-                write_rust_box_extern(out, &out.types.resolve(&inner));
+        if let Type::RustBox(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    out.next_section();
+                    write_rust_box_extern(out, &out.types.resolve(&inner));
+                }
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(&inner.rust).is_none() {
+        } else if let Type::RustVec(vec) = ty {
+            if let Type::Ident(inner) = &vec.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
                     out.next_section();
                     write_rust_vec_extern(out, inner);
                 }
@@ -1287,8 +1295,8 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_shared_ptr(out, inner);
                 }
             }
-        } else if let Type::CxxVector(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
+        } else if let Type::CxxVector(vector) = ty {
+            if let Type::Ident(inner) = &vector.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
                         || out.types.explicit_impls.contains(ty))
@@ -1304,13 +1312,21 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
     for ty in out.types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                write_rust_box_impl(out, &out.types.resolve(&inner));
+        if let Type::RustBox(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    write_rust_box_impl(out, &out.types.resolve(&inner));
+                }
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(&inner.rust).is_none() {
+        } else if let Type::RustVec(vec) = ty {
+            if let Type::Ident(inner) = &vec.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
                     write_rust_vec_impl(out, inner);
                 }
             }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9f16e5e6..43f152be 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -68,13 +68,17 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none() {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
                     hidden.extend(expand_rust_box(ident, types));
                 }
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none() {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
                     hidden.extend(expand_rust_vec(ident, types));
                 }
             }
diff --git a/syntax/check.rs b/syntax/check.rs
index e9d977bd..3b7b5136 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -440,12 +440,19 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
         return;
     }
 
-    if let Type::UniquePtr(ty) | Type::SharedPtr(ty) | Type::CxxVector(ty) = ty {
-        if let Type::Ident(inner) = &ty.inner {
-            if Atom::from(&inner.rust).is_none() {
-                return;
+    match ty {
+        Type::RustBox(ty)
+        | Type::RustVec(ty)
+        | Type::UniquePtr(ty)
+        | Type::SharedPtr(ty)
+        | Type::CxxVector(ty) => {
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(&inner.rust).is_none() {
+                    return;
+                }
             }
         }
+        _ => {}
     }
 
     cx.error(imp, "unsupported Self type of explicit impl");


Test patch:
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 0dd51e5b..a2c13d3b 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -11,6 +11,8 @@ pub mod ffi {
 
         fn c_take_unique_ptr(c: UniquePtr<C>);
     }
+
+    impl Vec<Job> {}
 }
 
 #[cxx::bridge(namespace = "tests")]