Skip to content

Commit 3fafbe3

Browse files
authored
Merge pull request #73 from TheBlueMatt/main
Handle impl blocks outside of the mod of the being-implemented object
2 parents 8b697a6 + cac55d2 commit 3fafbe3

24 files changed

+1696
-415
lines changed

c-bindings-gen/src/main.rs

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ use crate::c_types::*;
4343
use alloc::{vec::Vec, boxed::Box};
4444
";
4545

46+
47+
/// str.rsplit_once but with an older MSRV
48+
fn rsplit_once<'a>(inp: &'a str, pattern: &str) -> Option<(&'a str, &'a str)> {
49+
let mut iter = inp.rsplitn(2, pattern);
50+
let second_entry = iter.next().unwrap();
51+
Some((iter.next().unwrap(), second_entry))
52+
}
53+
4654
// *************************************
4755
// *** Manually-expanded conversions ***
4856
// *************************************
@@ -54,11 +62,10 @@ fn maybe_convert_trait_impl<W: std::io::Write>(w: &mut W, trait_path: &syn::Path
5462
let full_obj_path;
5563
let mut has_inner = false;
5664
if let syn::Type::Path(ref p) = for_ty {
57-
if let Some(ident) = single_ident_generic_path_to_ident(&p.path) {
58-
for_obj = format!("{}", ident);
59-
full_obj_path = for_obj.clone();
60-
has_inner = types.c_type_has_inner_from_path(&types.resolve_path(&p.path, Some(generics)));
61-
} else { return; }
65+
let resolved_path = types.resolve_path(&p.path, Some(generics));
66+
for_obj = format!("{}", p.path.segments.last().unwrap().ident);
67+
full_obj_path = format!("crate::{}", resolved_path);
68+
has_inner = types.c_type_has_inner_from_path(&resolved_path);
6269
} else {
6370
// We assume that anything that isn't a Path is somehow a generic that ends up in our
6471
// derived-types module.
@@ -872,8 +879,12 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
872879
}
873880
if let &syn::Type::Path(ref p) = &*i.self_ty {
874881
if p.qself.is_some() { unimplemented!(); }
875-
if let Some(ident) = single_ident_generic_path_to_ident(&p.path) {
876-
if let Some(resolved_path) = types.maybe_resolve_non_ignored_ident(&ident) {
882+
let ident = &p.path.segments.last().unwrap().ident;
883+
if let Some(resolved_path) = types.maybe_resolve_path(&p.path, None) {
884+
if types.crate_types.opaques.contains_key(&resolved_path) || types.crate_types.mirrored_enums.contains_key(&resolved_path) ||
885+
// At least for core::infallible::Infallible we need to support mapping an
886+
// out-of-crate trait implementation.
887+
(types.understood_c_path(&p.path) && first_seg_is_stdlib(resolved_path.split("::").next().unwrap())) {
877888
if !types.understood_c_path(&p.path) {
878889
eprintln!("Not implementing anything for impl {} as the type is not understood (probably C-not exported)", ident);
879890
return;
@@ -1300,7 +1311,8 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
13001311
maybe_convert_trait_impl(w, &trait_path.1, &*i.self_ty, types, &gen_types);
13011312
}
13021313
} else {
1303-
let declared_type = (*types.get_declared_type(&ident).unwrap()).clone();
1314+
let is_opaque = types.crate_types.opaques.contains_key(&resolved_path);
1315+
let is_mirrored_enum = types.crate_types.mirrored_enums.contains_key(&resolved_path);
13041316
for item in i.items.iter() {
13051317
match item {
13061318
syn::ImplItem::Method(m) => {
@@ -1318,11 +1330,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
13181330
writeln!(w, "#[must_use]").unwrap();
13191331
}
13201332
write!(w, "#[no_mangle]\npub extern \"C\" fn {}_{}(", ident, m.sig.ident).unwrap();
1321-
let ret_type = match &declared_type {
1322-
DeclType::MirroredEnum => format!("{}", ident),
1323-
DeclType::StructImported {..} => format!("{}", ident),
1324-
_ => unimplemented!(),
1325-
};
1333+
let ret_type = format!("crate::{}", resolved_path);
13261334
write_method_params(w, &m.sig, &ret_type, types, Some(&meth_gen_types), false, true);
13271335
write!(w, " {{\n\t").unwrap();
13281336
write_method_var_decl_body(w, &m.sig, "", types, Some(&meth_gen_types), false);
@@ -1339,18 +1347,18 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
13391347
if !takes_mut_self && !takes_self {
13401348
write!(w, "{}::{}(", resolved_path, m.sig.ident).unwrap();
13411349
} else {
1342-
match &declared_type {
1343-
DeclType::MirroredEnum => write!(w, "this_arg.to_native().{}(", m.sig.ident).unwrap(),
1344-
DeclType::StructImported {..} => {
1345-
if takes_owned_self {
1346-
write!(w, "(*unsafe {{ Box::from_raw(this_arg.take_inner()) }}).{}(", m.sig.ident).unwrap();
1347-
} else if takes_mut_self {
1348-
write!(w, "unsafe {{ &mut (*ObjOps::untweak_ptr(this_arg.inner as *mut native{})) }}.{}(", ident, m.sig.ident).unwrap();
1349-
} else {
1350-
write!(w, "unsafe {{ &*ObjOps::untweak_ptr(this_arg.inner) }}.{}(", m.sig.ident).unwrap();
1351-
}
1352-
},
1353-
_ => unimplemented!(),
1350+
if is_mirrored_enum {
1351+
write!(w, "this_arg.to_native().{}(", m.sig.ident).unwrap();
1352+
} else if is_opaque {
1353+
if takes_owned_self {
1354+
write!(w, "(*unsafe {{ Box::from_raw(this_arg.take_inner()) }}).{}(", m.sig.ident).unwrap();
1355+
} else if takes_mut_self {
1356+
write!(w, "unsafe {{ &mut (*ObjOps::untweak_ptr(this_arg.inner as *mut crate::{}::native{})) }}.{}(", rsplit_once(&resolved_path, "::").unwrap().0, ident, m.sig.ident).unwrap();
1357+
} else {
1358+
write!(w, "unsafe {{ &*ObjOps::untweak_ptr(this_arg.inner) }}.{}(", m.sig.ident).unwrap();
1359+
}
1360+
} else {
1361+
unimplemented!();
13541362
}
13551363
}
13561364
write_method_call_params(w, &m.sig, "", types, Some(&meth_gen_types), &ret_type, false);
@@ -1367,11 +1375,18 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
13671375
if !gen_types.as_mut().unwrap().learn_generics(&i.generics, types) {
13681376
gen_types = None;
13691377
}
1370-
'alias_impls: for (alias, arguments) in aliases {
1378+
let alias_module = rsplit_once(&resolved_path, "::").unwrap().0;
1379+
1380+
'alias_impls: for (alias_resolved, arguments) in aliases {
13711381
let mut new_ty_generics = Vec::new();
13721382
let mut need_generics = false;
13731383

1374-
let alias_resolved = types.resolve_path(&alias, None);
1384+
let alias_resolver_override;
1385+
let alias_resolver = if alias_module != types.module_path {
1386+
alias_resolver_override = ImportResolver::new(types.types.crate_name, &types.crate_types.lib_ast.dependencies,
1387+
alias_module, &types.crate_types.lib_ast.modules.get(alias_module).unwrap().items);
1388+
&alias_resolver_override
1389+
} else { &types.types };/*.maybe_resolve_path(&alias, None).unwrap();*/
13751390
for (idx, gen) in i.generics.params.iter().enumerate() {
13761391
match gen {
13771392
syn::GenericParam::Type(type_param) => {
@@ -1380,10 +1395,11 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
13801395
if let syn::PathArguments::AngleBracketed(ref t) = &arguments {
13811396
assert!(idx < t.args.len());
13821397
if let syn::GenericArgument::Type(syn::Type::Path(p)) = &t.args[idx] {
1383-
if let Some(generic_arg) = types.maybe_resolve_path(&p.path, None) {
1398+
if let Some(generic_arg) = alias_resolver.maybe_resolve_path(&p.path, None) {
13841399

13851400
new_ty_generics.push((type_param.ident.clone(), syn::Type::Path(p.clone())));
1386-
let generic_bound = types.resolve_path(&trait_bound.path, None);
1401+
let generic_bound = types.maybe_resolve_path(&trait_bound.path, None)
1402+
.unwrap_or_else(|| format!("{}::{}", types.module_path, single_ident_generic_path_to_ident(&trait_bound.path).unwrap()));
13871403
if let Some(traits_impld) = types.crate_types.trait_impls.get(&generic_arg) {
13881404
for trait_impld in traits_impld {
13891405
if *trait_impld == generic_bound { continue 'bounds_check; }
@@ -1411,6 +1427,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
14111427
}
14121428
}
14131429
let mut params = syn::punctuated::Punctuated::new();
1430+
let alias = string_path_to_syn_path(&alias_resolved);
14141431
let real_aliased =
14151432
if need_generics {
14161433
let alias_generics = types.crate_types.opaques.get(&alias_resolved).unwrap().1;
@@ -1776,11 +1793,7 @@ fn convert_priv_mod<'a, 'b: 'a, W: std::io::Write>(w: &mut W, libast: &'b FullLi
17761793
match item {
17771794
syn::Item::Mod(m) => convert_priv_mod(w, libast, crate_types, out_dir, &format!("{}::{}", mod_path, module.ident), m),
17781795
syn::Item::Impl(i) => {
1779-
if let &syn::Type::Path(ref p) = &*i.self_ty {
1780-
if p.path.get_ident().is_some() {
1781-
writeln_impl(w, i, &mut types);
1782-
}
1783-
}
1796+
writeln_impl(w, i, &mut types);
17841797
},
17851798
_ => {},
17861799
}
@@ -2022,17 +2035,14 @@ fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a
20222035
let type_path = format!("{}::{}", module, t.ident);
20232036
match &*t.ty {
20242037
syn::Type::Path(p) => {
2025-
let t_ident = &t.ident;
2026-
20272038
// If its a path with no generics, assume we don't map the aliased type and map it opaque
2028-
let path_obj = parse_quote!(#t_ident);
20292039
let args_obj = p.path.segments.last().unwrap().arguments.clone();
20302040
match crate_types.reverse_alias_map.entry(import_resolver.maybe_resolve_path(&p.path, None).unwrap()) {
2031-
hash_map::Entry::Occupied(mut e) => { e.get_mut().push((path_obj, args_obj)); },
2032-
hash_map::Entry::Vacant(e) => { e.insert(vec![(path_obj, args_obj)]); },
2041+
hash_map::Entry::Occupied(mut e) => { e.get_mut().push((type_path.clone(), args_obj)); },
2042+
hash_map::Entry::Vacant(e) => { e.insert(vec![(type_path.clone(), args_obj)]); },
20332043
}
20342044

2035-
crate_types.opaques.insert(type_path, (t_ident, &t.generics));
2045+
crate_types.opaques.insert(type_path, (&t.ident, &t.generics));
20362046
},
20372047
_ => {
20382048
crate_types.type_aliases.insert(type_path, import_resolver.resolve_imported_refs((*t.ty).clone()));

c-bindings-gen/src/types.rs

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ pub fn path_matches_nongeneric(p: &syn::Path, exp: &[&str]) -> bool {
6565
true
6666
}
6767

68+
pub fn string_path_to_syn_path(path: &str) -> syn::Path {
69+
let mut segments = syn::punctuated::Punctuated::new();
70+
for seg in path.split("::") {
71+
segments.push(syn::PathSegment {
72+
ident: syn::Ident::new(seg, Span::call_site()),
73+
arguments: syn::PathArguments::None,
74+
});
75+
}
76+
syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments }
77+
}
78+
6879
#[derive(Debug, PartialEq)]
6980
pub enum ExportStatus {
7081
Export,
@@ -391,7 +402,7 @@ pub enum DeclType<'a> {
391402
}
392403

393404
pub struct ImportResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> {
394-
crate_name: &'mod_lifetime str,
405+
pub crate_name: &'mod_lifetime str,
395406
dependencies: &'mod_lifetime HashSet<syn::Ident>,
396407
module_path: &'mod_lifetime str,
397408
imports: HashMap<syn::Ident, (String, syn::Path)>,
@@ -546,10 +557,6 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr
546557
Self { crate_name, dependencies, module_path, imports, declared, priv_modules }
547558
}
548559

549-
pub fn get_declared_type(&self, ident: &syn::Ident) -> Option<&DeclType<'crate_lft>> {
550-
self.declared.get(ident)
551-
}
552-
553560
pub fn maybe_resolve_declared(&self, id: &syn::Ident) -> Option<&DeclType<'crate_lft>> {
554561
self.declared.get(id)
555562
}
@@ -562,17 +569,6 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr
562569
} else { None }
563570
}
564571

565-
pub fn maybe_resolve_non_ignored_ident(&self, id: &syn::Ident) -> Option<String> {
566-
if let Some((imp, _)) = self.imports.get(id) {
567-
Some(imp.clone())
568-
} else if let Some(decl_type) = self.declared.get(id) {
569-
match decl_type {
570-
DeclType::StructIgnored => None,
571-
_ => Some(self.module_path.to_string() + "::" + &format!("{}", id)),
572-
}
573-
} else { None }
574-
}
575-
576572
pub fn maybe_resolve_path(&self, p: &syn::Path, generics: Option<&GenericTypes>) -> Option<String> {
577573
if let Some(gen_types) = generics {
578574
if let Some(resp) = gen_types.maybe_resolve_path(p) {
@@ -741,7 +737,7 @@ pub struct CrateTypes<'a> {
741737
/// Aliases from paths to some other Type
742738
pub type_aliases: HashMap<String, syn::Type>,
743739
/// Value is an alias to Key (maybe with some generics)
744-
pub reverse_alias_map: HashMap<String, Vec<(syn::Path, syn::PathArguments)>>,
740+
pub reverse_alias_map: HashMap<String, Vec<(String, syn::PathArguments)>>,
745741
/// Template continer types defined, map from mangled type name -> whether a destructor fn
746742
/// exists.
747743
///
@@ -785,7 +781,7 @@ impl<'a> CrateTypes<'a> {
785781
pub struct TypeResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> {
786782
pub module_path: &'mod_lifetime str,
787783
pub crate_types: &'mod_lifetime CrateTypes<'crate_lft>,
788-
types: ImportResolver<'mod_lifetime, 'crate_lft>,
784+
pub types: ImportResolver<'mod_lifetime, 'crate_lft>,
789785
}
790786

791787
/// Returned by write_empty_rust_val_check_suffix to indicate what type of dereferencing needs to
@@ -1583,9 +1579,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
15831579
// *** Type definition during main.rs processing ***
15841580
// *************************************************
15851581

1586-
pub fn get_declared_type(&'a self, ident: &syn::Ident) -> Option<&'a DeclType<'c>> {
1587-
self.types.get_declared_type(ident)
1588-
}
15891582
/// Returns true if the object at the given path is mapped as X { inner: *mut origX, .. }.
15901583
pub fn c_type_has_inner_from_path(&self, full_path: &str) -> bool {
15911584
self.crate_types.opaques.get(full_path).is_some()
@@ -1610,10 +1603,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
16101603
self.types.maybe_resolve_ident(id)
16111604
}
16121605

1613-
pub fn maybe_resolve_non_ignored_ident(&self, id: &syn::Ident) -> Option<String> {
1614-
self.types.maybe_resolve_non_ignored_ident(id)
1615-
}
1616-
16171606
pub fn maybe_resolve_path(&self, p_arg: &syn::Path, generics: Option<&GenericTypes>) -> Option<String> {
16181607
self.types.maybe_resolve_path(p_arg, generics)
16191608
}
@@ -2874,7 +2863,6 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
28742863
assert!(self.write_c_type_intern(w, t, generics, false, false, ptr_for_ref, true, false));
28752864
}
28762865
pub fn understood_c_path(&self, p: &syn::Path) -> bool {
2877-
if p.leading_colon.is_some() { return false; }
28782866
self.write_c_path_intern(&mut std::io::sink(), p, None, false, false, false, false, true)
28792867
}
28802868
pub fn understood_c_type(&self, t: &syn::Type, generics: Option<&GenericTypes>) -> bool {

0 commit comments

Comments
 (0)