Generate all explicit and implicit impls based on one map
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 96592b3..6679076 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,13 +3,14 @@
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 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::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
-    derive, mangle, Api, Enum, ExternFn, ExternType, NamedType, Pair, Signature, Struct, Trait,
-    Type, TypeAlias, Types, Var,
+    derive, mangle, Api, Enum, ExternFn, ExternType, Pair, Signature, Struct, Trait, Type,
+    TypeAlias, Types, Var,
 };
 use proc_macro2::Ident;
 
@@ -1284,15 +1285,15 @@
 
 #[derive(Copy, Clone)]
 enum UniquePtr<'a> {
-    Ident(&'a NamedType),
-    CxxVector(&'a NamedType),
+    Ident(&'a Ident),
+    CxxVector(&'a Ident),
 }
 
 trait ToTypename {
     fn to_typename(&self, types: &Types) -> String;
 }
 
-impl ToTypename for NamedType {
+impl ToTypename for Ident {
     fn to_typename(&self, types: &Types) -> String {
         types.resolve(self).to_fully_qualified()
     }
@@ -1313,7 +1314,7 @@
     fn to_mangled(&self, types: &Types) -> Symbol;
 }
 
-impl ToMangled for NamedType {
+impl ToMangled for Ident {
     fn to_mangled(&self, types: &Types) -> Symbol {
         types.resolve(self).to_symbol()
     }
@@ -1336,109 +1337,36 @@
     out.next_section();
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
-    for ty in out.types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        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_key(&impl_key))
-                {
-                    out.next_section();
-                    write_rust_box_extern(out, &out.types.resolve(&inner));
-                }
-            }
-        } 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_key(&impl_key))
-                {
-                    out.next_section();
-                    write_rust_vec_extern(out, inner);
-                }
-            }
-        } else if let Type::UniquePtr(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_key(&impl_key))
-                {
-                    out.next_section();
-                    write_unique_ptr(out, inner);
-                }
-            }
-        } else if let Type::SharedPtr(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_key(&impl_key))
-                {
-                    out.next_section();
-                    write_shared_ptr(out, inner);
-                }
-            }
-        } else if let Type::WeakPtr(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_key(&impl_key))
-                {
-                    out.next_section();
-                    write_weak_ptr(out, 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_key(&impl_key))
-                {
-                    out.next_section();
-                    write_cxx_vector(out, inner);
-                }
-            }
+    for impl_key in out.types.impls.keys() {
+        out.next_section();
+        match impl_key {
+            ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
+            ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
+            ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
+            ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident),
+            ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident),
+            ImplKey::CxxVector(ident) => write_cxx_vector(out, ident),
         }
     }
     out.end_block(Block::ExternC);
 
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
-    for ty in out.types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        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_key(&impl_key))
-                {
-                    write_rust_box_impl(out, &out.types.resolve(&inner));
-                }
-            }
-        } 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_key(&impl_key))
-                {
-                    write_rust_vec_impl(out, inner);
-                }
-            }
+    for impl_key in out.types.impls.keys() {
+        match impl_key {
+            ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
+            ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
+            _ => {}
         }
     }
     out.end_block(Block::InlineNamespace("cxxbridge1"));
     out.end_block(Block::Namespace("rust"));
 }
 
-fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
-    let inner = ident.to_fully_qualified();
-    let instance = ident.to_symbol();
+fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
+    let resolve = out.types.resolve(ident);
+    let inner = resolve.to_fully_qualified();
+    let instance = resolve.to_symbol();
 
     writeln!(
         out,
@@ -1457,7 +1385,7 @@
     );
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &NamedType) {
+fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1500,9 +1428,10 @@
     );
 }
 
-fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
-    let inner = ident.to_fully_qualified();
-    let instance = ident.to_symbol();
+fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
+    let resolve = out.types.resolve(ident);
+    let inner = resolve.to_fully_qualified();
+    let instance = resolve.to_symbol();
 
     writeln!(out, "template <>");
     begin_function_definition(out);
@@ -1531,7 +1460,7 @@
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &NamedType) {
+fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1608,7 +1537,7 @@
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &NamedType) {
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     let ty = UniquePtr::Ident(ident);
     write_unique_ptr_common(out, ty);
 }
@@ -1626,17 +1555,16 @@
         // bindings for a "new" method anyway. But the Rust code can't be called
         // for Opaque types because the 'new' method is not implemented.
         UniquePtr::Ident(ident) => {
-            out.types.structs.contains_key(&ident.rust)
-                || out.types.enums.contains_key(&ident.rust)
-                || out.types.aliases.contains_key(&ident.rust)
+            out.types.structs.contains_key(ident)
+                || out.types.enums.contains_key(ident)
+                || out.types.aliases.contains_key(ident)
         }
         UniquePtr::CxxVector(_) => false,
     };
 
     let conditional_delete = match ty {
         UniquePtr::Ident(ident) => {
-            !out.types.structs.contains_key(&ident.rust)
-                && !out.types.enums.contains_key(&ident.rust)
+            !out.types.structs.contains_key(ident) && !out.types.enums.contains_key(ident)
         }
         UniquePtr::CxxVector(_) => false,
     };
@@ -1725,7 +1653,7 @@
     writeln!(out, "}}");
 }
 
-fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) {
+fn write_shared_ptr(out: &mut OutFile, ident: &Ident) {
     let resolve = out.types.resolve(ident);
     let inner = resolve.to_fully_qualified();
     let instance = resolve.to_symbol();
@@ -1737,9 +1665,9 @@
     // know at code generation time, so we generate both C++ and Rust side
     // bindings for a "new" method anyway. But the Rust code can't be called for
     // Opaque types because the 'new' method is not implemented.
-    let can_construct_from_value = out.types.structs.contains_key(&ident.rust)
-        || out.types.enums.contains_key(&ident.rust)
-        || out.types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = out.types.structs.contains_key(ident)
+        || out.types.enums.contains_key(ident)
+        || out.types.aliases.contains_key(ident);
 
     writeln!(
         out,
@@ -1797,7 +1725,7 @@
     writeln!(out, "}}");
 }
 
-fn write_weak_ptr(out: &mut OutFile, ident: &NamedType) {
+fn write_weak_ptr(out: &mut OutFile, ident: &Ident) {
     let resolve = out.types.resolve(ident);
     let inner = resolve.to_fully_qualified();
     let instance = resolve.to_symbol();
@@ -1856,7 +1784,7 @@
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, element: &NamedType) {
+fn write_cxx_vector(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 90b835a..40ed5e2 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,12 +1,13 @@
 use crate::derive;
-use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::atom::Atom::*;
 use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
+use crate::syntax::instantiate::ImplKey;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, NamedType, Pair, Signature,
-    Struct, Trait, Type, TypeAlias, Types,
+    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Pair, Signature, Struct,
+    Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -79,62 +80,25 @@
         }
     }
 
-    for ty in types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        let explicit_impl = types.explicit_impls.get(&impl_key).copied();
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    hidden.extend(expand_rust_box(ident, types, explicit_impl));
-                }
+    for (impl_key, &explicit_impl) in &types.impls {
+        match impl_key {
+            ImplKey::RustBox(ident) => {
+                hidden.extend(expand_rust_box(ident, types, explicit_impl));
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    hidden.extend(expand_rust_vec(ident, types, explicit_impl));
-                }
+            ImplKey::RustVec(ident) => {
+                hidden.extend(expand_rust_vec(ident, types, explicit_impl));
             }
-        } else if let Type::UniquePtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::UniquePtr(ident) => {
+                expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::SharedPtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::SharedPtr(ident) => {
+                expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::WeakPtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::WeakPtr(ident) => {
+                expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::CxxVector(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    // Generate impl for CxxVector<T> if T is a struct or opaque
-                    // C++ type. Impl for primitives is already provided by cxx
-                    // crate.
-                    expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
-                }
+            ImplKey::CxxVector(ident) => {
+                expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
             }
         }
     }
@@ -1071,14 +1035,14 @@
     }
 }
 
-fn expand_rust_box(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let resolve = types.resolve(ident);
     let link_prefix = format!("cxxbridge1$box${}$", resolve.to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
     let link_dealloc = format!("{}dealloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
-    let local_prefix = format_ident!("{}__box_", &ident.rust);
+    let local_prefix = format_ident!("{}__box_", ident);
     let local_alloc = format_ident!("{}alloc", local_prefix);
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
@@ -1109,7 +1073,7 @@
     }
 }
 
-fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let resolve = types.resolve(elem);
     let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.to_symbol());
     let link_new = format!("{}new", link_prefix);
@@ -1120,7 +1084,7 @@
     let link_reserve_total = format!("{}reserve_total", link_prefix);
     let link_set_len = format!("{}set_len", link_prefix);
 
-    let local_prefix = format_ident!("{}__vec_", elem.rust);
+    let local_prefix = format_ident!("{}__vec_", elem);
     let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
@@ -1175,12 +1139,8 @@
     }
 }
 
-fn expand_unique_ptr(
-    ident: &NamedType,
-    types: &Types,
-    explicit_impl: Option<&Impl>,
-) -> TokenStream {
-    let name = ident.rust.to_string();
+fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.to_symbol());
     let link_null = format!("{}null", prefix);
@@ -1190,9 +1150,9 @@
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let can_construct_from_value = types.structs.contains_key(&ident.rust)
-        || types.enums.contains_key(&ident.rust)
-        || types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = types.structs.contains_key(ident)
+        || types.enums.contains_key(ident)
+        || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
             fn __new(value: Self) -> *mut ::std::ffi::c_void {
@@ -1261,12 +1221,8 @@
     }
 }
 
-fn expand_shared_ptr(
-    ident: &NamedType,
-    types: &Types,
-    explicit_impl: Option<&Impl>,
-) -> TokenStream {
-    let name = ident.rust.to_string();
+fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.to_symbol());
     let link_null = format!("{}null", prefix);
@@ -1275,9 +1231,9 @@
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let can_construct_from_value = types.structs.contains_key(&ident.rust)
-        || types.enums.contains_key(&ident.rust)
-        || types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = types.structs.contains_key(ident)
+        || types.enums.contains_key(ident)
+        || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
             unsafe fn __new(value: Self, new: *mut ::std::ffi::c_void) {
@@ -1333,8 +1289,8 @@
     }
 }
 
-fn expand_weak_ptr(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
-    let name = ident.rust.to_string();
+fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.to_symbol());
     let link_null = format!("{}null", prefix);
@@ -1390,8 +1346,8 @@
     }
 }
 
-fn expand_cxx_vector(elem: &NamedType, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
-    let name = elem.rust.to_string();
+fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
+    let name = elem.to_string();
     let resolve = types.resolve(elem);
     let prefix = format!("cxxbridge1$std$vector${}$", resolve.to_symbol());
     let link_size = format!("{}size", prefix);
diff --git a/syntax/map.rs b/syntax/map.rs
index f1ea5fc..4873409 100644
--- a/syntax/map.rs
+++ b/syntax/map.rs
@@ -29,6 +29,10 @@
         pub fn iter(&self) -> Iter<K, V> {
             Iter(self.vec.iter())
         }
+
+        pub fn keys(&self) -> impl Iterator<Item = &K> {
+            self.vec.iter().map(|(k, _v)| k)
+        }
     }
 
     impl<K, V> OrderedMap<K, V>
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3a77b82..4298995 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,6 +20,7 @@
 mod pod;
 pub mod qualified;
 pub mod report;
+mod resolve;
 pub mod set;
 pub mod symbol;
 mod tokens;
diff --git a/syntax/resolve.rs b/syntax/resolve.rs
new file mode 100644
index 0000000..5bb1535
--- /dev/null
+++ b/syntax/resolve.rs
@@ -0,0 +1,26 @@
+use crate::syntax::{NamedType, Pair, Types};
+use proc_macro2::Ident;
+
+impl<'a> Types<'a> {
+    pub fn resolve(&self, ident: &impl UnresolvedName) -> &Pair {
+        self.resolutions
+            .get(ident.ident())
+            .expect("Unable to resolve type")
+    }
+}
+
+pub trait UnresolvedName {
+    fn ident(&self) -> &Ident;
+}
+
+impl UnresolvedName for Ident {
+    fn ident(&self) -> &Ident {
+        self
+    }
+}
+
+impl UnresolvedName for NamedType {
+    fn ident(&self) -> &Ident {
+        &self.rust
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 54cd8f0..0eb4293 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,17 +1,15 @@
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::instantiate::ImplKey;
-use crate::syntax::map::UnorderedMap;
+use crate::syntax::map::{OrderedMap, UnorderedMap};
 use crate::syntax::report::Errors;
-use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
+use crate::syntax::set::{OrderedSet, UnorderedSet};
 use crate::syntax::trivial::{self, TrivialReason};
-use crate::syntax::{
-    toposort, Api, Enum, ExternType, Impl, NamedType, Pair, Struct, Type, TypeAlias,
-};
+use crate::syntax::{toposort, Api, Atom, Enum, ExternType, Impl, Pair, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 
 pub struct Types<'a> {
-    pub all: Set<&'a Type>,
+    pub all: OrderedSet<&'a Type>,
     pub structs: UnorderedMap<&'a Ident, &'a Struct>,
     pub enums: UnorderedMap<&'a Ident, &'a Enum>,
     pub cxx: UnorderedSet<&'a Ident>,
@@ -19,7 +17,7 @@
     pub aliases: UnorderedMap<&'a Ident, &'a TypeAlias>,
     pub untrusted: UnorderedMap<&'a Ident, &'a ExternType>,
     pub required_trivial: UnorderedMap<&'a Ident, Vec<TrivialReason<'a>>>,
-    pub explicit_impls: UnorderedMap<ImplKey<'a>, &'a Impl>,
+    pub impls: OrderedMap<ImplKey<'a>, Option<&'a Impl>>,
     pub resolutions: UnorderedMap<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
@@ -27,19 +25,19 @@
 
 impl<'a> Types<'a> {
     pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
-        let mut all = Set::new();
+        let mut all = OrderedSet::new();
         let mut structs = UnorderedMap::new();
         let mut enums = UnorderedMap::new();
         let mut cxx = UnorderedSet::new();
         let mut rust = UnorderedSet::new();
         let mut aliases = UnorderedMap::new();
         let mut untrusted = UnorderedMap::new();
-        let mut explicit_impls = UnorderedMap::new();
+        let mut impls = OrderedMap::new();
         let mut resolutions = UnorderedMap::new();
         let struct_improper_ctypes = UnorderedSet::new();
         let toposorted_structs = Vec::new();
 
-        fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
+        fn visit<'a>(all: &mut OrderedSet<&'a Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
@@ -162,12 +160,32 @@
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
                     if let Some(key) = imp.ty.impl_key() {
-                        explicit_impls.insert(key, imp);
+                        impls.insert(key, Some(imp));
                     }
                 }
             }
         }
 
+        for ty in &all {
+            let impl_key = match ty.impl_key() {
+                Some(impl_key) => impl_key,
+                None => continue,
+            };
+            let implicit_impl = match impl_key {
+                ImplKey::RustBox(ident)
+                | ImplKey::RustVec(ident)
+                | ImplKey::UniquePtr(ident)
+                | ImplKey::SharedPtr(ident)
+                | ImplKey::WeakPtr(ident)
+                | ImplKey::CxxVector(ident) => {
+                    Atom::from(ident).is_none() && !aliases.contains_key(ident)
+                }
+            };
+            if implicit_impl && !impls.contains_key(&impl_key) {
+                impls.insert(impl_key, None);
+            }
+        }
+
         // All these APIs may contain types passed by value. We need to ensure
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
@@ -184,7 +202,7 @@
             aliases,
             untrusted,
             required_trivial,
-            explicit_impls,
+            impls,
             resolutions,
             struct_improper_ctypes,
             toposorted_structs,
@@ -239,12 +257,6 @@
             ImproperCtype::Depends(ident) => self.struct_improper_ctypes.contains(ident),
         }
     }
-
-    pub fn resolve(&self, ident: &NamedType) -> &Pair {
-        self.resolutions
-            .get(&ident.rust)
-            .expect("Unable to resolve type")
-    }
 }
 
 impl<'t, 'a> IntoIterator for &'t Types<'a> {