X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=c-bindings-gen%2Fsrc%2Fmain.rs;h=f8e5b48492fd3944ca4775b7d593025f8ee79f0c;hb=b49781e8d81dc400033c1ea6660f06eda9a87347;hp=f8475bbdcf958ce40f90d57c16e0c3cbb6e3d41d;hpb=be74b366d2af242d688f8ce567d49b7c19813c26;p=rust-lightning diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index f8475bbdc..f8e5b4849 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -517,7 +517,6 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty writeln!(w, "\t\t}}\n\t}}\n}}").unwrap(); write_cpp_wrapper(cpp_headers, &trait_name, true); - types.trait_declared(&t.ident, t); } /// Write out a simple "opaque" type (eg structs) which contain a pointer to the native Rust type @@ -557,26 +556,11 @@ fn writeln_opaque(w: &mut W, ident: &syn::Ident, struct_name: write_cpp_wrapper(cpp_headers, &format!("{}", ident), true); } -fn declare_struct<'a, 'b>(s: &'a syn::ItemStruct, types: &mut TypeResolver<'b, 'a>) -> bool { - let export = export_status(&s.attrs); - match export { - ExportStatus::Export => {}, - ExportStatus::TestOnly => return false, - ExportStatus::NoExport => { - types.struct_ignored(&s.ident); - return false; - } - } - - types.struct_imported(&s.ident); - true -} - /// Writes out all the relevant mappings for a Rust struct, deferring to writeln_opaque to generate /// the struct itself, and then writing getters and setters for public, understood-type fields and /// a constructor if every field is public. fn writeln_struct<'a, 'b, W: std::io::Write>(w: &mut W, s: &'a syn::ItemStruct, types: &mut TypeResolver<'b, 'a>, extra_headers: &mut File, cpp_headers: &mut File) { - if !declare_struct(s, types) { return; } + if export_status(&s.attrs) != ExportStatus::Export { return; } let struct_name = &format!("{}", s.ident); writeln_opaque(w, &s.ident, struct_name, &s.generics, &s.attrs, types, extra_headers, cpp_headers); @@ -998,37 +982,6 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ } } -/// Returns true if the enum will be mapped as an opaue (ie struct with a pointer to the underlying -/// type), otherwise it is mapped into a transparent, C-compatible version of itself. -fn is_enum_opaque(e: &syn::ItemEnum) -> bool { - for var in e.variants.iter() { - if let syn::Fields::Unit = var.fields { - } else if let syn::Fields::Named(fields) = &var.fields { - for field in fields.named.iter() { - match export_status(&field.attrs) { - ExportStatus::Export|ExportStatus::TestOnly => {}, - ExportStatus::NoExport => return true, - } - } - } else { - return true; - } - } - false -} - -fn declare_enum<'a, 'b>(e: &'a syn::ItemEnum, types: &mut TypeResolver<'b, 'a>) { - match export_status(&e.attrs) { - ExportStatus::Export => {}, - ExportStatus::NoExport|ExportStatus::TestOnly => return, - } - - if is_enum_opaque(e) { - types.enum_ignored(&e.ident); - } else { - types.mirrored_enum_declared(&e.ident); - } -} /// Print a mapping of an enum. If all of the enum's fields are C-mapped in some form (or the enum /// is unitary), we generate an equivalent enum with all types replaced with their C mapped @@ -1212,9 +1165,12 @@ impl FullLibraryAST { }; self.load_module(modname, m.attrs, m.content.unwrap().1); submods.push(modident); + } else { + non_mod_items.push(syn::Item::Mod(m)); } } }, + syn::Item::Mod(_) => panic!("--pretty=expanded output should never have non-body modules"), _ => { non_mod_items.push(item); } } } @@ -1274,25 +1230,8 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &mut CrateTypes eprintln!("Converting {} entries...", module); - let mut type_resolver = TypeResolver::new(orig_crate, module, crate_types); - - // First pass over the items and fill in imports and file-declared objects in the type resolver - for item in items.iter() { - match item { - syn::Item::Use(u) => type_resolver.process_use(&mut out, &u), - syn::Item::Struct(s) => { - if let syn::Visibility::Public(_) = s.vis { - declare_struct(&s, &mut type_resolver); - } - }, - syn::Item::Enum(e) => { - if let syn::Visibility::Public(_) = e.vis { - declare_enum(&e, &mut type_resolver); - } - }, - _ => {}, - } - } + let import_resolver = ImportResolver::new(module, items); + let mut type_resolver = TypeResolver::new(orig_crate, module, import_resolver, crate_types); for item in items.iter() { match item { @@ -1370,64 +1309,15 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &mut CrateTypes } } -/// Insert ident -> absolute Path resolutions into imports from the given UseTree and path-prefix. -fn process_use_intern<'a>(u: &'a syn::UseTree, mut path: syn::punctuated::Punctuated, imports: &mut HashMap<&'a syn::Ident, syn::Path>) { - match u { - syn::UseTree::Path(p) => { - path.push(syn::PathSegment { ident: p.ident.clone(), arguments: syn::PathArguments::None }); - process_use_intern(&p.tree, path, imports); - }, - syn::UseTree::Name(n) => { - path.push(syn::PathSegment { ident: n.ident.clone(), arguments: syn::PathArguments::None }); - imports.insert(&n.ident, syn::Path { leading_colon: Some(syn::Token![::](Span::call_site())), segments: path }); - }, - syn::UseTree::Group(g) => { - for i in g.items.iter() { - process_use_intern(i, path.clone(), imports); - } - }, - _ => {} - } -} - -/// Map all the Paths in a Type into absolute paths given a set of imports (generated via process_use_intern) -fn resolve_imported_refs(imports: &HashMap<&syn::Ident, syn::Path>, mut ty: syn::Type) -> syn::Type { - match &mut ty { - syn::Type::Path(p) => { - if let Some(ident) = p.path.get_ident() { - if let Some(newpath) = imports.get(ident) { - p.path = newpath.clone(); - } - } else { unimplemented!(); } - }, - syn::Type::Reference(r) => { - r.elem = Box::new(resolve_imported_refs(imports, (*r.elem).clone())); - }, - syn::Type::Slice(s) => { - s.elem = Box::new(resolve_imported_refs(imports, (*s.elem).clone())); - }, - syn::Type::Tuple(t) => { - for e in t.elems.iter_mut() { - *e = resolve_imported_refs(imports, e.clone()); - } - }, - _ => unimplemented!(), - } - ty -} - /// Walk the FullLibraryAST, deciding how things will be mapped and adding tracking to CrateTypes. fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a>) { for (module, astmod) in ast_storage.modules.iter() { let ASTModule { ref attrs, ref items, submods: _ } = astmod; assert_eq!(export_status(&attrs), ExportStatus::Export); - let mut import_maps = HashMap::new(); + let import_resolver = ImportResolver::new(module, items); for item in items.iter() { match item { - syn::Item::Use(u) => { - process_use_intern(&u.tree, syn::punctuated::Punctuated::new(), &mut import_maps); - }, syn::Item::Struct(s) => { if let syn::Visibility::Public(_) = s.vis { match export_status(&s.attrs) { @@ -1473,7 +1363,7 @@ fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a crate_types.opaques.insert(type_path, &t.ident); }, _ => { - crate_types.type_aliases.insert(type_path, resolve_imported_refs(&import_maps, (*t.ty).clone())); + crate_types.type_aliases.insert(type_path, import_resolver.resolve_imported_refs((*t.ty).clone())); } } } @@ -1503,11 +1393,9 @@ fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a if let &syn::Type::Path(ref p) = &*i.self_ty { if let Some(trait_path) = i.trait_.as_ref() { if path_matches_nongeneric(&trait_path.1, &["core", "clone", "Clone"]) { - // Note, we should probably have more full-featured type resolution here, - // but for now we don't have any cases where we impl X for A::B. - let ident = single_ident_generic_path_to_ident(&p.path).expect("impl X for A::B currently unsupported"); - assert!(import_maps.get(&ident).is_none()); - crate_types.clonable_types.insert(format!("crate::{}::{}", module, ident)); + if let Some(full_path) = import_resolver.maybe_resolve_path(&p.path, None) { + crate_types.clonable_types.insert("crate::".to_owned() + &full_path); + } } } }