@@ -56,7 +56,7 @@ fn convert_macro<W: std::io::Write>(w: &mut W, macro_path: &syn::Path, stream: &
5656
5757/// Convert "impl trait_path for for_obj { .. }" for manually-mapped types (ie (de)serialization)
5858fn maybe_convert_trait_impl < W : std:: io:: Write > ( w : & mut W , trait_path : & syn:: Path , for_obj : & syn:: Ident , types : & TypeResolver ) {
59- if let Some ( t) = types. maybe_resolve_path ( & trait_path) {
59+ if let Some ( t) = types. maybe_resolve_path ( & trait_path, None ) {
6060 let s = types. maybe_resolve_ident ( for_obj) . unwrap ( ) ;
6161 if !types. crate_types . opaques . get ( & s) . is_some ( ) { return ; }
6262 match & t as & str {
@@ -97,7 +97,7 @@ macro_rules! walk_supertraits { ($t: expr, $types: expr, ($( $pat: pat => $e: ex
9797 $( $pat => $e, ) *
9898 }
9999 } else {
100- let path = $types. resolve_path( & supertrait. path) ;
100+ let path = $types. resolve_path( & supertrait. path, None ) ;
101101 match ( & path as & str , & supertrait. path. segments. iter( ) . last( ) . unwrap( ) . ident) {
102102 $( $pat => $e, ) *
103103 }
@@ -357,7 +357,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
357357 let mut bounds_iter = t. bounds . iter ( ) ;
358358 match bounds_iter. next ( ) . unwrap ( ) {
359359 syn:: TypeParamBound :: Trait ( tr) => {
360- writeln ! ( w, "\t type {} = crate::{};" , t. ident, types. resolve_path( & tr. path) ) . unwrap ( ) ;
360+ writeln ! ( w, "\t type {} = crate::{};" , t. ident, types. resolve_path( & tr. path, None ) ) . unwrap ( ) ;
361361 } ,
362362 _ => unimplemented ! ( ) ,
363363 }
@@ -397,7 +397,7 @@ fn writeln_opaque<W: std::io::Write>(w: &mut W, ident: &syn::Ident, struct_name:
397397 writeln ! ( w, ";\n " ) . unwrap ( ) ;
398398 writeln ! ( extra_headers, "struct native{}Opaque;\n typedef struct native{}Opaque LDKnative{};" , ident, ident, ident) . unwrap ( ) ;
399399 writeln_docs ( w, & attrs, "" ) ;
400- writeln ! ( w, "#[must_use]\n #[repr(C)]\n pub struct {} {{\n \t /// Nearly everyhwere , inner must be non-null, however in places where" , struct_name) . unwrap ( ) ;
400+ writeln ! ( w, "#[must_use]\n #[repr(C)]\n pub struct {} {{\n \t /// Nearly everywhere , inner must be non-null, however in places where" , struct_name) . unwrap ( ) ;
401401 writeln ! ( w, "\t /// the Rust equivalent takes an Option, it may be set to null to indicate None." ) . unwrap ( ) ;
402402 writeln ! ( w, "\t pub inner: *mut native{},\n \t pub is_owned: bool,\n }}\n " , ident) . unwrap ( ) ;
403403 writeln ! ( w, "impl Drop for {} {{\n \t fn drop(&mut self) {{" , struct_name) . unwrap ( ) ;
@@ -579,7 +579,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
579579 if let Some ( trait_path) = i. trait_ . as_ref ( ) {
580580 if trait_path. 0 . is_some ( ) { unimplemented ! ( ) ; }
581581 if types. understood_c_path ( & trait_path. 1 ) {
582- let full_trait_path = types. resolve_path ( & trait_path. 1 ) ;
582+ let full_trait_path = types. resolve_path ( & trait_path. 1 , None ) ;
583583 let trait_obj = * types. crate_types . traits . get ( & full_trait_path) . unwrap ( ) ;
584584 // We learn the associated types maping from the original trait object.
585585 // That's great, except that they are unresolved idents, so if we learn
@@ -628,7 +628,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
628628 if let syn:: ReturnType :: Type ( _, rtype) = & $m. sig. output {
629629 if let syn:: Type :: Reference ( r) = & * * rtype {
630630 write!( w, "\n \t \t {}{}: " , $indent, $m. sig. ident) . unwrap( ) ;
631- types. write_empty_rust_val( w, & * r. elem) ;
631+ types. write_empty_rust_val( Some ( & gen_types ) , w, & * r. elem) ;
632632 writeln!( w, ",\n {}\t \t set_{}: Some({}_{}_set_{})," , $indent, $m. sig. ident, ident, trait_obj. ident, $m. sig. ident) . unwrap( ) ;
633633 printed = true ;
634634 }
@@ -722,7 +722,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
722722 writeln!( w, "\t // This is a bit race-y in the general case, but for our specific use-cases today, we're safe" ) . unwrap( ) ;
723723 writeln!( w, "\t // Specifically, we must ensure that the first time we're called it can never be in parallel" ) . unwrap( ) ;
724724 write!( w, "\t if " ) . unwrap( ) ;
725- types. write_empty_rust_val_check( w, & * r. elem, & format!( "trait_self_arg.{}" , $m. sig. ident) ) ;
725+ types. write_empty_rust_val_check( Some ( & gen_types ) , w, & * r. elem, & format!( "trait_self_arg.{}" , $m. sig. ident) ) ;
726726 writeln!( w, " {{" ) . unwrap( ) ;
727727 writeln!( w, "\t \t unsafe {{ &mut *(trait_self_arg as *const {} as *mut {}) }}.{} = {}_{}_{}(trait_self_arg.this_arg);" , trait_obj. ident, trait_obj. ident, $m. sig. ident, ident, trait_obj. ident, $m. sig. ident) . unwrap( ) ;
728728 writeln!( w, "\t }}" ) . unwrap( ) ;
@@ -1057,8 +1057,6 @@ struct FullLibraryAST {
10571057/// `out_path` and fills it with wrapper structs/functions to allow calling the things in the AST
10581058/// at `module` from C.
10591059fn convert_file < ' a , ' b > ( libast : & ' a FullLibraryAST , crate_types : & mut CrateTypes < ' a > , in_dir : & str , out_dir : & str , path : & str , orig_crate : & str , module : & str , header_file : & mut File , cpp_header_file : & mut File ) {
1060- eprintln ! ( "Converting {}..." , path) ;
1061-
10621060 let syntax = if let Some ( ast) = libast. files . get ( module) { ast } else { return } ;
10631061
10641062 assert ! ( syntax. shebang. is_none( ) ) ; // Not sure what this is, hope we dont have one
@@ -1096,6 +1094,8 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &mut CrateTypes
10961094 orig_crate, & new_mod, header_file, cpp_header_file) ;
10971095 }
10981096
1097+ eprintln ! ( "Converting {} entries..." , path) ;
1098+
10991099 let mut type_resolver = TypeResolver :: new ( orig_crate, module, crate_types) ;
11001100
11011101 for item in syntax. items . iter ( ) {
@@ -1125,7 +1125,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &mut CrateTypes
11251125 // Re-export any primitive-type constants.
11261126 if let syn:: Visibility :: Public ( _) = c. vis {
11271127 if let syn:: Type :: Path ( p) = & * c. ty {
1128- let resolved_path = type_resolver. resolve_path ( & p. path ) ;
1128+ let resolved_path = type_resolver. resolve_path ( & p. path , None ) ;
11291129 if type_resolver. is_primitive ( & resolved_path) {
11301130 writeln ! ( out, "\n #[no_mangle]" ) . unwrap ( ) ;
11311131 writeln ! ( out, "pub static {}: {} = {}::{}::{};" , c. ident, resolved_path, orig_crate, module, c. ident) . unwrap ( ) ;
@@ -1139,8 +1139,18 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &mut CrateTypes
11391139 ExportStatus :: Export => { } ,
11401140 ExportStatus :: NoExport |ExportStatus :: TestOnly => continue ,
11411141 }
1142- if t. generics . lt_token . is_none ( ) {
1143- writeln_opaque ( & mut out, & t. ident , & format ! ( "{}" , t. ident) , & t. generics , & t. attrs , & type_resolver, header_file, cpp_header_file) ;
1142+
1143+ let mut process_alias = true ;
1144+ for tok in t. generics . params . iter ( ) {
1145+ if let syn:: GenericParam :: Lifetime ( _) = tok { }
1146+ else { process_alias = false ; }
1147+ }
1148+ if process_alias {
1149+ match & * t. ty {
1150+ syn:: Type :: Path ( _) =>
1151+ writeln_opaque ( & mut out, & t. ident , & format ! ( "{}" , t. ident) , & t. generics , & t. attrs , & type_resolver, header_file, cpp_header_file) ,
1152+ _ => { }
1153+ }
11441154 }
11451155 }
11461156 } ,
@@ -1180,6 +1190,52 @@ fn load_ast(in_dir: &str, path: &str, module: String, ast_storage: &mut FullLibr
11801190 ast_storage. files . insert ( module, syntax) ;
11811191}
11821192
1193+ /// Insert ident -> absolute Path resolutions into imports from the given UseTree and path-prefix.
1194+ fn process_use_intern < ' a > ( u : & ' a syn:: UseTree , mut path : syn:: punctuated:: Punctuated < syn:: PathSegment , syn:: token:: Colon2 > , imports : & mut HashMap < & ' a syn:: Ident , syn:: Path > ) {
1195+ match u {
1196+ syn:: UseTree :: Path ( p) => {
1197+ path. push ( syn:: PathSegment { ident : p. ident . clone ( ) , arguments : syn:: PathArguments :: None } ) ;
1198+ process_use_intern ( & p. tree , path, imports) ;
1199+ } ,
1200+ syn:: UseTree :: Name ( n) => {
1201+ path. push ( syn:: PathSegment { ident : n. ident . clone ( ) , arguments : syn:: PathArguments :: None } ) ;
1202+ imports. insert ( & n. ident , syn:: Path { leading_colon : Some ( syn:: Token ![ :: ] ( Span :: call_site ( ) ) ) , segments : path } ) ;
1203+ } ,
1204+ syn:: UseTree :: Group ( g) => {
1205+ for i in g. items . iter ( ) {
1206+ process_use_intern ( i, path. clone ( ) , imports) ;
1207+ }
1208+ } ,
1209+ _ => { }
1210+ }
1211+ }
1212+
1213+ /// Map all the Paths in a Type into absolute paths given a set of imports (generated via process_use_intern)
1214+ fn resolve_imported_refs ( imports : & HashMap < & syn:: Ident , syn:: Path > , mut ty : syn:: Type ) -> syn:: Type {
1215+ match & mut ty {
1216+ syn:: Type :: Path ( p) => {
1217+ if let Some ( ident) = p. path . get_ident ( ) {
1218+ if let Some ( newpath) = imports. get ( ident) {
1219+ p. path = newpath. clone ( ) ;
1220+ }
1221+ } else { unimplemented ! ( ) ; }
1222+ } ,
1223+ syn:: Type :: Reference ( r) => {
1224+ r. elem = Box :: new ( resolve_imported_refs ( imports, ( * r. elem ) . clone ( ) ) ) ;
1225+ } ,
1226+ syn:: Type :: Slice ( s) => {
1227+ s. elem = Box :: new ( resolve_imported_refs ( imports, ( * s. elem ) . clone ( ) ) ) ;
1228+ } ,
1229+ syn:: Type :: Tuple ( t) => {
1230+ for e in t. elems . iter_mut ( ) {
1231+ * e = resolve_imported_refs ( imports, e. clone ( ) ) ;
1232+ }
1233+ } ,
1234+ _ => unimplemented ! ( ) ,
1235+ }
1236+ ty
1237+ }
1238+
11831239/// Walk the FullLibraryAST, deciding how things will be mapped and adding tracking to CrateTypes.
11841240fn walk_ast < ' a > ( in_dir : & str , path : & str , module : String , ast_storage : & ' a FullLibraryAST , crate_types : & mut CrateTypes < ' a > ) {
11851241 let syntax = if let Some ( ast) = ast_storage. files . get ( & module) { ast } else { return } ;
@@ -1189,8 +1245,13 @@ fn walk_ast<'a>(in_dir: &str, path: &str, module: String, ast_storage: &'a FullL
11891245 walk_ast ( in_dir, & path, new_mod, ast_storage, crate_types) ;
11901246 }
11911247
1248+ let mut import_maps = HashMap :: new ( ) ;
1249+
11921250 for item in syntax. items . iter ( ) {
11931251 match item {
1252+ syn:: Item :: Use ( u) => {
1253+ process_use_intern ( & u. tree , syn:: punctuated:: Punctuated :: new ( ) , & mut import_maps) ;
1254+ } ,
11941255 syn:: Item :: Struct ( s) => {
11951256 if let syn:: Visibility :: Public ( _) = s. vis {
11961257 match export_status ( & s. attrs ) {
@@ -1211,6 +1272,31 @@ fn walk_ast<'a>(in_dir: &str, path: &str, module: String, ast_storage: &'a FullL
12111272 crate_types. traits . insert ( trait_path, & t) ;
12121273 }
12131274 } ,
1275+ syn:: Item :: Type ( t) => {
1276+ if let syn:: Visibility :: Public ( _) = t. vis {
1277+ match export_status ( & t. attrs ) {
1278+ ExportStatus :: Export => { } ,
1279+ ExportStatus :: NoExport |ExportStatus :: TestOnly => continue ,
1280+ }
1281+ let type_path = format ! ( "{}::{}" , module, t. ident) ;
1282+ let mut process_alias = true ;
1283+ for tok in t. generics . params . iter ( ) {
1284+ if let syn:: GenericParam :: Lifetime ( _) = tok { }
1285+ else { process_alias = false ; }
1286+ }
1287+ if process_alias {
1288+ match & * t. ty {
1289+ syn:: Type :: Path ( _) => {
1290+ // If its a path with no generics, assume we don't map the aliased type and map it opaque
1291+ crate_types. opaques . insert ( type_path, & t. ident ) ;
1292+ } ,
1293+ _ => {
1294+ crate_types. type_aliases . insert ( type_path, resolve_imported_refs ( & import_maps, ( * t. ty ) . clone ( ) ) ) ;
1295+ }
1296+ }
1297+ }
1298+ }
1299+ } ,
12141300 syn:: Item :: Enum ( e) if is_enum_opaque ( e) => {
12151301 if let syn:: Visibility :: Public ( _) = e. vis {
12161302 match export_status ( & e. attrs ) {
@@ -1264,7 +1350,7 @@ fn main() {
12641350 // ...then walk the ASTs tracking what types we will map, and how, so that we can resolve them
12651351 // when parsing other file ASTs...
12661352 let mut libtypes = CrateTypes { traits : HashMap :: new ( ) , opaques : HashMap :: new ( ) , mirrored_enums : HashMap :: new ( ) ,
1267- templates_defined : HashMap :: new ( ) , template_file : & mut derived_templates } ;
1353+ type_aliases : HashMap :: new ( ) , templates_defined : HashMap :: default ( ) , template_file : & mut derived_templates } ;
12681354 walk_ast ( & args[ 1 ] , "/lib.rs" , "" . to_string ( ) , & libast, & mut libtypes) ;
12691355
12701356 // ... finally, do the actual file conversion/mapping, writing out types as we go.
0 commit comments