Skip to content

Commit b7defa4

Browse files
committed
Handle no-export traits which are only implemented once as the implementor
If we have a trait marked no-export, and there's a single implementor, we can just pretend its always the implementor. This makes sense in LDK, for example, for the `APeerManager` trait, which is implemented for all `PeerManager`s, but doesn't make sense in bindings.
1 parent dda9d45 commit b7defa4

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

c-bindings-gen/src/main.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,9 +2200,13 @@ fn walk_private_mod<'a>(ast_storage: &'a FullLibraryAST, orig_crate: &str, modul
22002200
if let Some(trait_path) = i.trait_.as_ref() {
22012201
if let Some(tp) = import_resolver.maybe_resolve_path(&trait_path.1, None) {
22022202
if let Some(sp) = import_resolver.maybe_resolve_path(&p.path, None) {
2203-
match crate_types.trait_impls.entry(sp) {
2204-
hash_map::Entry::Occupied(mut e) => { e.get_mut().push(tp); },
2205-
hash_map::Entry::Vacant(e) => { e.insert(vec![tp]); },
2203+
match crate_types.trait_impls.entry(sp.clone()) {
2204+
hash_map::Entry::Occupied(mut e) => { e.get_mut().push(tp.clone()); },
2205+
hash_map::Entry::Vacant(e) => { e.insert(vec![tp.clone()]); },
2206+
}
2207+
match crate_types.traits_impld.entry(tp) {
2208+
hash_map::Entry::Occupied(mut e) => { e.get_mut().push(sp); },
2209+
hash_map::Entry::Vacant(e) => { e.insert(vec![sp]); },
22062210
}
22072211
}
22082212
}
@@ -2312,9 +2316,13 @@ fn walk_ast_first_pass<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut Cr
23122316
}
23132317
if let Some(tp) = import_resolver.maybe_resolve_path(&trait_path.1, None) {
23142318
if let Some(sp) = import_resolver.maybe_resolve_path(&p.path, None) {
2315-
match crate_types.trait_impls.entry(sp) {
2316-
hash_map::Entry::Occupied(mut e) => { e.get_mut().push(tp); },
2317-
hash_map::Entry::Vacant(e) => { e.insert(vec![tp]); },
2319+
match crate_types.trait_impls.entry(sp.clone()) {
2320+
hash_map::Entry::Occupied(mut e) => { e.get_mut().push(tp.clone()); },
2321+
hash_map::Entry::Vacant(e) => { e.insert(vec![tp.clone()]); },
2322+
}
2323+
match crate_types.traits_impld.entry(tp) {
2324+
hash_map::Entry::Occupied(mut e) => { e.get_mut().push(sp); },
2325+
hash_map::Entry::Vacant(e) => { e.insert(vec![sp]); },
23182326
}
23192327
}
23202328
}

c-bindings-gen/src/types.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,8 @@ pub struct CrateTypes<'a> {
864864
clonable_types: RefCell<HashSet<String>>,
865865
/// Key impls Value
866866
pub trait_impls: HashMap<String, Vec<String>>,
867+
/// Value impls Key
868+
pub traits_impld: HashMap<String, Vec<String>>,
867869
/// The full set of modules in the crate(s)
868870
pub lib_ast: &'a FullLibraryAST,
869871
}
@@ -874,7 +876,8 @@ impl<'a> CrateTypes<'a> {
874876
opaques: HashMap::new(), mirrored_enums: HashMap::new(), traits: HashMap::new(),
875877
type_aliases: HashMap::new(), reverse_alias_map: HashMap::new(),
876878
templates_defined: RefCell::new(HashMap::default()), priv_structs: HashMap::new(),
877-
clonable_types: RefCell::new(initial_clonable_types()), trait_impls: HashMap::new(),
879+
clonable_types: RefCell::new(initial_clonable_types()),
880+
trait_impls: HashMap::new(), traits_impld: HashMap::new(),
878881
template_file: RefCell::new(template_file), lib_ast: &libast,
879882
}
880883
}
@@ -2131,7 +2134,19 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
21312134
if let Some(decl_type) = self.types.maybe_resolve_declared(ident) {
21322135
decl_lookup(w, decl_type, &self.maybe_resolve_ident(ident).unwrap(), is_ref, is_mut);
21332136
} else { unimplemented!(); }
2134-
} else { unimplemented!(); }
2137+
} else {
2138+
if let Some(trait_impls) = self.crate_types.traits_impld.get(&resolved_path) {
2139+
if trait_impls.len() == 1 {
2140+
// If this is a no-export'd crate and there's only one implementation
2141+
// in the whole crate, just treat it as a reference to whatever the
2142+
// implementor is.
2143+
let implementor = self.crate_types.opaques.get(&trait_impls[0]).unwrap();
2144+
decl_lookup(w, &DeclType::StructImported { generics: &implementor.1 }, &trait_impls[0], true, is_mut);
2145+
return;
2146+
}
2147+
}
2148+
unimplemented!();
2149+
}
21352150
},
21362151
syn::Type::Array(a) => {
21372152
if let syn::Type::Path(p) = &*a.elem {
@@ -2969,6 +2984,18 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
29692984
}
29702985
true
29712986
} else {
2987+
if let Some(trait_impls) = self.crate_types.traits_impld.get(&full_path) {
2988+
if trait_impls.len() == 1 {
2989+
// If this is a no-export'd crate and there's only one implementation in the
2990+
// whole crate, just treat it as a reference to whatever the implementor is.
2991+
if with_ref_lifetime {
2992+
write!(w, "&'static crate::{}", trait_impls[0]).unwrap();
2993+
} else {
2994+
write!(w, "&crate::{}", trait_impls[0]).unwrap();
2995+
}
2996+
return true;
2997+
}
2998+
}
29722999
false
29733000
}
29743001
}

0 commit comments

Comments
 (0)