@@ -56,7 +56,7 @@ fn convert_macro<W: std::io::Write>(w: &mut W, macro_path: &syn::Path, stream: &
56
56
57
57
/// Convert "impl trait_path for for_obj { .. }" for manually-mapped types (ie (de)serialization)
58
58
fn 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 ) {
60
60
let s = types. maybe_resolve_ident ( for_obj) . unwrap ( ) ;
61
61
if !types. crate_types . opaques . get ( & s) . is_some ( ) { return ; }
62
62
match & t as & str {
@@ -97,7 +97,7 @@ macro_rules! walk_supertraits { ($t: expr, $types: expr, ($( $pat: pat => $e: ex
97
97
$( $pat => $e, ) *
98
98
}
99
99
} else {
100
- let path = $types. resolve_path( & supertrait. path) ;
100
+ let path = $types. resolve_path( & supertrait. path, None ) ;
101
101
match ( & path as & str , & supertrait. path. segments. iter( ) . last( ) . unwrap( ) . ident) {
102
102
$( $pat => $e, ) *
103
103
}
@@ -357,7 +357,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
357
357
let mut bounds_iter = t. bounds . iter ( ) ;
358
358
match bounds_iter. next ( ) . unwrap ( ) {
359
359
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 ( ) ;
361
361
} ,
362
362
_ => unimplemented ! ( ) ,
363
363
}
@@ -397,7 +397,7 @@ fn writeln_opaque<W: std::io::Write>(w: &mut W, ident: &syn::Ident, struct_name:
397
397
writeln ! ( w, ";\n " ) . unwrap ( ) ;
398
398
writeln ! ( extra_headers, "struct native{}Opaque;\n typedef struct native{}Opaque LDKnative{};" , ident, ident, ident) . unwrap ( ) ;
399
399
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 ( ) ;
401
401
writeln ! ( w, "\t /// the Rust equivalent takes an Option, it may be set to null to indicate None." ) . unwrap ( ) ;
402
402
writeln ! ( w, "\t pub inner: *mut native{},\n \t pub is_owned: bool,\n }}\n " , ident) . unwrap ( ) ;
403
403
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
579
579
if let Some ( trait_path) = i. trait_ . as_ref ( ) {
580
580
if trait_path. 0 . is_some ( ) { unimplemented ! ( ) ; }
581
581
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 ) ;
583
583
let trait_obj = * types. crate_types . traits . get ( & full_trait_path) . unwrap ( ) ;
584
584
// We learn the associated types maping from the original trait object.
585
585
// 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
628
628
if let syn:: ReturnType :: Type ( _, rtype) = & $m. sig. output {
629
629
if let syn:: Type :: Reference ( r) = & * * rtype {
630
630
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) ;
632
632
writeln!( w, ",\n {}\t \t set_{}: Some({}_{}_set_{})," , $indent, $m. sig. ident, ident, trait_obj. ident, $m. sig. ident) . unwrap( ) ;
633
633
printed = true ;
634
634
}
@@ -722,7 +722,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
722
722
writeln!( w, "\t // This is a bit race-y in the general case, but for our specific use-cases today, we're safe" ) . unwrap( ) ;
723
723
writeln!( w, "\t // Specifically, we must ensure that the first time we're called it can never be in parallel" ) . unwrap( ) ;
724
724
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) ) ;
726
726
writeln!( w, " {{" ) . unwrap( ) ;
727
727
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( ) ;
728
728
writeln!( w, "\t }}" ) . unwrap( ) ;
@@ -1057,8 +1057,6 @@ struct FullLibraryAST {
1057
1057
/// `out_path` and fills it with wrapper structs/functions to allow calling the things in the AST
1058
1058
/// at `module` from C.
1059
1059
fn 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
-
1062
1060
let syntax = if let Some ( ast) = libast. files . get ( module) { ast } else { return } ;
1063
1061
1064
1062
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
1096
1094
orig_crate, & new_mod, header_file, cpp_header_file) ;
1097
1095
}
1098
1096
1097
+ eprintln ! ( "Converting {} entries..." , path) ;
1098
+
1099
1099
let mut type_resolver = TypeResolver :: new ( orig_crate, module, crate_types) ;
1100
1100
1101
1101
for item in syntax. items . iter ( ) {
@@ -1125,7 +1125,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &mut CrateTypes
1125
1125
// Re-export any primitive-type constants.
1126
1126
if let syn:: Visibility :: Public ( _) = c. vis {
1127
1127
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 ) ;
1129
1129
if type_resolver. is_primitive ( & resolved_path) {
1130
1130
writeln ! ( out, "\n #[no_mangle]" ) . unwrap ( ) ;
1131
1131
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
1139
1139
ExportStatus :: Export => { } ,
1140
1140
ExportStatus :: NoExport |ExportStatus :: TestOnly => continue ,
1141
1141
}
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
+ }
1144
1154
}
1145
1155
}
1146
1156
} ,
@@ -1180,6 +1190,52 @@ fn load_ast(in_dir: &str, path: &str, module: String, ast_storage: &mut FullLibr
1180
1190
ast_storage. files . insert ( module, syntax) ;
1181
1191
}
1182
1192
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
+
1183
1239
/// Walk the FullLibraryAST, deciding how things will be mapped and adding tracking to CrateTypes.
1184
1240
fn walk_ast < ' a > ( in_dir : & str , path : & str , module : String , ast_storage : & ' a FullLibraryAST , crate_types : & mut CrateTypes < ' a > ) {
1185
1241
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
1189
1245
walk_ast ( in_dir, & path, new_mod, ast_storage, crate_types) ;
1190
1246
}
1191
1247
1248
+ let mut import_maps = HashMap :: new ( ) ;
1249
+
1192
1250
for item in syntax. items . iter ( ) {
1193
1251
match item {
1252
+ syn:: Item :: Use ( u) => {
1253
+ process_use_intern ( & u. tree , syn:: punctuated:: Punctuated :: new ( ) , & mut import_maps) ;
1254
+ } ,
1194
1255
syn:: Item :: Struct ( s) => {
1195
1256
if let syn:: Visibility :: Public ( _) = s. vis {
1196
1257
match export_status ( & s. attrs ) {
@@ -1211,6 +1272,31 @@ fn walk_ast<'a>(in_dir: &str, path: &str, module: String, ast_storage: &'a FullL
1211
1272
crate_types. traits . insert ( trait_path, & t) ;
1212
1273
}
1213
1274
} ,
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
+ } ,
1214
1300
syn:: Item :: Enum ( e) if is_enum_opaque ( e) => {
1215
1301
if let syn:: Visibility :: Public ( _) = e. vis {
1216
1302
match export_status ( & e. attrs ) {
@@ -1264,7 +1350,7 @@ fn main() {
1264
1350
// ...then walk the ASTs tracking what types we will map, and how, so that we can resolve them
1265
1351
// when parsing other file ASTs...
1266
1352
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 } ;
1268
1354
walk_ast ( & args[ 1 ] , "/lib.rs" , "" . to_string ( ) , & libast, & mut libtypes) ;
1269
1355
1270
1356
// ... finally, do the actual file conversion/mapping, writing out types as we go.
0 commit comments