diff --git a/gen/src/write.rs b/gen/src/write.rs index 96592b32b..6679076c6 100644 --- a/gen/src/write.rs +++ b/gen/src/write.rs @@ -3,13 +3,14 @@ use crate::gen::nested::NamespaceEntries; 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 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) { #[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 @@ trait ToMangled { 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 @@ fn write_generic_instantiations(out: &mut OutFile) { 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_box_extern(out: &mut OutFile, ident: &Pair) { ); } -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_vec_extern(out: &mut OutFile, element: &NamedType) { ); } -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 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) { 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 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &NamedType) { 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 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) { // 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 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) { 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 @@ fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) { // 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 @@ fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) { 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 @@ fn write_weak_ptr(out: &mut OutFile, ident: &NamedType) { 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 90b835a4b..40ed5e283 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 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) } } - 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 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 type_id(name: &Pair) -> TokenStream { } } -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_box(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl } } -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 @@ fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl> 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_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl> } } -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 @@ fn expand_unique_ptr( 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_unique_ptr( } } -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 @@ fn expand_shared_ptr( 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_shared_ptr( } } -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_weak_ptr(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl } } -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 f1ea5fc72..4873409d6 100644 --- a/syntax/map.rs +++ b/syntax/map.rs @@ -29,6 +29,10 @@ mod ordered { pub fn iter(&self) -> Iter { Iter(self.vec.iter()) } + + pub fn keys(&self) -> impl Iterator { + self.vec.iter().map(|(k, _v)| k) + } } impl OrderedMap diff --git a/syntax/mod.rs b/syntax/mod.rs index 3a77b82ca..4298995ad 100644 --- a/syntax/mod.rs +++ b/syntax/mod.rs @@ -20,6 +20,7 @@ mod parse; 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 000000000..5bb15357a --- /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 54cd8f05a..0eb4293c7 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 struct Types<'a> { pub aliases: UnorderedMap<&'a Ident, &'a TypeAlias>, pub untrusted: UnorderedMap<&'a Ident, &'a ExternType>, pub required_trivial: UnorderedMap<&'a Ident, Vec>>, - pub explicit_impls: UnorderedMap, &'a Impl>, + pub impls: OrderedMap, 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 @@ pub struct Types<'a> { 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 @@ impl<'a> Types<'a> { 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 @@ impl<'a> Types<'a> { aliases, untrusted, required_trivial, - explicit_impls, + impls, resolutions, struct_improper_ctypes, toposorted_structs, @@ -239,12 +257,6 @@ impl<'a> Types<'a> { 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> {